SystemVerilog中 `timescale的使用问题

一、`timescale介绍

在 SystemVerilog 中,`timescale 是一个编译器指令,用于定义仿真过程中的时间单位(Time Unit)和时间精度(Time Precision)。

它直接决定了代码中 #10 这种延迟到底代表多长时间。

1. 语法格式

`timescale <时间单位> / <时间精度>

  • 时间单位 (Time Unit):定义数字延迟(如 #10)代表的具体时间。
  • 时间精度 (Time Precision):定义仿真器处理时间的最小刻度。仿真器会将所有时间值舍入到该精度的整数倍。

合法的时间单位和精度: 1s, 100ms, 10ms, 1ms, 100us, 10us, 1us, 100ns, 10ns, 1ns, 100ps, 10ps, 1ps, 100fs, 10fs, 1fs。

cpp 复制代码
`timescale 1ns / 1ps

module tb;
    reg clk;
    
    initial begin
        clk = 0;
        // #5 表示延迟 5 * 1ns = 5ns
        // 精度是 1ps,所以可以写 #5.001 (5001ps)
        #5.0005; 
        clk = 1;
    end
endmodule
2. 注意事项

A. 单位必须大于或等于精度

  • 1ns / 1ps 是合法的,但 1ps / 1ns 是非法的。精度必须比单位更细。
3. `timescale作用范围

`timescale 指令是**基于编译顺序(Compilation Order)**生效的:

如果一个文件没有定义 `timescale,它会继承上一个文件的设置。

一旦编译器在解析过程中遇到了一个 `timescale 指令,它就会对之后所有解析到的模块(module)、接口(interface)等生效,直到遇到下一个 `timescale 指令将其覆盖。

  • 文件 A (1ns/1ps): 定义了 timescale。
  • 文件 B (无定义): 如果在编译列表中紧随 A 之后,B 将继承 A 的 1ns/1ps。
  • 文件 C (1ps/1fs): 重新定义后,后续文件将按 1ps/1fs 执行。

如果所有文件都没定义,仿真器会使用默认值(通常是 1ns/1ns 或 1ns/1ps)。

4. 单位与精度的关系
设置 延迟代码 实际仿真延迟 舍入说明
```timescale 1ns / 1ns`` #1.4 1ns 精度不够,0.4ns 被舍弃
```timescale 1ns / 100ps`` #1.44 1.4ns 精度到 0.1ns,0.04ns 被舍弃
```timescale 1ns / 1ps`` #1.445 1.445ns 精度足够,完全保留

二、timeunit 和 timeprecision

为了避免timescale带来的全局污染,SystemVerilog 引入了timeunit 和 timeprecision关键字声明。

这两个关键字可以出现在以下四个主要作用域中:

  • Module / Interface / Program:最常见的位置,用于锁定特定硬件块的时间基准。
  • Package:用于确保包内的 task 或 function 延迟不随引用者的环境而改变。
  • Compilation Unit Scope ($unit):在所有模块外部(通常是文件顶层)。
  • Class:SystemVerilog 允许在类定义中声明。
1. 在模块/接口内部
cpp 复制代码
module my_design (
    input logic clk,
    input logic rst_n
);
    // 必须放在开头
    timeunit 1ns;
    timeprecision 1ps;

    // 逻辑部分...
    always #5 clk = ~clk; 
endmodule
2. 在 Package 内部

在 package 中使用它们是防止"时间单位污染"的最佳方案。

cpp 复制代码
package my_utils;
    timeunit 1ns;
    timeprecision 1ps;

    task automatic wait_cycles(int n);
        # (n * 1.5); // 这里的 1.5 将严格解析为 1.5ns
    endtask
endpackage

timescale的作用,不会受限于package,比如package中定义的timescale,不只局限于package中生效,依然是遵循上述的编译顺序生效

不要在 package 文件里写 `timescale:这会导致你在 import 这个包的其他文件中遇到莫名其妙的时间对不上的问题。

始终在 package 内部显式声明 timeunit:这样无论包在哪里被编译,其内部的时间逻辑始终保持一致。

3. 优先级与覆盖规则

当多种声明方式并存时,仿真器遵循以下优先级:

  • 最高优先级:模块内部定义的 timeunit / timeprecision。

  • 中等优先级:编译器指令 `timescale(受编译顺序影响)。

  • 最低优先级:仿真器命令行指定的默认值(如 VCS 的 -timescale=1ns/1ps)。

  • 就近原则:模块内部的 timeunit 优先级高于文件顶层的 `timescale。

  • 不可重定义性:在一个作用域(如一个 module)内,只能声明一次 timeunit。你不能在同一个模块里改来改去。

  • 继承性:

    • 如果模块内没有声明 timeunit,它会查找当前的 `timescale 指令。
    • 如果连 `timescale 也没有,它会回退到编译单元($unit)的定义或仿真器默认值。

三、`timescale设置精度太小时,引发的仿真异常问题

问题场景: 最近仿真遇到一个奇怪的问题,我验证环境中的文件 A,里面的 task 有延迟 #1000us;但是当我吃的 rtl 的 flist 中带上 Xilinx 的 memory 库文件 B 时,这个 1000us 的延迟,变成了 1000ns。#1000us 前后都加了打印确认的。如果不带这个文件 B,就是实际 delay 1000us。

疑点:而且 A 文件的编译顺序是在 B 文件之前,按理说不应该受到 B 文件 timescale 的影响。

排查:我使用 -diag timescale 命令查看了 A 的 timescale 是 1ns/1ps,B 的 timescale 是 1ps/1ps。

网上也有网友遇到了我类似的问题,就是 timescale 精度过高时,出现 1000us 被识别成 1000ns 的问题。


针对这个问题的深度解析:

之所以 A 在 B 之前编译仍受影响,是因为在 VCS 的 Elaboration(细化) 阶段,仿真器会确定一个全局的 最小仿真步长(Precision)。当 B 文件引入了 1ps 这种极高精度时,整个仿真引擎的单位换算逻辑可能会发生微妙的变化。如果 A 文件中没有显式的 timeunit 声明,仅靠 `timescale 指令,在复杂的混合精度环境下,带单位的延迟(如 us)有时会被工具错误地截断或舍入到当前的基准单位(ns)上。

终极方案 :使用大杀器 -override_timescale

如果你无法修改代码位置,或者 $unit 污染太严重,建议直接在 VCS 命令行强制统一。

由于你发现 Xilinx 库 B 是 1ps/1ps,而你想要 1ns/1ps 或 1us,可以在编译命令中加入:

vcs -override_timescale=1ns/1ps

原理:这会无视所有文件里的 `timescale 指令和 timeunit 声明,强行让整个仿真环境整齐划一。

注意:这会解决 #1000us 识别错的问题,但如果 Xilinx 的某些模拟电路 IP 必须依赖 1ps 精度才能工作,可能会导致那些 IP 行为异常。

这个本质问题,应该是仿真器版本是vcs 2017版本,可能比较老。

相关推荐
蓝天下的守望者9 天前
uvm_field_automation机制学习
uvm
Chef Chip10 天前
定宽数组的随机约束
systemverilog·数字ic验证
Piri_LogicBldr20 天前
【验证技能树】UVM 源码解读11 -- TLM2 —— Blocking vs Non-blocking 背后的建模取舍
uvm·芯片验证·验证技能
北方孤寂的灵魂21 天前
systemverilog中随机std::randomize的用法
verilog·systemverilog·sv·数字验证
蓝天下的守望者22 天前
uvm_config_db机制学习
uvm
蓝天下的守望者22 天前
由continue引发的一个debug灾难
算法·systemverilog
Piri_LogicBldr23 天前
【验证技能树】UVM 源码解读10 --TLM 是通信机制,还是架构边界?
uvm·芯片验证·验证技能
蓝天下的守望者1 个月前
systemverilog系统函数$test$plusargs和$value$plusargs
systemverilog·芯片验证
lbt_dvshare1 个月前
MTCMOS flow
systemverilog