📜  Verilog时间刻度

📅  最后修改于: 2021-01-11 15:01:40             🧑  作者: Mango

Verilog时标

Verilog仿真取决于如何定义时间,因为仿真器需要知道时间上#1的含义。 timescale编译器指令指定了跟随其的模块的时间单位和精度。

句法

`timescale /
// for example
`timescale 1ns/1ps
`timescale 10us/100ns
`timescale 10ns/1ns

time_unit是延迟和模拟时间的度量,而time_precision指定在模拟中使用延迟值之前如何取整。

使用以下时标构造可在同一设计中使用不同的时间单位。设计中的延迟规范无法综合,因此无法转换为硬件逻辑。

  • '时标为基本计量单位和时间精度。
  • $ printtimescale系统任务显示时间单位和精度。
  • $ time$ realtime系统函数返回当前时间,默认的报告格式可以用另一个系统任务$ timeformat更改
Character Unit
s seconds
ms milliseconds
us microseconds
ns nanoseconds
ps picoseconds
fs Femtoseconds

在这些规范的整数可以是1,10或100和<字符>指定单元可以在上面的表中提到的任何值。

例1:1ns / 1ns

// Declare the timescale where time_unit is 1ns
// and time_precision is also 1ns
`timescale 1ns/1ns

module tb;
    // To understand the effect of timescale, let us
    // drive a signal with some values after some delay
  reg val;

  initial begin
      // Initialize the signal to 0 at time 0 units
    val <= 0;

    // Advance by 1 time unit, display a message and toggle val
    #1         $display ("T=%0t At time #1", $realtime);
    val <= 1;

    // Advance by 0.49 time unit and toggle val
    #0.49     $display ("T=%0t At time #0.49", $realtime);
    val <= 0;

    // Advance by 0.50 time unit and toggle val
    #0.50     $display ("T=%0t At time #0.50", $realtime);
    val <= 1;

    // Advance by 0.51 time unit and toggle val
    #0.51     $display ("T=%0t At time #0.51", $realtime);
    val <= 0;

     // Let simulation run for another 5-time units and exit 
    #5 $display ("T=%0t End of simulation", $realtime);
  end
endmodule

第一个delay语句使用#1,使模拟器等待精确的1倍时间单位,使用timescale指令将其指定为1ns。第二个延迟语句使用0.49,这小于一个时间单位的一半。

但是,时间精度指定为1ns,并且模拟器不能小于1ns,这使其舍入给定的延迟语句并产生0ns。因此,第二个延迟无法延长仿真时间。

第三条延迟语句恰好使用了时间单位[hl]#0.5 [/ lh]的一半,模拟器再次将值取整以获得#1,它代表一个完整的时间单位。因此,这将在T = 2ns时打印出来。

第四个延迟语句使用的值大于时间单位的一半,并且也会四舍五入,从而使显示语句在T = 3ns时被打印。执行后,将给出以下输出:

ncsim> run
T=1 At time #1
T=1 At time #0.49
T=2 At time #0.50
T=3 At time #0.51
T=8 End of simulation
ncsim: *W,RNQUIE: Simulation is complete.

仿真运行的预期时间为8ns,但请注意,该波形在每纳秒之间没有更小的分度。这是因为时间的精度与时间单位相同。

示例2:10ns / 1ns

与上一个示例相比,此示例中所做的唯一更改是时间范围已从1ns / 1ns更改为10ns / 1ns。因此时间单位为10ns,精度为1ns。

// Declare the timescale where time_unit is 10ns
// and time_precision is 1ns
`timescale 10ns/1ns

// Testbench is the same as in the previous example
module tb;
    // To understand the effect of timescale, let us
    // drive a signal with some values after some delay
  reg val;

  initial begin
      // Initialize the signal to 0 at time 0 units
    val <= 0;

    // Advance by 1 time unit, display a message and toggle val
    #1         $display ("T=%0t At time #1", $realtime);
    val <= 1;

    // Advance by 0.49 time unit and toggle val
    #0.49     $display ("T=%0t At time #0.49", $realtime);
    val <= 0;

    // Advance by 0.50 time unit and toggle val
    #0.50     $display ("T=%0t At time #0.50", $realtime);
    val <= 1;

    // Advance by 0.51 time unit and toggle val
    #0.51     $display ("T=%0t At time #0.51", $realtime);
    val <= 0;

     // Let simulation run for another 5-time units and exit 
    #5 $display ("T=%0t End of simulation", $realtime);
  end
endmodule

通过将使用#指定的延迟乘以时间单位来获得实际的仿真时间,然后根据精度进行四舍五入。然后,第一个延迟语句将产生10ns,第二个延迟语句将产生14.9,将其舍入为15ns。

第三条语句类似地加上5ns(0.5 * 10ns),总时间变为20ns。第四位再加上5ns(0.51 * 10),将总时间增加到25ns。

ncsim> run
T=10 At time #1
T=15 At time #0.49
T=20 At time #0.50
T=25 At time #0.51
T=75 End of simulation
ncsim: *W,RNQUIE: Simulation is complete.

注意:波形中的基本单位为数十纳秒,精度为1ns。

例3:1ns / 1ps

与上一个示例相比,此示例中所做的唯一更改是时间范围已从1ns / 1ns更改为1ns / 1ps。因此时间单位为1ns,精度为1ps。

