Home Articles

为什么verilog模拟器将净延迟建模为惯性延迟而不是传输延迟?

Asked
Viewed 1971 times
1

我正在测试台上连接DDR模型,使用具有净延迟的电线来模拟电路板上的走线延迟 . 迹线可以在其传输线中保持1或2位,但由于模拟器将净延迟建模为惯性延迟,因此所有位都被滤除为毛刺 . 我甚至没有这样的时钟 . SystemVerilog规范在此主题上并不明确 . 因此,我猜测模拟器不希望在性能和存储方面产生成本,将其建模为传输延迟 . 但是,我坚信传输延迟是用于净延迟的正确方法,因为否则用自己的延迟建模每个bidir信号的麻烦是巨大的 . 你怎么看?

这是我的测试用例 .

`timescale 1ps/1ps

module sim_top  ();

parameter realtime NET_DELAY = 80ps;
parameter realtime PULSE_DELAY = 50ps;

logic driver;
initial begin
  driver = 0;
  forever #PULSE_DELAY driver = !driver;
end

wire #NET_DELAY a;
assign a = driver;
always @(posedge a or negedge a) begin
  $display("a=%b @ %t", a, $time);
end

logic b;
always @(*) begin
  b <= #NET_DELAY driver;
end

always @(posedge b or negedge b) begin
  $display("b=%b @ %t", b, $time);
end


initial begin
 #1ns;
 $finish;
end
endmodule

2 Answers

  • 0

    可以使用#delays with non-blocking assighments来模拟传输延迟:

    always @*
       out <= #delay input;
    

    这接近于惯性延迟:

    assign
        #delay out = input;
    

    其余的主要是行为模拟工件,应仅在测试平台中使用 .

    我发现这篇文章对这个问题非常有用:http://www-inst.eecs.berkeley.edu/~cs152/fa06/handouts/CummingsHDLCON1999_BehavioralDelays_Rev1_1.pdf

  • 0

    因此,我猜测模拟器不希望产生性能和存储成本,将其建模为传输延迟 .

    我可以想象你是如何得到这种推理的 . 据我所知,你的假设是不正确的 .

    真正的逻辑门具有惯性延迟 . 此延迟是由RC(电阻和电容)引起的,该RC继承到器件,路由或有意添加 . Verilog使用惯性延迟来模拟实际逻辑的延迟行为 .

    我找不到引文,但是通过与具有Verilog之前经验的工程师的讨论,早期的Verilog只模拟了门(想想Verilog原语 andornandbufif0 等) . 分配语句和总是在一段时间后添加块以及合成的可能性 . 非阻塞( <= )的分配在很晚之后被添加(并且从我听到的VHDL中复制),但是在Verilog之前由IEEE提出 .

    以与gate相同的方式分配语句句柄延迟 . 见IEEE1800-2012§10.3.3连续分配延迟

    给予连续分配的延迟应指定右手操作数值变化与左手分配之间的持续时间 . 如果左手引用标量网,则应以与门延迟相同的方式处理延迟;也就是说,可以给出输出上升,下降和变为高阻抗的不同延迟(见28.16) .

    我猜测分配语句使用与门相同类型的延迟来重用现有代码(在模拟器内,而不是Verilog代码)来管理延迟并保持延迟定义的连续性 . 它也更容易映射,例如: assign #1 out = in;buf #1 (out,in); 相同 .

    对于实际电路,当您希望延迟为10且滤波器为0.5时,您需要具有小RC的20个延迟单元链 . 如果你想要一个10的延迟和滤波器,你可以使用一个带有大RC的延迟单元 . 理论上,合成器可以将这种延迟信息用于目标延迟和过滤控制(我想不出任何实际上这样做的合成器;我知道的所有合成器都忽略了RTL延迟) .

    通常,非阻塞( <= )分配用于同步逻辑(边沿敏感触发器和电平敏感锁存器) . 传输延迟是主要的例外,但仅应用于不能合成的行为建模 . 如果您知道实际延迟路径的过滤量,我建议将其编码如下:

    reg out;
    wire #(FILTER) in_filtered = in;
    always @* out <= #(TOTAL_DELAY-FILTER) in_filter; // must be >=0.0
    

    与纯惯性延迟方法相比,它更干净,CPU密集度更低:

    localparam LENGTH = TOTAL_DELAY/FILTER; // must be an integer >=2
    wire out;
    wire [LENGTH-2 : 0] delay_chain;
    assign #(FILTER) {out,delay_chain} = {delay_chain,in};
    

Related