我一直在尝试用VHDL代码编写一个有限状态机,用于在Altera DE1板上实现的简单16位处理器。在有限状态机中,我有一个CASE
语句,用于处理不同的16位指令,这些指令由16位STD_LOGIC_VECTOR引入FSM。但是,我在有限状态机解码指令的解码状态下遇到了一些麻烦。其中一条指令是ADD,它将两个寄存器作为操作数,第三个作为目标寄存器。但是,我还有一个ADD指令,它将寄存器和5位立即数作为操作数,并将第二个寄存器作为目标。我的问题是在CASE
语句中,我需要能够区分两种不同的ADD指令。所以,我认为如果我在CASE
语句中使用“ - ”或“X”之类的通配符值,我只能用两种情况区分两者,而不是列出所有可能的寄存器/立即数价值组合。例如:
CASE IR IS --(IR stands for "Instruction Register")
WHEN "0001------0-----" => (Go to 3-register add);
WHEN "0001------1-----" => (Go to 2-register/immediate value add);
WHEN OTHERS => (Do whatever);
END CASE;
这些不是我所拥有的唯一两条指令,我只是将这两条指令缩短了一点。当我编译并运行此代码时,处理器在进入“解码”状态时停止执行。此外,Quartus提供了许多警告说“LC3FSM.vhd(37)中的VHDL选择警告:忽略包含元值的选择”“0001 ------ 0 -----”“” 我不知道如何实现这一目标。我真的不需要也可能不需要定义每一个16位组合,我希望有一种方法可以在STD_LOGIC_VECTOR中使用通配符来最小化我必须定义的组合数。
有人知道如何做到这一点吗?
由于
答案 0 :(得分:5)
不幸的是,这是不可能完成的。对于大多数用户来说,比较运算符=
和case
比较意外地进行了字面比较。这是因为std_logic
类型只是一组字符,由于其他函数(例如and
和or
)的定义方式,它们碰巧执行逻辑值。
VHDL-2008引入了一个新的案例语句case?
,它可以按预期执行 - 您需要告诉编译器在VHDL 2008模式下运行。此外,VHDL 2008中有一个?=
运算符,它比较了两个值,并考虑了-
s。
如果您使用仍然不支持VHDL 2008的编译器,请向供应商投诉。还有一个std_match
函数允许您在较旧的VHDL版本中执行比较,但我不知道如何使case
语句以这种方式工作。
答案 1 :(得分:1)
假设您不需要指令中的其他位,您可以通过使用预检查过程屏蔽其他位来解决此问题。 (或者只是确保在写指令时其他位复位?)
这真的是一个黑客攻击。
假设IR存储为变量
if IR(15 downto 12) == "0001" then
IR := IR_in(15 downto 12) & "0000000" & IR_in(5) & "00000";
else
IR := IR_in
end if;
CASE IR IS --(IR stands for "Instruction Register")
WHEN "0001000000000000" => (Go to 3-register add);
WHEN "0001000000100000" => (Go to 2-register/immediate value add);
WHEN OTHERS => (Do whatever);
END CASE;
或者假设您的指令经过深思熟虑(命令字的前四位或沿着这些行的东西?),您可以执行嵌套的case语句,并根据需要在这些子块中进行区分。