1

我目前正在自学 Verilog,并浏览了一些我发现的教程,有两件事让我感到困惑,即如何具体计算在将输入更改为组合电路后需要延迟多少时间,以及项目的顺序是什么在您的代码中执行。我通常了解实际电路具有上升/下降延迟时间,并且您希望延迟输出,以便您的输入在计算输出之前生成一个值,但我想知道具体情况。

所以,这里有一个例子:

module dflipflop (d,clk,reset,q);
input d, clk, reset;
output q;
reg q;

always @ (posedge clk or posedge reset) begin
  if (reset) begin
    q <= 0;
  else begin
    q <= #2 d; //why did I need to delay this 2 time units?
  end
 end
end module

module main;
reg d, clk, rst;
wire q;
dflipflop dff(d,clk,rst,q);

inital begin
  forever begin
    clk = 0;
    #5
    clk = 1;
    #5
    clk = 0; //why do I need to reset the clk to 0 if this is a forever block and my first assignment is clk = 0 in the beginning? 
  end
end

 initial begin
  d=0; rst=1; 
  #4  //why #4? How did they calculate that?
  d=1; rst=0; 
  #50
  d=1; rst=1;
  #20
  d=0; rst=0; 
 end  
end module

我的一些问题嵌入在代码的注释中。然而,我的另一个困惑是时间问题。在主模块的开头,我使用我在上面 main 中定义的参数实例化了一个名为 dff 的 dflipflop 模块。我的代码在哪里说:当我更改 main 中的输入时重建模块/重新计算 Q?我没有看到链接。

4

3 回答 3

4

关于您的具体问题:

//why did I need to delay this 2 time units?

你没有。向时钟分支而不是复位分支添加传输延迟几乎没有意义。

//why do I need to reset the clk to 0 if this is a forever block and my first assignment is clk = 0 in the beginning?

你没有;模型有缺陷。删除第一个clk=0,或将其移至forever.

//why #4? How did they calculate that?

不知道 - 这只是刺激生成的任意延迟。没关系,只要它“足够长”。

一般要点:

  1. 在编写 HDL 代码时,您不关心指定延迟;这几乎总是工具的工作。您的工具将计算出真正的硅延迟,并使用 sdf 等将它们反注释到您的代码中 specify blocks。如果您想了解详细信息,请查看合成器或布局布线工具输出的仿真模型。
  2. 只要您小心使用阻塞和非阻塞分配,那么您的代码就会“工作”,即使您没有明确地将延迟放入其中。“工作”意味着输出以正确的顺序更改以保留您所需的功能。
  3. 我认为您可能对“上升/下降延迟”和“延迟输出”的理解感到困惑。一般来说,在 HDL 级别,您从不关心信号上升或下降时间;一切都发生在阈值电压下。输入在时间 x 发生变化,相关输出在稍后的某个时间发生变化。这是传播延迟。对于时钟电路,prop 延迟将取决于输出是变为 0 还是变为 1,这导致不幸的术语涉及“上升延迟”或“下降延迟”(实际上传播延迟为 1 或 0)。您不会“延迟输出,以便您的输入在计算输出之前生成一个值”。除非在特殊情况下,您会立即计算您的输出,
于 2013-05-24T08:23:27.340 回答
1

如果您的dflipflop模块将被合成,则不应有#2延迟。有时人们会添加这些延迟,因为他们正在使用不同编码风格的混合进行模拟:行为和结构。有时结构代码有延迟,这会使您的行为代码行为不正确。

也许这就是本意:

inital begin
  clk = 0;
  forever begin
    #5
    clk = 1;
    #5
    clk = 0;
  end
end

也许#4用于在时间 = 5 时释放rst第一条边之前的位置。clk

于 2013-05-23T21:03:05.460 回答
1

q <= #2 d;这是时钟到 q 的延迟。该数字很可能是任意的,但它可能来自特定触发器设计的特征。许多设计人员在时钟到 q 上设置了一个小的延迟,以使查看波形更容易。通常,您希望这个数字非常小,并且几乎总是小于时钟周期。

对于您的时钟发生器,clock = 0只要有分号,多余的就无关紧要。这很可能是设计师喜欢使用的编码风格。以下两个都相当于你的时钟,只是写法不同:

always begin
  clk = 0;
  #5;
  clk = 1;
  #5;
end
// or
initial begin
  clk = 0;
  forever #5 clk = !clk;
end

这是因为设计人员希望测试在第一个时钟 (@ )#4之前结束设计的复位。#5这也给出了所有以下延迟(是时钟周期的倍数#10)和#1建立时间。

dflipflip只会在有posedge clkor时做出反应posedge reset。如果reset为高,q则将分配给0。如果reset和 的上升沿clk被检测到,d则将被采样,然后将#2采样值分配给q

这是关于正在发生的事情的一步购买步骤:

initial begin
  d=0; rst=1;  /* simulation time #0, rst goes 1'bx->1'b1 (posedge) therefore q goes 1'bx->1'b0 */
  #4  
  d=1; rst=0; /* 
       simulation time #4, rst goes low, sill no posedge clk therefore dflipflop does nothing 
       simulation time #5 first posedge clk therefore sample d (1)
       simulation time #7 q is assigned to 1 (sampled d)
       simulation time #15 posedge clk therefore  sample d (1) again
       simulation time #17 q is assigned to 1 (sampled d) again
       ... repeat pattern ...
       simulation time #45 posedge clk therefore sample d (1) again
       simulation time #47 q is assigned to 1 (sampled d) again */
  #50
  d=1; rst=1; /* 
       simulation time #54, rst goes high therefore assign q to 0 
       simulation time #55 posedge clk, rst==1 therefore assign q to 0
       simulation time #65 posedge clk, rst==1 therefore assign q to 0 */
  #20
  d=0; rst=0; /* 
     simulation time #74, rst goes low therefore no change
     simulation time #74, initial block ends */
end  
于 2013-05-23T21:15:04.933 回答