// Declare the timescale where time_unit is 1ns
// and time_precision is 1ps
`timescale 1ns/1ps

// Testbench is the same as in the previous example
module tb;
    // To understand the effect of timescale, let us
    // drive a signal with some values after some delay
  reg val;

  initial begin
      // Initialize the signal to 0 at time 0 units
    val <= 0;

    // Advance by 1 time unit, display a message and toggle val
    #1         $display ("T=%0t At time #1", $realtime);
    val <= 1;

    // Advance by 0.49 time unit and toggle val
    #0.49     $display ("T=%0t At time #0.49", $realtime);
    val <= 0;

    // Advance by 0.50 time unit and toggle val
    #0.50     $display ("T=%0t At time #0.50", $realtime);
    val <= 1;

    // Advance by 0.51 time unit and toggle val
    #0.51     $display ("T=%0t At time #0.51", $realtime);
    val <= 0;

     // Let simulation run for another 5-time units and exit 
    #5 $display ("T=%0t End of simulation", $realtime);
  end
endmodule

看到时间单位缩放以匹配新的1ps精度值。时间以最小分辨率表示,在这种情况下为皮秒。

ncsim> run
T=1000 At time #1
T=1490 At time #0.49
T=1990 At time #0.50
T=2500 At time #0.51
T=7500 End of simulation
ncsim: *W,RNQUIE: Simulation is complete.

默认时标

尽管预计Verilog模块在模块之前定义了时间范围,但模拟器可能会插入默认时间范围。

可以使用系统任务$ printtimescale来打印在Verilog详细说明的层次结构中的任何范围内应用的实际时间标度,该任务将范围作为参数。

module tb;
    initial begin
        // Print timescale of this module
        $printtimescale(tb);
        // $printtimescale($root);
    end
endmodule

注意:时间刻度指令未放置在此模块之前。模拟器最终应用了1ns / 1ns的时标值。

xcelium> run
Time scale of (tb) is  1ns /  1ns
xmsim: *W,RNQUIE: Simulation is complete.

标准时标范围

默认情况下,放置在文件中的timescale指令将应用于该指令之后的所有模块,直到定义另一个timescale指令为止。

`timescale 1ns/1ps

module tb;
  des m_des();
  alu m_alu();

  initial begin
    $printtimescale(tb);
    $printtimescale(tb.m_alu);
    $printtimescale(tb.m_des);
  end
endmodule

module alu;

endmodule

`timescale 1ns/10ps

module des;

endmodule

在上面的示例中, tbalu的时间标度为1ns / 1ns,而des的时间标度为1ns / 10ps,这是因为将指令放置在des的模块定义之前。

xcelium> run
Time scale of (tb) is  1ns /  1ps
Time scale of (tb.m_alu) is  1ns /  1ps
Time scale of (tb.m_des) is  1ns /  10ps
xmsim: *W,RNQUIE: Simulation is complete.

Verilog文件

可以使用`include指令,将其他文件包含在当前文件中,include指令是预处理程序指令,使编译器在编译之前将所包含文件的内容放入。

这等效于简单地将另一个文件的全部内容粘贴到此主文件中。

// main.v
`timescale 1ns/1ps

module tb;
  des m_des();
  alu m_alu();

  initial begin
    $printtimescale(tb);
    $printtimescale(tb.m_alu);
    $printtimescale(tb.m_des);
  end
endmodule

`include "file_alu.v"
`include "file_des.v"

// file_alu.v
module alu;
endmodule

// file_des.v
`timescale 1ns/10ps

module des;

endmodule

可以看到结果与前面的示例完全相同。 alu的时间标度为1ns / 1ps,因为它是最后一个有效的指令,直到编译器发现alu定义坚持将其放在另一个文件中为止。

des的时间范围为1ns / 10ps,因为该指令在其定义之前已被替换。

xcelium> run
Time scale of (tb) is  1ns /  1ps
Time scale of (tb.m_alu) is  1ns /  1ps
Time scale of (tb.m_des) is  1ns /  10ps
xmsim: *W,RNQUIE: Simulation is complete.

交换文件可以更改时间表。

文件的包含顺序在重新定义时间刻度指令中起着重要作用,这在下面的示例中很明显。

// main.v
`timescale 1ns/1ps

module tb;
  des m_des();
  alu m_alu();

  initial begin
    $printtimescale(tb);
    $printtimescale(tb.m_alu);
    $printtimescale(tb.m_des);
  end
endmodule

// Swapped order of inclusion
`include "file_des.v"
`include "file_alu.v"

// file_alu.v
module alu;
endmodule

// file_des.v
`timescale 1ns/10ps

module des;

endmodule

看到模块alu现在的时间标度为1ns / 10ps。

xcelium> run
Time scale of (tb) is  1ns /  1ps
Time scale of (tb.m_alu) is  1ns /  10ps
Time scale of (tb.m_des) is  1ns /  10ps
xmsim: *W,RNQUIE: Simulation is complete.

这是在文件顶部使用timescale指令的原因之一,以便该文件中的所有模块都采用正确的时间标度,而不考虑文件是否包含在内。

但是,这种方法可能使得难以在不更改每个文件的情况下以不同的时标精度进行编译。

许多编译器和模拟器还提供了覆盖默认时间标度值的选项,该选项将应用于所有模块。