我正在学习VHDL,以描述和演示具有危险检测和分支预测等的超标量流水线CPU的工作。
我从小做起,所以在练习中我尝试制作一个非常简单的计算器"设计,像这样:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_signed.all;
entity calculator is
port(
in_A : in std_logic_vector(3 downto 0);
in_B : in std_logic_vector(3 downto 0);
add : in std_logic;
sub : in std_logic;
out_C : out std_logic_vector(3 downto 0)
);
end entity calculator;
architecture RTL of calculator is
signal next_output : std_logic_vector(3 downto 0);
begin
process(in_A, in_B, add, sub)
variable temp_x, temp_y, temp_z : integer;
begin
temp_x := conv_integer(in_A);
temp_y := conv_integer(in_B);
if(add = '1') and (sub = '0') then
temp_z := temp_x + temp_y;
next_output <= std_logic_vector(to_unsigned(temp_z, 4));
elsif(add = '0') and (sub = '1') then
temp_z := temp_x - temp_y;
next_output <= std_logic_vector(to_unsigned(temp_z,4));
else
temp_z := 0;
next_output <= std_logic_vector(to_unsigned(temp_z,4));
end if;
out_C <= next_output;
end process;
end architecture RTL;
但是,我无法弄清楚为什么只在输入改变后才设置输出,如此处所示(我认为测试台代码无关紧要):
我想知道我应该做些什么才能使输出正确并且没有延迟。如果add是1,那么输出应该根据输入设置,没有延迟(好吧,我希望它是,我写它的方式,它不是:))
此外,有人可以向我解释输出会在触发器中被记住的情况,以及是否以触发器的方式记住我编写描述的方式。
我也非常感谢所有的建议,批评和指导来帮助我。这只是一个简单的ADD / SUB计算器,我需要在大约两个月内描述一个带有指令集的整个处理器!也许你可以指出我很好的学习教程,因为我的课程没用:(
提前致谢! :)
答案 0 :(得分:1)
最简单的方法是移动作业
out_C <= next_output;
进程外(使其成为并发信号分配)。
您还可以使next_output成为流程中声明的变量,并将信号分配保留在原来的位置。
发生延迟是因为信号分配不会在它们发生的模拟周期中生效。如果没有对next_output敏感的过程,则下次执行过程时将看到新值。
并发信号赋值语句具有等效过程,其中右侧的信号位于灵敏度列表中。
使next_output成为变量使其值立即可用。
您也可以重写您的流程:
process(in_A, in_B, add, sub)
variable temp_x, temp_y, temp_z : integer;
begin
temp_x := conv_integer(in_A);
temp_y := conv_integer(in_B);
if(add = '1') and (sub = '0') then
temp_z := temp_x + temp_y;
elsif(add = '0') and (sub = '1') then
temp_z := temp_x - temp_y;
else
temp_z := 0;
end if;
out_C <= std_logic_vector(to_unsigned(temp_z,4));
end process;
消除next_output。
答案 1 :(得分:1)
<=
与中间信号next_output
的信号分配不是
在进程的同一次运行中可见,因此需要另一次运行
直到out_C <= next_output
看到新值,因此延迟。
正如David Koontz写的那样,你可以将out_C <= next_output
移到外面
过程
替代方案是获得所有中间信号和变量的脊,并且
重写代码如下,包括仅使用IEEE标准包
numeric_std
,并跳过Synopsys专有软件包
std_logic_signed
。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
...
architecture RTL of calculator is
begin
process(in_A, in_B, add, sub)
begin
if(add = '1') and (sub = '0') then
out_C <= std_logic_vector(signed(in_A) + signed(in_B));
elsif(add = '0') and (sub = '1') then
out_C <= std_logic_vector(signed(in_A) - signed(in_B));
else
out_C <= std_logic_vector(to_signed(0, out_C'length));
end if;
end process;
end architecture RTL;
我看到David提出了类似的建议,但无论如何你都可以得到我的建议: - )