VHDL:为什么输出延迟这么多?

时间:2015-02-12 17:54:58

标签: vhdl hdl quartus

我正在学习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;

但是,我无法弄清楚为什么只在输入改变后才设置输出,如此处所示(我认为测试台代码无关紧要):

Model-Sim

我想知道我应该做些什么才能使输出正确并且没有延迟。如果add是1,那么输出应该根据输入设置,没有延迟(好吧,我希望它是,我写它的方式,它不是:))

此外,有人可以向我解释输出会在触发器中被记住的情况,以及是否以触发器的方式记住我编写描述的方式。

我也非常感谢所有的建议,批评和指导来帮助我。这只是一个简单的ADD / SUB计算器,我需要在大约两个月内描述一个带有指令集的整个处理器!也许你可以指出我很好的学习教程,因为我的课程没用:(

提前致谢! :)

2 个答案:

答案 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提出了类似的建议,但无论如何你都可以得到我的建议: - )

相关问题