我如何解决这个增量周期时钟延迟问题 [英] How do I solve this delta cycle clock delay issue

查看:27
本文介绍了我如何解决这个增量周期时钟延迟问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码的简化示例,其中可以模拟 DeltasTest 实体以显示问题.实际设计中的时钟是否基于泛型反转或不反转,并在此下方馈送其他几个实体.

I have the following simplified example of my code, where the DeltasTest entity can be simulated to show the issue. The clock in the real design is inverted or not based on a generic, and feeds several other entities below this one.

问题是简单的边沿检测器在行为模拟中不起作用(data_out 只是一个小故障),因为反转阶段在时钟上引入了增量周期延迟.有没有标准或其他优雅的方法来解决这个问题?

The problem is that the simple edge detector does not work (data_out is just a glitch) in behavioral simulation, due to the delta cycle delay introduced on the clock by the inversion stage. Is there a standard or otherwise elegant way to solve this?

到目前为止,我最好的解决方案是将 data_in 信号分配给另一个信号,使其具有与 clk 相同的增量周期延迟.我想过根据需要使用函数来反转时钟,基于泛型作为函数的第二个参数,但是时钟被用在很多地方,这看起来不是很优雅,我注意到它甚至可以解决问题.我迫不及待地想把时钟倒置赋值设为 transport 赋值,但正如预期的那样,这没有什么区别.

So far my best solution is to assign the data_in signal to another signal, to give it the same delta cycle delay as clk. I thought of using a function to invert the clock as necessary based on the generic as a second parameter to the function, but the clock is used in many places and this did not seem very elegant, and I was note sure it would even solve the problem. Clutching at straws, I also tried making the clock inversion assignment a transport assignment, but, as expected, this made no difference.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Deltas is
    Generic (
        CLK_INVERT : boolean := false
    );
    Port (
        clk : in std_logic;
        data_in : in std_logic
    );
end Deltas;

architecture Behavioral of Deltas is

    -- Signals
    signal data_reg : std_logic := '0';
    signal clk_inverted : std_logic := '0';
    signal data_out : std_logic := '0';

begin

    ClkInvert : if (CLK_INVERT) generate
        clk_inverted <= not clk;
    else generate
        clk_inverted <= clk;
    end generate;

    process (clk_inverted)  
    begin
        if (rising_edge(clk_inverted)) then
            data_reg <= data_in;
        end if;
    end process;

    process (data_reg, data_in) 
    begin
        if (data_reg /= data_in) then
            data_out <= '1';
        else
            data_out <= '0';
        end if;
    end process;

    -- Other entities use `clk_inverted`. Commented out so that this example compiles
    --LowerEntity : entity work.Counter
    --port map (
    --  clk => clk_inverted
    --);

end Behavioral;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity DeltasTest is
end DeltasTest;

architecture Behavioral of DeltasTest is

    signal clk : std_logic := '0';
    signal data_in : std_logic := '0';

begin

    clk <= not clk after 10 ns;

    process (clk)
        variable count : integer := 0;
    begin
        if (rising_edge(clk)) then
            count := count + 1;
            if (count = 4) then
                count := 0;
                data_in <= not data_in;
            end if;
        end if;
    end process;

    uut : entity work.Deltas
    Port map (
        clk => clk,
        data_in => data_in
    );

end Behavioral;

推荐答案

我认为您对 data_in 的额外增量循环的解决方案"可能是最简洁的解决方案.

I think your "solution" of an additional delta cycle on data_in is probably the cleanest simple solution.

从语义上讲,对 clk_inverted 的赋值可以转化为硬件作为时钟信号中的反相器,因此仿真中的增量周期延迟代表了在实数中引入的(可能(*)实数)竞争条件硬件.

Semantically, the assignment to clk_inverted could translate into hardware as an inverter in the clock signal, thus the delta cycle delay in simulation represents a (possibly(*) real) race condition introduced in the real hardware.

因此,模拟行为不仅是一种烦恼,而且是一种有用的属性,警告您必须注意与良好同步设计实践的潜在偏差.

Thus the simulation behaviour is not merely an annoyance but a useful property, warning you of a potential deviation from good synchronous design practice that must be attended to.

(*) 仅可能真实",因为根据技术的不同,综合可能会通过检测相反的边缘将反转推"到下游 FF - 根据 Morten 的评论自动转换您的设计.

(*) Only "possibly real" because, depending on the technology, synthesis may "push" the inversion into the downstream FF by detecting the opposite edge instead - automatically converting your design per Morten's comment.

当额外的增量周期被埋在其他人的 IP 中时,问题就变得更大了,可能是外部组件的模型,例如内存.然后 IP 不再受您的控制,板级仿真可能会在错误的时钟周期中读取或写入数据.

It becomes more of a problem when the additional delta cycle is buried in somebody else's IP, perhaps a model of an external component such as memory. The IP is then no longer under your control, and a board level simulation may read or write data in the wrong clock cycle.

在这里,我的答案是添加近似的 I/O 延迟,或者作为 FPGA 的 I/O 分配中的惯性延迟(来自 FPGA 数据表或综合报告),或者作为 PCB 上的传输延迟.这确保了我的模拟近似于电路板的行为 - 不是完美的,但足够接近让我能够按照正常的同步实践来设计内部逻辑.

Here, my answer is to add approximate I/O delays, either as inertial delays in the FPGA's I/O assignments (from the FPGA datasheet or synthesis report), or as transport delays on the PCB. This ensures my simulations approximate teh behaviour of the board - not perfectly, but closely enough to allow me to design the internal logic following normal synchronous practice.

更简洁的解决方案是基于通用生成两个不同的时钟进程.这完全消除了讨厌的增量循环.

A cleaner solution would be to generate two different clocked processes based on the generic. This eliminates the pesky delta-cycle altogether.

终于!使用 SM 的 2 进程形式,其中保持时钟进程尽可能简单有好处......

FINALLY! a use for the 2-process form of SM, where keeping the clocked processes as simple as possible has a benefit ...

没那么快...

您要重构的行为是时钟边缘检测,它已经从过时的复杂(级别和事件)表达式重构为一个简单的函数.

The behaviour you want to refactor is clock edge detection, which is already refactored into a simple function from the obsolete and complex (level and event) expression.

为什么不进一步重构时钟边沿检测,例如...

Why not refactor the clock edge detection further, for example...

function clock_edge(signal clk : in std_logic) return boolean is
begin
   if CLK_INVERT then
      return falling_edge(clk);
   else 
      return rising_edge(clk);
   end if;
end clock_edge;
...

process (my_clock) is
begin
   if clock_edge(my_clk) then ...

我尚未对此进行测试,以查看综合工具是否可以根据需要实现这一点.有些人可能会,有些人可能不会(如果他们只是对系统提供的功能进行特殊处理而不是正确地完成工作)

I have not tested this to see if synthesis tools can implement this as desired. Some probably will, some may not (if they simply special-cased the system-provided functions instead of doing the job properly)

在分层设计中,此功能将位于一个包中,供任何需要它的实体使用.这带来了泛型的可见性问题:一个建议是在包中使用常量,另一个建议是将泛型作为第二个参数传递给函数.正确的方法可能取决于综合工具施加的限制.

In a hierarchical design, this function would be in a package, used by any entities that needed it. This poses problems of the visibility of the generic : one suggestion would be to use a constant in the package instead, another would be to pass the generic as a second parameter to the function. The right approach probably depends on restrictions imposed by the synthesis tool.

这篇关于我如何解决这个增量周期时钟延迟问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