如何模拟双向传输延迟

Gre*_*reg 2 verilog system-verilog

例如:连接的 IO A 和 B 之间有 10ns 的 io-to-io 延迟。IO 以 500MHz(2ns 周期)运行。

默认情况下,Verilog 使用惯性延迟作为过滤器。因此将互连线定义为wire #(10ns) io;不起作用,因为它会过滤掉数据。

wire #(10ns) io;

assign io = io_a_en ? a_data_500MHz : 'z;
assign io = io_b_en ? b_data_500MHz : 'z;
Run Code Online (Sandbox Code Playgroud)

传输延迟是单向的。为 IO 上的每个方向创建一个将导致多个驱动程序和反馈循环。

always @(a) b_reg <= #(10ns) a;
always @(b) a_reg <= #(10ns) b;
assign a = b_reg; // feedback b_reg = b = a_reg = a ... and multi-driver
assign b = a_reg; // feedback a_reg = a = b_reg = b ... and multi-driver

assign a = io_a_en ? a_data_500MHz : 'z;
assign b = io_b_en ? b_data_500MHz : 'z;
Run Code Online (Sandbox Code Playgroud)

应该如何建模双向传输延迟?

Gre*_*reg 5

双向传输延迟可以使用具有两个单向传输延迟的驱动程序强度来实现。该模型应将网络分配给 IO 驱动程序的较弱驱动强度。这将优先考虑真正的驱动程序并防止驱动程序冲突。

为防止出现反馈回路,使用驱动强度作为限定符来决定传输延迟是否应分配源值或高阻抗。确定驱动强度的一种简单方法是使用%v,请参阅IEEE Std 1800-2012 § 21.2.1.5强度格式

module bidi_delay #( parameter INERTIAL=0, TRANSPORT=10 ) (
    inout a, b
  );

  reg a2b, b2a;
  reg [23:0] a_strength, b_strength;

  always @(a) begin
    $sformat(a_strength, "%v", a);
    a2b <= #(TRANSPORT) (a_strength[23:16] == "S") ? a : 1'bz;
  end
  always @(b) begin
    $sformat(b_strength, "%v", b);
    b2a <= #(TRANSPORT) (b_strength[23:16] == "S") ? b : 1'bz;
  end

  assign (weak0,weak1) #(INERTIAL) a = b2a;
  assign (weak0,weak1) #(INERTIAL) b = a2b;
endmodule
Run Code Online (Sandbox Code Playgroud)

EDAplayground 上使用 Aldec Riviera、Icarus Verilog 和 GPL Cver 进行测试