发出信号等到下降沿

时间:2013-09-02 21:24:06

标签: matrix signals vhdl

我有这个信号,应该为零,直到另一个信号Start = 0.我怎么能做到这一点?以下是相关代码:

        din<=0;
        wait until falling_edge(start);

    for i in 0 to 63 loop
        wait until clk = '1' and clk'event;
        if i = 0 then
            Start <= '1','0' after clk_period;
        end if;
            if (i < 24) then 
                din <= 255;
            elsif (i > 40) then
                din <= 255;
            else
                din <= 0;
            end if;

        end loop;

    wait;

我想我可以让din = 0直到开始的下降沿,但它会在开始的上升沿停止。我想在start = 0时开始读取din值。在那之前din = 0。

这是一张照片: enter image description here

编辑:实际上我是从正确的信号值开始的,但是dout值总是有一个不必要的中间值。在这种情况下,它的78450.我知道这与testbench代码有关,但我不能让它只是在正确的时间计算正确的值。可以对下面的代码进行哪些更改以消除中间值?

enter image description here

            din<=0;


    for i in 0 to 63 loop
        wait until clk = '1' and clk'event;
        if i = 0 then
            Start <= '1','0' after clk_period;
            elsif (i < 24) then 
                din <= 255;
            elsif (i > 40) then
                din <= 255;
            else
                din <= 0;
        end if;

        end loop;

3 个答案:

答案 0 :(得分:4)

首先,我假设(并希望)您正在编写测试平台。如果没有,您应该避免使用等待语句,因为它们在综合工具中的支持非常有限。

即使在测试平台中,最好只使用基于时间的等待或后续语句来生成时钟,并使所有其他信号依赖于事件(例如rising_edge(clk))。这避免了在delta周期0期间多个信号随时钟变化的问题。

考虑典型寄存器的以下代码:

process(clk) begin
    if(rising_edge(clk)) then
        a <= b;
    end if;
end process;

并假设clkb在测试平台中生成如下:

clk <= not clock after 1 ns;

process begin
    b <= '1', '0' after 10 ns;
    wait;
end process;
  • 在0 0时刻,clk变为'1',b变为'1'。
  • 在时间0 delta 1处,注册过程将在clk更改后运行,a将更改为“1”。
  • 不存在进一步的敏感性,因此时间将以1 ns更新到下一个事件。
  • 在时间1 delta 0,clk变为'0'。
  • 在时间1 delta 1,注册过程自clk更改后运行,但没有任何反应,因为rising_edge(clk)为false。
  • 上述重复时间为2-9 ns。
  • 在时间10 delta 0,clk变为'1',b变为'0'。请注意,clkb会在相同的增量周期中发生变化。
  • 在时间10 delta 1,注册过程运行,a变为'0'!就结果而言,这意味着b在时钟上升之前发生变化!

即使在这个简单的系统中这种行为是可以理解的,它也可能导致一些非常难以找到的模拟错误。因此,最好将所有信号基于适当的时钟。

process begin
    -- Initialize b to 1.
    b <= '1';
    -- Wait for 5 cycles.
    for i in 1 to 5 loop
        wait for rising_edge(clk);
    end loop;
    -- Set b to 0.
    b <= '0';

    -- Done.
    wait;
end process;

这可以避免意外行为,因为所有信号将在相关时钟之后至少改变一个增量周期,这意味着在所有过程中都会保持因果关系。

答案 1 :(得分:0)

I have this signal that should be zero until another signal Start = 0. How can I accomplish this?

也许您可以使用握手信号并将其放入流程的敏感列表中。它的行为就像一个复位信号。

process (handshake_s, ...)
begin
  if (handshake_s = '1') then  -- failing edge of start
    din <= 0;
  else
    -- do something
  end if;
end process;

使用其他进程更新 handshake_s

process (start, ...)
begin
  if failing_edge(start) then
    handshake_s <= '1', '0' after 10 ns;  -- produce a pulse
  end if;
  -- do something
end process;

你介意在这里发布所有代码,以便我们更好地理解波形吗?

答案 2 :(得分:0)

Testbench或RTL代码?

对于测试平台,您的编码风格基本上没问题,但是,您的信号Start有问题,并且在时钟的上升沿期间永远不会为'1'。它在时钟的上升沿之后变为“1”,并且将在时钟之前与时钟或1个增量循环同时返回“0”(取决于您的时钟设置)。无论哪种方式,在rising_edge时钟上运行的任何内容(例如您的设计)都不会将其视为“1”。

避免这种情况的一种简单方法是在所有进入DUT(被测设备)的测试平台输出上使用标称延迟(tperiod_Clk的25%)。脉冲的模式如下。

wait until clk = '1' ;  -- I recommend using rising_edge(Clk) for readability
Start <= '1' after tpd, '0' after tpd + tperiod_clk ; 

或者,您可以通过不使用波形分配来避免此问题。如下。在这种情况下,您不需要tpd,但是,如果它确实是一个测试平台,我建议使用它。

wait until clk = '1' ;  
if i = 0 then 
  Start <= '1' after tpd ; 
else 
  Start <= '0' after tpd ; 
end if ; 

对于 RTL代码,您需要探索不同的方法。非常简短的一种方法是如下。注意不要使用任何延迟,波形分配或循环。

-- Counter to count from 0 to 63.  Use  "+ 1".  Use "mod 64" if using type integer.
-- Start logic = decoder (can be coded separately) 
-- Din Logic = decoder (can be coded separately)