乍一看,您会期望下面的VHDL源代码充当移位寄存器。在那个q中,随着时间的流逝,
"UUUU0", "UUU00", "UU000", "U0000", "00000", ....
但是它总是U
在五个(或更多)连续时钟周期之后。
为什么是这样?
该代码实际上是复杂得多的模拟的简化版本。但这证明了我看到的症状。
它在ModelSim和ActiveHDL下的仿真过程中都显示出这一有趣且出乎意料的结果,我没有尝试过其他仿真器,并且(第二个原因的解释)想知道其他程序是否以相同的方式运行。
要正确回答此问题,您必须了解:
- 我知道这不是实现移位寄存器的最佳方法
- 我知道对于RTL综合,应该重新设置。
- 我知道std_logic的数组是std_logic_vector。
- 我知道聚合运算符
&
。
我还发现了:
- 如果将分配
temp(0)<='0';
移到流程中,则它将起作用。 - 如果循环已展开(请参见注释的代码),则它将起作用。
我要重申的是,这是一个更为复杂的设计(用于流水线CPU)的非常简化的版本,被配置为纯粹显示意外的仿真结果。实际信号类型只是一种简化。因此,您必须按照原样考虑代码中的答案。
我的猜测是,VHDL仿真引擎的优化器错误地(或按照规范)没有费心地在循环内运行表达式,因为没有外部变化的信号,尽管我可以通过将展开的循环置于循环中来证明这一点。
因此,我希望这个问题的答案更多地与模糊VHDL语法的VHDL仿真标准以及VHDL仿真引擎如何进行优化有关,而不是是否给出代码示例是完成某件事的最佳方法。
现在我要模拟的代码:
library ieee;
use ieee.std_logic_1164.all;
entity test_simple is
port (
clk : in std_logic;
q : out std_logic
);
end entity;
architecture example of test_simple is
type t_temp is array(4 downto 0) of std_logic;
signal temp : t_temp;
begin
temp(0) <= '0';
p : process (clk)
begin
if rising_edge(clk) then
for i in 1 to 4 loop
temp(i) <= temp(i - 1);
end loop;
--temp(1) <= temp(0);
--temp(2) <= temp(1);
--temp(3) <= temp(2);
--temp(4) <= temp(3);
end if;
end process p;
q <= temp(4);
end architecture;
和测试台:
library ieee;
use ieee.std_logic_1164.all;
entity Bench is
end entity;
architecture tb of bench is
component test_simple is
port (
clk : in std_logic;
q : out std_logic
);
end component;
signal clk:std_logic:='0';
signal q:std_logic;
signal rst:std_logic;
constant freq:real:=100.0e3;
begin
clk<=not clk after 0.5 sec / freq;
TB:process
begin
rst<='1';
wait for 10 us;
rst<='0';
wait for 100 us;
wait;
end process;
--Note: rst is not connected
UUT:test_simple port map (clk=>clk,q=>q) ;
end architecture;
temp(0)
由于没有与文字常量关联的“事件” ,因此模拟器似乎忽略了并发分配。将分配放入process
会创建与时钟事件的关联,从而使它起作用。我不知道after
在分配中添加一个子句是否可能是一种解决方法。