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;
这给了我们完整的模拟:
我正在尝试制作一个由 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;
这给了我们完整的模拟: