VHDL - iSIM 输出未初始化,不改变状态

VHDL - iSIM output uninitialised, doesn't change states

您好,我是 Xilinx 的新用户,在如何在测试平台中编写 stimulus/simulate 时遇到了问题。我的输出 (Kd) 没有给我任何合理的值,并且在移动之前的前几个时钟周期给出 'u' 并始终保持在“1”。

不确定我是否写了正确的刺激,但希望有人能帮助我!

我的VHDL代码

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity codeFig2b is
    Port ( R0 : in  STD_LOGIC;
           R1 : in  STD_LOGIC;
           R2 : in  STD_LOGIC;
           R3 : in  STD_LOGIC;
           Kd : out  STD_LOGIC;
           clock : in  STD_LOGIC);
end codeFig2b;

architecture Behavioral of codeFig2b is
    signal Qa, Qb: STD_LOGIC;
begin
    process(clock, R0, R1, R2, R3)
        begin
        if clock = '1' and clock'event then
        Qa <= (R0 or R1 or R2 or R3) or (Qa and Qb);
        Qb <= Qa;
        end if;
    end process;
Kd <= Qa and Qb;    

end Behavioral;

我的测试平台##

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;

ENTITY codeFig2b_test IS
END codeFig2b_test;

ARCHITECTURE behavior OF codeFig2b_test IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT codeFig2b
    PORT(
         R0 : IN  std_logic;
         R1 : IN  std_logic;
         R2 : IN  std_logic;
         R3 : IN  std_logic;
         Kd : OUT  std_logic;
         clock : IN  std_logic
        );
    END COMPONENT;


   --Inputs
   signal R0 : std_logic := '0';
   signal R1 : std_logic := '0';
   signal R2 : std_logic := '0';
   signal R3 : std_logic := '0';
   signal clock : std_logic := '0';

    --Outputs
   signal Kd : std_logic;

   -- Clock period definitions
   constant clock_period : time := 100 ns;

BEGIN
    -- Instantiate the Unit Under Test (UUT)
   uut: codeFig2b PORT MAP (
          R0 => R0,
          R1 => R1,
          R2 => R2,
          R3 => R3,
          Kd => Kd,
          clock => clock
        );

   -- Clock process definitions
   clock_process :process
   begin
        clock <= '0';
        wait for clock_period/2;
        clock <= '1';
        wait for clock_period/2;
   end process;


   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
       wait for 100 ns;
            R0 <= '0';
            R1 <= '0';
            R2 <= '0';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '0';
            R2 <= '0';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '0';
            R2 <= '1';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '0';
            R2 <= '1';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '1';
            R2 <= '0';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '1';
            R2 <= '0';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '1';
            R2 <= '1';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '1';
            R2 <= '1';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '0';
            R2 <= '0';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '0';
            R2 <= '0';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '0';
            R2 <= '1';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '0';
            R2 <= '1';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '1';
            R2 <= '0';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '1';
            R2 <= '0';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '1';
            R2 <= '1';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '1';
            R2 <= '1';
            R3 <= '1';

      wait for clock_period*10;

      -- insert stimulus here 

      wait;
   end process;

END;

这个不用模拟也能回答。 Kd 的输出将变为“1”并保持在那里。

    process(clock, R0, R1, R2, R3)
        begin
        if clock = '1' and clock'event then
        Qa <= (R0 or R1 or R2 or R3) or (Qa and Qb);
        Qb <= Qa;
        end if;
    end process;
Kd <= Qa and Qb;  

对于 R0、R1、R2 或 R2 或(Qa 和 Qb)中的任何一个,Qa 变高;

所以一旦 Qa 和 Qb 变高,Qa 就会保持高位。

Qb 在第一次出现 Qa 变高后一个时钟变高。

发生这种情况的方式是在 R0、R1、R2 或 R3 中的任何一个上连续输入“1”。

你的时钟周期是 100 ns,你的刺激间隔也是。

在第一个时钟之后没有刺激,其中所有 R0、R1、R2 和 R3 同时都处于低电平以示证明。

不幸的是,您的 Xilinx post (iSIM output Unintialised, doesn't change states.) 上的波形图像没有显示 QA 和 Qb,无法看到它们都变高并保持在那里:

(可点击)

当你添加它们时,这一点就会出现:

可点击)

您构建的是 顺序 逻辑,这意味着输出取决于 inputs/outputs 的 previous hystory。在您的情况下,我们有 Qa 和 Qb,这是 Qa 的最后一个值。

请记住这一点,您在测试台中使用的方法并不是最佳的,因为您正在尝试输入的每个组合,而没有考虑最后一个 Qa 实际上很重要。

事情是这样的:

Start :   Qa = U    Qb = U     =>    Kb = U
Inputs 1: Qa = 1    Qb = U     =>    Kb = U
Inputs 2: Qa = 1    Qb = 1     =>    Kb = 1
Inputs 3: Qa = 1    Qb = 1     =>    Kb = 1
Inputs 4: Qa = 1    Qb = 1     =>    Kb = 1
....

其中一个Rs变高,Qa就变高。给定输入组合的顺序,Qa 不会再次变低。 这意味着在第二个输入组合之后,Qb 得到一个已知值并且 Kb 变高。


敏感度列表

这不是答案的一部分,但它是对您编写的代码的考虑:您已将敏感度列表 R0、R1、R2、R3 放入,但考虑到您之后编写的内容,这不是必要的。

进程只在

时才做某事
if clock'event and clock = 1 then

这意味着 Rs 上的任何事件都将被忽略。我确信合成器实际上意识到了这一点并忽略了它,但设置适当的敏感度列表是一个很好的做法,并且在可能的情况下,只使用 clocked 顺序逻辑和有限状态的进程机器。

我还建议您使用更具可读性的 rising_edge(clock) 和 falling_edge(clock) 函数:

process(clock)
begin
    if rising_edge(clock) then
        Qa <= R0 or R1 or R2 or R3 or (Qa and Qb);
        Qb <= Qa;
    end if;
end process;

信号和过程

您应该知道的另一件事是流程的工作原理:您不是为信号分配新值,而是为它们分配 规划 值。如果您对某个信号进行重新编程,您只是在覆盖之前的计划,并且永远不会分配第一个值。在过程结束时 最终分配值

这是一个简单的例子:

-- Let's assume A = 0 and B = 0 at startup
clocked_process : process(clk)
begin
    if rising_edge(clk) then
        A <= '1';
        B <= A;
        A <= '0';
    end if;
end process;

最后B还是0,这是因为整个过程A=0,只得到一个计划值为1,实际上没有赋值,因为之前被覆盖了过程结束(在这种特定情况下,合成器将忽略 A <= '1' 的实现)。

覆盖计划值可以用来简化逻辑:我通常做的是设置一些默认值,然后只在需要时覆盖它们。

所以,而不是写作

...
case A is
when "00" =>
    B <= '0';
when "01" =>
    B <= '0';
when "10" =>
    B <= '0';
when "11" =>
    B <= '1';
end case;
...

我写了这个(如果我需要它用于其他信号,我可能会保留 case 结构,通常在有限状态机中):

...
B <= '0';
if A = "11" then
    B <= '1';
end if;
...

对于这个简单的例子,合成器可能能够推断出简化。但是,您应该习惯于在逻辑级端口中思考,因为从行为的角度来看,以两种等效方式编写的同一事物实际上是不同的。