Vivado 停止对反馈电路的仿真

Vivado stops simulation on feedback circuit

我正在尝试制作一个由 2 对 1 多路复用器(8 位总线)、8 位寄存器和 8 位加法器组成的电路。这些组件都经过测试并按预期工作。

问题是:如果我尝试将加法器的输出发送到加法器的输入之一 多路复用器(如图中虚线所示),模拟将突然停止。如果我不这样做而只是让 ain 做它的事情,一切都会 运行 就像它应该的那样,但我确实需要加法器的输出是那个输入到多路复用器。

模拟如下:

密码是:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Sumitas is
    port (m   : in  STD_LOGIC;
          clk : in  STD_LOGIC;
          ain : in  STD_LOGIC_VECTOR (7 downto 0);
          Add : out STD_LOGIC_VECTOR (7 downto 0));
end Sumitas;

architecture rtl of Sumitas is
    component Adder8bit
        port (a, b : in  STD_LOGIC_VECTOR (7 downto 0);
              Cin  : in  STD_LOGIC;
              S    : out STD_LOGIC_VECTOR (7 downto 0);
              Cout : out STD_LOGIC);
    end component;
    
    component GenericReg
        generic (DataWidth : integer := 8);
        port (en      : in  STD_LOGIC;
              dataIn  : in  STD_LOGIC_VECTOR (DataWidth - 1 downto 0);
              dataOut : out STD_LOGIC_VECTOR (DataWidth - 1 downto 0));
    end component;
    
    component GenericMux2_1
        generic (DataWidth : integer := 8);
        port (a, b : in  STD_LOGIC_VECTOR (DataWidth - 1 downto 0);
              Z    : in  STD_LOGIC;
              S    : out STD_LOGIC_VECTOR (DataWidth - 1 downto 0));
    end component;
    
    constant DW : integer := 8;
    
    signal AddOut_s, MuxOut_s : STD_LOGIC_VECTOR (7 downto 0);
    signal PCOut_s            : STD_LOGIC_VECTOR (7 downto 0);
    
begin
    
    m0 : GenericMux2_1
        generic map (DataWidth => DW)
        port map (a => "00000000",
                  b => AddOut_s,
                  Z => m,
                  S => MuxOut_s);

    PC : GenericReg
        generic map (DataWidth => DW)
        port map (en      => clk,
                  dataIn  => MuxOut_s,
                  dataOut => PCOut_s);

    Add0 : Adder8bit
        port map (a    => "00000001",
                  b    => PCOut_s,
                  Cin  => '0',
                  S    => AddOut_s,
                  Cout => open);
    Add <= AddOut_s;    
end rtl;

和测试平台:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity bm_Sumitas is
end bm_Sumitas;

architecture benchmark of bm_Sumitas is
    component Sumitas
        port (m   : in  STD_LOGIC;
              clk : in  STD_LOGIC;
              ain : in  STD_LOGIC_VECTOR (7 downto 0);
              Add : out STD_LOGIC_VECTOR (7 downto 0));
    end component;
    
    signal clk_s, m_s    : STD_LOGIC;
    signal Add_s, ain_s  : STD_LOGIC_VECTOR (7 downto 0);
    
    constant T : time := 2 ns;
    
begin

    benchmark : Sumitas
        port map (m   => m_s,
                  clk => clk_s,
                  ain => ain_s,
                  Add => Add_s);

    clk_proc: process
    begin
        clk_s <= '0';
            wait for T/2;
        clk_s <= '1';
            wait for T/2;
    end process;

    bm_proc : process
    begin
        m_s <= '0';
            wait for 10 ns;
        m_s <= '1';
            wait for 100 ns;
    end process;

    ains_proc : process
    begin
        ain_s <= "00001111";
        for I in 0 to 250 loop
            ain_s <= STD_LOGIC_VECTOR(TO_UNSIGNED(I, ain_s'length));
            wait for T;
        end loop;
    end process;
end benchmark;

我怎样才能做我想做的事?我最终试图模拟我设计的计算机。我已经设计了每个组件,并且正在将它们耦合在一起。

构建Minimal, Complete, and Verifiable example需要填写缺失的组件:

library ieee;
use ieee.std_logic_1164.all;

entity Adder8bit is
    port (a, b : in  STD_LOGIC_VECTOR (7 downto 0);
          Cin  : in  STD_LOGIC;
          S    : out STD_LOGIC_VECTOR (7 downto 0);
          Cout : out STD_LOGIC);
end entity;

architecture foo of adder8bit is
    signal sum: std_logic_vector (9 downto 0);
    use ieee.numeric_std.all;
begin
    sum <= std_logic_vector ( unsigned ('0' & a & cin) +
                              unsigned ('0' & b & cin ));
    s <= sum(8 downto 1);
    cout <= sum(9);
end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity GenericReg is
    generic (DataWidth : integer := 8);
    port (en      : in  STD_LOGIC;
          dataIn  : in  STD_LOGIC_VECTOR (DataWidth - 1 downto 0);
          dataOut : out STD_LOGIC_VECTOR (DataWidth - 1 downto 0));
end entity;

architecture fum of genericreg is
begin
    dataout <= datain when en = '1';
end architecture;

使用行为模型替代品。

(工作量不大,复制组件声明并粘贴它们,将 entity 替换为 component 并添加保留字 ,其次是架构中的简单行为。)

它重现了您在模拟波形中显示的症状:

您可以看到当寄存器使能 (ms_s) 变高时发生故障的关键点。

模拟器将报告操作 STD_OUTPUT:

%: make wave
/usr/local/bin/ghdl -a   bm_sumitas.vhdl
/usr/local/bin/ghdl -e   bm_sumitas
/usr/local/bin/ghdl -r  bm_sumitas --wave=bm_sumitas.ghw --stop-time=40ns
./bm_sumitas:info: simulation stopped @11ns by --stop-delta=5000
/usr/bin/open  bm_sumitas.gtkw
%:

请注意,模拟在 11 ns 处停止,因为进程在增量周期中重复执行(模拟时间没有提前)。

这是由门控张弛振荡器引起的,门控张弛振荡器由启用的锁存器、延迟(增量周期)形成,并且至少有一个锁存器输入元素在每个增量周期内反转。

所使用的特定模拟器具有增量循环限制,当模拟时间未提前发生 5,000 个增量循环时,它将退出模拟。

假设 0 fs(分辨率限制)后,genericreg 继续生成事件,分配时没有时间延迟,波形中没有 after 子句。

本质上,当启用为真时,由于增量,信号将在每个模拟周期至少更改一个元素,并在每个模拟周期为信号分配至少一个元素的新值,而不允许提前模拟时间通过不去静止。

您可能会注意到,您使用的模拟器如果能够(并已启用),应该会产生一个带有类似消息的 'console' 输出。

那么这个问题是怎么解决的呢?最简单的方法是使用对时钟边沿敏感的寄存器(不是锁存器):

architecture foo of genericreg is
begin
    dataout <= datain when rising_edge(en);
end architecture;

这给了我们完整的模拟: