繁体   English   中英

采样和驱动信号的 SV/Verilog 时序

[英]SV/Verilog timing of sampling and driving signals

我有一个类驱动程序(用 UVM 编码)和一个模块 sampler_n_dummy_gnt 如下(为本问题的目的而简化):

class driver extends uvm_driver #(bus_trans);
    ...
    task run_phase();
        forever begin
            seq_item_port.get_next_item(bus_trans_h);
            drive_item(bus_trans_h);
            ...
        end
    ...
    endtask

    task drive_item();
        vif.sel = 1;
        vif.req = 0;
        @(posedge vif.clk);
        vif.req = 1;
        // #1; // this delay needed to prolong req for 1 clock
        if (vif.gnt == 1)
            @(posedge vif.clk);
        else begin
            while (vif.gnt == 0)
                @(posedge vif.clk);
            end
        end
        vif.req = 0;
    endtask
endclass
module sampler_n_dummy_gnt;
    logic clk, rstn;
    int rdelay;

    bus_interface vif(clk, rstn);

    always #10ns clk = ~clk;

    always @(posedge vif.req) begin
        rdelay = $urandom_range(0,5);
        if (rdelay != 0) begin
          for (int i=0; i<rdelay; i=i+1) begin
            vif.gnt = 0;
            @(posedge vif.clk);
          end
        end
        vif.gnt = 1;
    end
endmodule

基本上,驱动程序模拟一个协议,该协议指定它应该在有新事务时断言sel 一个周期后,它应该断言req 然后它一直等到gnt为高电平,并且仅在一个周期后取消断言req

采样器等待req的断言,并根据随机生成的数字在断言gnt之前等待一定数量的时钟周期。 所以要么没有延迟,要么有一些延迟,最多 5 个周期。

在我遇到第二笔交易之前,第一笔交易还可以。 在时钟 7 的位置, gnt被取消断言,因此req应该保持高电平,直到它在时钟 8 看到gnt断言。但是,从时钟 7 开始,我再也没有看到req断言(即它保持为 0)。 我怀疑在时钟 7 的位置,它看到gnt = 1但跳过了if-else条件并直接驱动req = 0 所以我必须添加我在上面评论过的那一行,以获得预期的场景。 有人可以帮助解释为什么需要延迟吗?

                (Expected)                               (Actual)
        1   2   3   4   5   6   7   8          1   2   3   4   5   6   7   8
       _   _   _   _   _   _   _   _          _   _   _   _   _   _   _   _  
clk  _| |_| |_| |_| |_| |_| |_| |_| |_      _| |_| |_| |_| |_| |_| |_| |_| |_
       _______________     ___________        _______________     ___________
sel  _|               |___|                 _|               |___|
           ___________         _______            ___________         
req  _____|           |_______|             _____|           |_______________   
                   ___________     ___                    ___________     ___
gnt  _____________|           |___|         _____________|           |___|

我假设clkvif.clkvif.pclk实际上都是相同的信号。

您的代码在处理同步信号方面存在许多问题。

  • 除非您正在处理异步逻辑,否则您应该只使用一个时钟边沿事件,而不是另一个信号的边沿。
  • 对同步信号进行赋值时,始终使用非阻塞赋值<=
  • 确保对任务的第一次调用与时钟沿同步

由于您没有发布完整的代码,我只能提出这个建议

class driver extends uvm_driver #(bus_trans);
    ...
    task run_phase();
       @(posedge vif.clk; // initial sync
       forever begin
            while (!seq_item_port.try_next_item(bus_trans_h)
               @(posedge vif.clk;
            drive_item(bus_trans_h);
            ...
        end
    ...
    endtask

    task drive_item();
        vif.sel <= 1;
        vif.req <= 0;
        @(posedge vif.clk);
        vif.req <= 1;
        @(posedge vif.clk iff vif.gnt);
        vif.req <= 0;
    endtask
endclass

从 SystemVerilog (SV) 类域采样和驱动同步数据可能会出现问题。 在接口内部使用 SV 时钟块是标准解决方案。 使用时钟模块需要了解时钟模块、时钟驱动分配和时钟事件。 它还需要从界面的角度来理解输入和输出的感觉。 我列出的论文显示了使用时钟模块时犯的一些经典错误(不要“绕过”CB。

为了帮助理解:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM