SV 仿真的常识

文章目录

SV对verilog的扩展

SystemVerilog 和 Verilog 的语法标准由 **IEEE(美国电气和电子工程师协会)**制定,正式文档如下:


📘 标准文档名称:

名称 简称 最新版本 标准编号 是否免费
Verilog Verilog HDL IEEE 1364-2005 IEEE Std 1364-2005 ❌ 付费
SystemVerilog SystemVerilog HDL IEEE 1800-2017 IEEE Std 1800-2017 ❌ 付费
SystemVerilog 最新合并版 Unified HDL (Verilog + SystemVerilog) IEEE 1800-2023 IEEE Std 1800-2023 ❌ 付费
  • SystemVerilog(SV)相对于传统 Verilog 的主要扩展和增强,涵盖语法、数据类型、验证特性等方面。
类别 Verilog 特性 SystemVerilog 扩展 说明 参考文献
数据类型 regwire 新增 logicbitintbyteshortintlonginttimeenumstructunionstringchandle 更强的类型安全、结构化数据、枚举和字符串支持 (代码覆盖率原理简介原创 - CSDN博客) (see 1)
数组与集合 连续向量 reg [7:0] a; 动态数组 int da[];、关联数组 int aa[string];、队列 int q[$]; 支持可变长度和哈希索引结构 (代码覆盖率原理简介原创 - CSDN博客) (see 2)
接口与包 modulefunctiontask interfaceprogrampackageimport/export 接口封装信号集合,package 封装共享声明 (代码覆盖率原理简介原创 - CSDN博客) (see 3)
模块化 & 生成 generate generate 扩展语法、localparamtypedef 更灵活的生成语法,本地参数和类型重命名 (代码覆盖率原理简介原创 - CSDN博客) (see 4)
线程 & 时间控制 alwaysinitial always_ffalways_combalways_latchuniquepriority 明确组合/时序/锁存块,优化仿真和综合 (代码覆盖率原理简介原创 - CSDN博客) (see 5)
约束随机化 classrandconstraintsolve...before 面向验证的随机化对象支持 (代码覆盖率原理简介原创 - CSDN博客) (see 6)
面向对象 支持 class、继承 extends、多态、new() 构造函数 引入面向对象编程,验证组件化 (代码覆盖率原理简介原创 - CSDN博客) (see 7)
断言 & 覆盖率 SVA 断言 assertcovergroupcoverpointcross 内置断言和功能覆盖率建模 (代码覆盖率原理简介原创 - CSDN博客) (see 8)
TLM 接口 uvm_sequence_itemuvm_portuvm_exportuvm_analysis_port 事务级建模接口,为 UVM 提供通信通道 (代码覆盖率原理简介原创 - CSDN博客) (see 9)
并发扩展 fork/join fork...join_anyfork...join_none-多种 join 语义 更灵活的并发控制 (代码覆盖率原理简介原创 - CSDN博客) (see 10)

简要说明:

  1. 数据类型和数组 :SV 增加了丰富的强类型和容器类型,解决了 Verilog 只有 reg/wire、固定向量的限制。
  2. 接口与包 :通过 interfacepackage,SV 实现了代码重用与封装,提高了可维护性。
  3. 线程与时间控制 :引入更语义化的 always_ff 等,帮助综合工具和仿真工具区分不同用途。
  4. 面向对象 & 约束随机:SV 将验证带入语言层面,结合 UVM 形成强大的验证生态。
  5. 断言 & 覆盖率:SystemVerilog Assertions (SVA) 和功能覆盖率让验证更加系统化。
  6. 事务级建模 (TLM):提供通用接口,让组件间事务通信高度解耦,支撑 UVM 框架。

从SV到仿真

通用过程解读

  • 编译
c 复制代码
语法和语义分析 , 进行编译 , 编译出 中间文件
  • 建模
c 复制代码
按照设计集成关系, 组成顶层模块
    1. 模块例化
    2. 接口例化
    3. 程序例化
    4. 层次集成
    5. 计算参数
    6. 解决层次信号引用
    7. 建立模块连接
// 类似C代码的link阶段
  • 仿真
c 复制代码
建立RTL模型和参数验证环境, 以周期驱动(cycle-driven)或事件驱动(event-driven)的方式进行仿真

