我正在尝试编写一个具有输入(开始)和三个输出(tsy,tsr,tlg)的计数器,这些输出分别在4,6和16 clk_period
之后为1 clk_period
置位。以下代码适用于单个启动断言。
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;
entity proj_test is
port (
clk, start : in bit;
tsy, tsr, tlg : out bit
) ;
end entity ; -- proj_test
architecture behav of proj_test is
constant clk_period : time := 100 ns;
begin
process (start)
begin
if (start='1') then
tsy <= '1' after 4*clk_period, '0' after 5*clk_period;
tsr <= '1' after 6*clk_period, '0' after 7*clk_period;
tlg <= '1' after 16*clk_period, '0' after 17*clk_period;
end if;
end process;
end architecture ; -- behav
start
脉冲相隔400 ns,由以下代码驱动:
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;
entity proj_test_test is
end entity proj_test_test;
architecture behav of proj_test_test is
constant clk_period : time := 100 ns;
signal clk, start : bit;
signal tsy, tsr, tlg : bit;
begin
P : entity work.proj_test port map (clk, start, tsy, tsr, tlg);
start <= '0',
'1' after 2*clk_period,
'0' after 3*clk_period,
'1' after 6*clk_period,
'0' after 7*clk_period,
'1' after 42*clk_period;
end architecture behav;
https://www.edaplayground.com/x/52mP
或以下模拟器命令:
force -freeze sim:/proj_test/clk 0 0, 1 {50 ns} -r 100
force -freeze sim:/proj_test/start 1 0, 0 100, 1 400, 0 500
但是,当我第二次断言输入start
时,tsy
会跨越多个时钟周期。
我试图理解为什么。我的猜测是第二个进程调用“刷新”第一个进程的分配。另外,有没有更好的方法来编写此计数器的行为?
答案 0 :(得分:2)
VHDL模拟器维护事件队列。这是模拟器的“待办事项”列表。使用信号分配执行任何VHDL行的效果是修改事件队列。通常,事件会添加到事件队列中,但通常也可以删除事件。将删除事件以模拟惯性延迟;在VHDL中,默认情况下延迟是惯性的。
为了模拟惯性延迟,将事件添加到事件中 队列,计划同时发生的任何事件或 之前被删除,除非该事件的效果与之相同 正在添加新事件的效果。
执行代码时,后续信号分配会从事件队列中删除事件。我们需要详细分析事件队列。
因此,在0 ns时,事件队列为空。该行在时间0执行
start <= '0',
'1' after 2*clk_period,
'0' after 3*clk_period,
'1' after 6*clk_period,
'0' after 7*clk_period,
'1' after 42*clk_period;
将6个事件放入事件队列。事件队列现在看起来像这样:
TIME DELTA SIGNAL VALUE
0 ns 1 start '0'
200 ns 0 start '1'
300 ns 0 start '0'
600 ns 0 start '1'
700 ns 0 start '0'
4200 ns 0 start '1'
在200 ns时,start
被驱动到'1'
,因此执行以下三行:
tsy <= '1' after 4*clk_period, '0' after 5*clk_period;
tsr <= '1' after 6*clk_period, '0' after 7*clk_period;
tlg <= '1' after 16*clk_period, '0' after 17*clk_period;
将6个事件放到事件队列中。事件队列现在看起来像这样:
TIME DELTA SIGNAL VALUE
300 ns 0 start '0'
600 ns 0 start '1'
600 ns 0 tsy '1'
700 ns 0 start '0'
700 ns 0 tsy '0'
800 ns 0 tsr '1'
900 ns 0 tsr '0'
1800 ns 0 tlg '1'
1900 ns 0 tlg '0'
4200 ns 0 start '1'
然后在300 ns start
被驱动到'0'
,因此事件队列现在看起来像这样:
TIME DELTA SIGNAL VALUE
600 ns 0 start '1'
600 ns 0 tsy '1'
700 ns 0 start '0'
700 ns 0 tsy '0'
800 ns 0 tsr '1'
900 ns 0 tsr '0'
1800 ns 0 tlg '1'
1900 ns 0 tlg '0'
4200 ns 0 start '1'
然后在600 ns start
被驱动到'1'
(tsy
也被驱动到'1'
,因此事件队列现在看起来像这样:
TIME DELTA SIGNAL VALUE
700 ns 0 start '0'
700 ns 0 tsy '0'
800 ns 0 tsr '1'
900 ns 0 tsr '0'
1800 ns 0 tlg '1'
1900 ns 0 tlg '0'
4200 ns 0 start '1'
并再次执行以下三行:
tsy <= '1' after 4*clk_period, '0' after 5*clk_period;
tsr <= '1' after 6*clk_period, '0' after 7*clk_period;
tlg <= '1' after 16*clk_period, '0' after 17*clk_period;
将另外6个事件添加到事件队列中:
TIME DELTA SIGNAL VALUE
1000 ns 0 tsy '1'
1100 ns 0 tsy '0'
1200 ns 0 tsr '1'
1300 ns 0 tsr '0'
2200 ns 0 tlg '1'
2300 ns 0 tlg '0'
如果您遵循我上面给出的规则,您会看到事件队列如下所示:
TIME DELTA SIGNAL VALUE
700 ns 0 start '0'
1000 ns 0 tsy '1'
1100 ns 0 tsy '0'
1200 ns 0 tsr '1'
1300 ns 0 tsr '0'
2200 ns 0 tlg '1'
2300 ns 0 tlg '0'
4200 ns 0 start '1'
因为这五个事件被删除了:
TIME DELTA SIGNAL VALUE
700 ns 0 tsy '0'
800 ns 0 tsr '1'
900 ns 0 tsr '0'
1800 ns 0 tlg '1'
1900 ns 0 tlg '0'
如果查看跟踪,您会看到这些事件正是发生的事情:
tsy
的下降沿(因此宽脉冲); tsr
上的前两个事件被删除(因此只有一个脉冲); tlg
上的前两个事件被删除(因此只有一个脉冲)。