1

我有这个信号应该为零,直到另一个信号 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。

这是一张照片: 在此处输入图像描述

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

在此处输入图像描述

            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;
4

3 回答 3

4

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

即使在测试平台中,最好只使用基于时间的等待或后语句来生成时钟,并使所有其他信号依赖于事件(例如rising_edge(clk))。这避免了在增量周期 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 delta 0,clk更改为“1”b并将更改为“1”。
  • 在时间 0 delta 1 处,注册进程将在clk更改后运行,a并将更改为“1”。
  • 不存在进一步的敏感性,因此时间将在 1 ns 时更新到下一个事件。
  • 在时间 1 增量 0,clk变为“0”。
  • 在时间 1 delta 1 处,注册进程在clk更改后运行,但没有任何反应,因为rising_edge(clk)它是假的。
  • 上述重复时间 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;

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

于 2013-09-03T10:14:08.400 回答
0

测试台或 RTL 代码?

对于 testbench,您的编码风格基本没问题,但是,您的信号 Start 有问题,并且在时钟上升沿期间永远不会为“1”。它在时钟上升沿之后变为“1”,并将与时钟同时或时钟前 1 个增量周期返回“0”(取决于您的时钟设置)。无论哪种方式,在上升沿时钟上运行的任何东西(例如您的设计)都不会将其视为“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)
于 2013-09-03T22:29:02.923 回答
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;

您介意在此处发布您的所有代码,以便我们更好地理解波形吗?

于 2013-09-03T09:29:34.570 回答