0

我正在学习 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 计算器,我必须在大约两个月内描述一个带有指令集的整个处理器!也许你可以给我指点好的学习教程,因为我上的课没用:(

提前致谢!:)

4

2 回答 2

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。

于 2015-02-12T18:24:25.477 回答
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;

我看到大卫提出了类似的建议,但无论如何你都可以得到我的:-)

于 2015-02-12T18:39:25.913 回答