实例解读

  • Icarus Verilog(iverilog), VCS 和 Verilator 的典型使用流程
阶段 vcs verilator iverilog
编译(compilation) .sv.o .sv.o iverilog -g2005-sv -o tb.vvp <files>.sv
建模(elaboration) .osimv .oobj_dir/V$(TB_NAME) 隐式在生成 tb.vvp 时完成,不再单独产物
仿真(simulation) ./simv ./obj_dir/V$(TB_NAME) vvp tb.vvp
text 复制代码
与 VCS 和 Verilator 不同,
Icarus Verilog **不生成可执行 ELF**,也不生成 C++ 代码。
它在编译阶段就完成了 elaboration,将所有模块实例化和连接,并将结果编码进 `tb.vvp`。
无需单独生成可执行文件(`.o` 或 `simv`)。

SV的仿真过程


并行

SystemVerilog 采用 模块(module 作为设计的基本单元,整个电路从 顶层模块 开始,逐层实例化与端口互联,最终形成完整的层次化结构。

c 复制代码
在 SV世界中, 仿真一旦运行起来, 一个module 就类似于 软件世界中的 一个线程(不区分线程进程)
那么就必然有线程之间的同步与通信
    1. 信号的变化(事件触发)  //  @(posedge clk)
    2. 对特定事件的等待(时钟周期) // wait 
    3. 延时(固定延时) // #200
一般来说, module 中的语句都是顺序的, 但是如果你想 并行, 就需要用fork 关键字 来创建 并行结构(即创建新线程)

即 软件世界中的 一个线程 在硬件世界中的类比为 // 拓展知识 请查看 https://blog.csdn.net/u011011827/article/details/147444792
    1. module
    2. initial 包围的 硬件代码 
    3. always  包围的 硬件代码
    2. fork 包围的 硬件代码

仿真颗粒度

c 复制代码
仿真需要指定 仿真时的 时间单位和精度
    
不管是 用户TB ,还是设计指定的 时间都要 以 timeprecision  算(四舍五入)出来.
搞 timeunit 这个关键字,只是为了 代码的可读性 : 让用户无需每次都写带单位的延时,只需写 #1 即可代表 #(1 * timeunit)
c 复制代码
一般 timeprecision 指定的单位 比 timeunit 小
timeprecision 不是越小越好,太细反而开销大(调度器要管理的时间槽变多,导致仿真慢). // 这个要解读 调度, 来深入理解
合适的 timeprecision
    看设计的最快时钟------假如最高 500 MHz(周期 2ns),那么 timeprecision 设 100ps 就够(20 个步)。
    看需要模拟的最小延时------如果你要模拟 #0.5ns 这类延时,就要精度细于 500ps;否则会被舍入。
    按 10 的级数对齐------常用 1ns/100ps、1ns/10ps、100ps/10ps 这样的十倍关系,既好计算又利于读写。

SV仿真调度

c 复制代码
sv代码中module是并行的,但是cpu(仿真sv代码的时候)是顺序执行
那么在 0 时刻 ,有很多 并行代码(假设有10条语句) 需要仿真
   那么 谁先做谁后做呢 , 这就是 仿真调度 要考虑的事情

部分规则:
	时间片   : timeprecision指定的单位 // 如果 timeprecision = 100ps , 那么带 时间槽所在的时刻 只能是 100ps的倍数
    同槽不同事:同一槽位的多条语句,靠 "事件区域" + "申明顺序" 决定先后。
    效率至上  :调度器只跳到下一个有事的槽位,不会浪费时间检查空槽 
        // 即 存在一种可能, 200ps 时, 没有事件位于这一时刻, 那么 根本就不会 检查 200ps 是否有 事情要做 
        // 即 不会 在 200ps 这个刻度 浪费 一丁点cpu时间
  1. 同一时间槽内的执行次序就是"仿真调度"
    在每个离散的时间点(时间槽)上,仿真器会把所有待执行的事件分到几个"事件区域"(Active、Inactive、NBA、Monitor...),再在各区域内按声明顺序执行。这套从区域到区域、从语句到语句的调度机制,就称作仿真调度(event scheduling)。
  2. 仿真调度是为模拟并行硬件而设计的
    真实 CPU 是串行执行指令的,而硬件模块在同一时刻是并行更新欧。仿真器内部用"调度"来用顺序算法准确地再现硬件的并行行为------保证同时发生的并行事件能在同一个时间点"好像同时"地被执行,只是按照调度规则分批跑完。
  3. 实际硬件里没有"调度器"这层概念
    硬件的寄存器、门电路、互连网是真正同时更新的,不存在"先做 A 再做 B"的软件调度。调度只是仿真环境里用来序列化并行行为的实现细节。
  4. 仿真的时候 有 仿真调度, 但是硬件上没有, 怎么保证在仿真时能过的代码在硬件上一定没问题呢?
    • 可综合子集:设计时只用可综合的 SV/Verilog 语法(符合综合工具的语义),这样仿真行为和综合后硬件逻辑在功能上是等价的。
    • 静态时序分析 (STA):综合后用 STA 工具检查硬件的时序收敛,保证所有信号路径在目标时钟下都能按预期收敛。
    • 门级仿真 :在部分关键场景下,还会跑门级网表加 SDF back-annotation 仿真,验证时序与 RTL 仿真的一致性。
      通过以上流程,仿真"看得见"的并行逻辑,以及综合后验证的时序约束,都能确保最终硅片上真实并行电路的正确性。
调度区域

SystemVerilog 离散事件调度器在每个时间槽(time slot)内依次执行的主要仿真调度区域(也称为"事件区域")及其作用:

区域序号 调度区域 英文名 / 缩写 执行内容示例 说明
1 Active Active Region alwaysinitial 块中无延时语句之后的语句 执行所有因为当前时间到达而"就绪"的过程后的第一批语句
2 Inactive Inactive Region disable fork@(事件触发) 处理在 Active 区域产生的新就绪过程,但不再执行延时、NBATasks
3 NBA Non-Blocking Assigns 所有<=非阻塞赋值更新 收集并一次性更新非阻塞赋值,避免与 Active 中的顺序冲突
4 Monitor Monitor Region uvm_monitor$monitor、覆盖率采集、断言 观察信号变化,不影响驱动;常用于更新覆盖率、断言检查
5 Observed Observed Region @(<signal>) 等带延时或事件触发的观察者 用于"观察"在 Monitor 区域中改变的信号或变量
6 Reactive Reactive Region PLI/VPI/VHPI 回调、DPI-C 调用 外部仿真接口的回调处理,保证与内部更新同步

调度流程简述:

在仿真器中,每到一个时间槽,依次从 Active → Inactive → NBA → Monitor → Observed → Reactive 执行对应区域的所有就绪事件;然后仿真时间跳到下一个有事件的槽位。

这样设计可以:

  • 将顺序、非阻塞赋值、监视、外部回调等不同种类的操作有序分隔,
  • 保证同一时间点内的并行硬件行为被准确、可预测地"序列化"执行。
相关推荐
芯路行者16 小时前
7 HDLBits —— 验证:编写测试激励文件
fpga开发·verilog·fpga·hdlbits
芯路行者17 小时前
4.1 HDLBits —— 时序逻辑电路之锁存器与触发器
fpga开发·verilog·fpga·hdlbits
芯路行者20 小时前
5 HDLBits —— 构建更大的电路
fpga开发·verilog·fpga·hdlbits
芯路行者21 小时前
4.3 HDLBits —— 时序逻辑电路之移位寄存器
fpga开发·verilog·fpga·hdlbits
芯路行者1 天前
4.2 HDLBits —— 时序逻辑电路之计数器
fpga开发·verilog·fpga·hdlbits
鬼手点金3 天前
FPGA常用型号参考
fpga开发·verilog·vivado·xilinx·vhdl·altera·lattice
我爱C编程7 天前
基于FPGA的DSB调制解调系统verilog开发
fpga开发·verilog·fpga·dsb
北方孤寂的灵魂1 个月前
关于AXI协议详解
verilog·systemverilog·sv·数字验证
FPGA小迷弟1 个月前
vivado中的AXI Interconnect到底应该怎么用,他的底层原理是什么,一篇文档全部理清楚!!!
网络协议·tcp/ip·fpga开发·verilog·fpga
liuluyang5302 个月前
Verilog 中 wire 与 wor 的区别详解
fpga开发·verilog