问题描述
我正在上vhdl在线课程。 实验室的一项工作是:“基于分频器和8位循环移位寄存器,实现了具有1 s移位周期的环形计数器。”
任务表明,计数器的最高有效位不能用作移位寄存器的时钟信号(即,在if上升边缘(移位器(MSB))结构中)。 必须将使能信号形成为选通脉冲。
我做了工作。结果被接受。
shift_reg_proc : process(clk)
begin
if (rising_edge(clk)) then
if (srst = '1') then
shift_reg <= "10000000";
elsif (en = '1') then
shift_reg <= shift_reg(0) & shift_reg(7 downto 1);
end if;
end if;
end process shift_reg_proc
如果使能信号的持续时间为1个周期clk,则很有可能在rise_edge(clk)时刻en信号电平将没有时间变为= 1。 如果是这种情况,则不能保证寄存器移位将在下一秒发生。 有什么“正确”的方法可以完成此任务吗? 是这样吗?我的决定正确吗?实验室线索会误导人吗?
我将附加实现代码,测试台和波形图。
ring_counter.vhd
--------------------------------------------------------------------------------
-- Based on frequency divider and 8-bit cyclic shift register implement a ring
-- counter with a shift period of 1 s.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity ring_counter is
port(clk : in std_logic;
srst : in std_logic;
dout : out std_logic_vector(7 downto 0);
en_o : out std_logic
);
end entity ring_counter;
architecture behave of ring_counter is
signal cntr : std_logic_vector(26 downto 0) := (others => '0');
signal cntr_msb_delayed : std_logic;
signal shift_reg : std_logic_vector(7 downto 0);
signal en : std_logic;
constant cntr_msb_num : integer := 4; -- 26 for DE board,4 for test bench
begin
-- signal for test bench
en_o <= en;
--------------------------------------------------------------------------------
-- Counter implementation
--------------------------------------------------------------------------------
cntr_proc : process(clk)
begin
if (rising_edge(clk)) then
if (srst = '1') then
cntr <= (others => '0');
else
cntr <= unsigned(cntr) + 1;
end if;
end if;
end process cntr_proc;
----------------------------------------------------------------------------
-- Shift register implementation
----------------------------------------------------------------------------
shift_reg_proc : process(clk)
begin
if (rising_edge(clk)) then
if (srst = '1') then
shift_reg <= "10000000";
elsif (en = '1') then
shift_reg <= shift_reg(0) & shift_reg(7 downto 1);
end if;
end if;
end process shift_reg_proc;
dout <= shift_reg;
----------------------------------------------------------------------------
-- Enable signal generation
----------------------------------------------------------------------------
-- Counter MSB delay for 1 period of clk
delay_proc : process(clk)
begin
if (rising_edge(clk)) then
cntr_msb_delayed <= cntr(cntr_msb_num);
end if;
end process delay_proc;
en <= cntr(cntr_msb_num) and not cntr_msb_delayed;
end architecture behave;
ring_counter_tb.vhd
library ieee;
use ieee.std_logic_1164.all;
entity ring_counter_tb is
end entity ring_counter_tb;
architecture behave of ring_counter_tb is
component ring_counter is
port(clk : in std_logic;
srst : in std_logic;
dout : out std_logic_vector(7 downto 0);
en_o : out std_logic
);
end component ring_counter;
signal clk : std_logic;
signal srst : std_logic;
signal dout : std_logic_vector(7 downto 0);
signal en_o : std_logic;
constant clk_period : time := 4 ns;
begin
dut : ring_counter
port map (
clk => clk,srst => srst,dout => dout,en_o => en_o
);
clk_gen : process
begin
clk <= '0';
wait for clk_period;
loop
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end loop;
end process clk_gen;
srst <= '0','1' after 100 ns,'0' after 150 ns;
end architecture behave;
解决方法
TL; DR
clk
的上升沿之后的en
上升与移位寄存器移位的clk
的上升沿不同。 en
在上升沿N
之后被置为高电平,而在 上升沿N+1
之后被置为无效。因此,您的移位寄存器在N+1
的上升沿移位。
因此,在en
的声明和寄存器移位之间大约有一个时钟周期延迟。您不在乎,因为您的规格说明您想要1秒的转换时间。只要en
是周期为一秒的周期,即使en
与移位寄存器之间的常数延迟很小,您就可以满足规范。
但是最重要的是,正如您的移位寄存器所看到的,在{strong>上升沿en
之后,N
被断言为足够高,以避免过早出现在N+1
上升沿之后 撤消并充分断言以允许进行良好的平移。如果您对此也有兴趣,请继续阅读。
详细说明
您的en
信号是根据与移位寄存器在同一时钟clk
上同步的寄存器的输出计算得出的。您在那里没有任何保持时间问题:从时钟的上升沿到cntr
和cntr_msb_delayed
寄存器的输出的传播延迟保证了en
将在引起时钟的时钟上升沿之后足够地到达(假设您没有较大的时钟偏斜)。它不能太早到达。
到达时间是否太晚(设置时间问题)?是的,如果您的时钟频率太高。这样一来,时钟周期将太短,en
将没有足够的时间来计算,稳定并传播到下一个时钟上升沿之前的移位寄存器,并且可能发生任何事情(根本没有移位,部分移位,亚稳定...)
这是数字设计中非常普遍的问题:您不能以任意高的时钟频率进行操作。如果可以的话,您可以将自己的计算机以yotta-Hz或更高的频率(而不是giga-Hz)提供时钟,一切都会变得瞬间。很好,但这不是现实世界的工作方式。
在数字设计中,您始终拥有称为关键路径的东西。它是一组源寄存器和目标寄存器之间的特定逻辑门链,沿着该逻辑门,电信号的传播延迟是整个设计中最大的。
这是一条可行路径,该路径上的总延迟取决于设计的复杂性(例如,计数器的位数),目标硬件技术(例如,原型板的FPGA)和工作条件(温度,电源电压,FPGA的速度等级)。
(是的,这还取决于温度,以及为什么硬核游戏玩家使用高性能冷却系统为计算机冷却的原因。这避免了硅的破坏,并允许以更高的时钟频率和更多的帧来操作计算机每秒和更好的用户体验。)
信号从源时钟沿到到达目的地所花费的最长时间,并加上一个很小的安全裕量,称为“目标寄存器的建立时间”,这是最小的。时钟周期(最高时钟频率),您可以在其中运行设计。只要您不超过此限制,系统就可以按预期运行。
硬件设计工具链通常包含一个静态时序分析器(STA),它告诉您该最大时钟频率对于您的设计,目标和操作条件而言是什么。如果它告诉您500 MHz,而您只需要350 MHz,那么一切都很好(但是您可以进行调查,看看是否可以修改设计,节省一些硬件并仍在350 MHz上运行)。
但是,如果您需要650 MHz,则该轮到袖子了,查看关键路径(STA也将显示路径),了解它并重新设计以加快速度(例如,流水线长计算,使用提前进位加法器,而不是进位纹波...)请注意,通常,当您遇到时序收敛问题时,您不会只考虑一条关键路径,而是考虑超出时间预算的所有路径,因为您想消除所有这些,不只是最坏的。这就是为什么STA不仅按照严重性从高到低的顺序为您提供最坏的关键路径,而且还列出关键路径的原因。