跳转到内容
新建笔记

IEEE 1364-2005 Verilog 学习导读

IEEE 1364-2005 同时定义了 RTL、门级/开关级建模、事件驱动仿真、时序标注、波形交换和 C 接口。学习时不要把所有章节当成同一层次:

flowchart LR
A["词法、四态数据、表达式"] --> B["过程语句与赋值"]
B --> C["模块、端口、参数、generate"]
C --> D["可综合 RTL"]
B --> E["事件调度与 Testbench"]
C --> F["门级、specify、SDF"]
E --> G["VCD 与 VPI"]
F --> G

推荐顺序:先学 Clause 3-6、9-12,再学 17-19;需要门级时序仿真时读 7-8、14-16;需要工具扩展时读 20、26-28。Clause 21-25 的 TF/ACC 接口已弃用。

  1. net 表示连接和驱动解析,reg 表示过程赋值目标;reg 这个名字不保证综合出触发器。
  2. Verilog 值域是 0/1/x/z。x 是未知,z 是高阻,不能把它们当普通二进制值忽略。
  3. 组合过程通常用阻塞赋值 =,时钟过程通常用非阻塞赋值 <=。
  4. 位宽和 signedness 必须主动控制;加法不会自动多出进位位,窄赋值会丢弃高位。
  5. ==/!= 遇到无法确定的 x/z 可返回 x;===/!== 始终返回 0/1,主要用于 Testbench。
  6. if 将 x/z 条件视为不成立;?: 在一位未知条件下会逐位合并两个候选值。
  7. 并发过程在同一时间槽的 Active 区内没有固定先后顺序;不要依赖源码排列消除竞态。
  8. 模块端口的 signed 属性不会因连接自动传播,边界处应显式声明或转换。
  9. generate 在 elaboration 阶段展开,不在仿真期间反复执行。
  10. specify、timing check 和 SDF 面向时序仿真,不应与可综合 RTL 混为一谈。
对象驱动方式未初始化/未驱动值典型用途
wire、tri连续赋值、端口、实例输出,可解析多驱动z组合连接、总线
uwire单一驱动z用工具检查意外多驱动
wand/wor按 wired-AND/OR 解析多驱动z特殊板级/开关模型
tri0/tri1无有效驱动时带弱下拉/上拉0/1拉电阻模型
trireg保存电荷并可衰减依驱动与电荷状态开关级电容模型
reg、integer、time过程赋值xRTL 状态、循环和计时
real、realtime过程赋值0.0仿真计算,不是常规 RTL
reg [7:0] mem [0:255];
// ^ packed 向量 ^ unpacked 数组/存储器下标

位选择和部分选择的结果总是 unsigned。数组与 packed 向量是不同维度,连接端口时尤其要检查方向、范围和位宽。

8'hA5 // 8 位无符号十六进制
8'shA5 // 8 位有符号十六进制
'hA5 // 无尺寸、无符号,至少与 integer 同宽
-12 // 一元负号作用于无尺寸十进制数
4'b10xz // 四态二进制常量
  • 无尺寸十进制常量是 signed;带基数但没有 s 的常量是 unsigned。
  • 无尺寸常量至少 32 位;拼接中禁止使用无尺寸常量,因为结果位宽不明确。
  • 算术表达式中出现 x/z,结果通常整体变成 x。
  • 算术右移 >>> 只有在左操作数的表达式类型为 signed 时才复制符号位。
  • 赋值先按表达式规则求值,再按左值宽度扩展或截断;需要进位时主动扩宽操作数。
表达式结果宽度要点
+ - * / % & | ^通常由上下文与最大操作数宽度决定,不能假定 + 自动加 1 位
== != === !== < <= > >=1 位
`&&!`1 位
归约运算1 位
a << n、a >> n与左操作数宽度相同,移位量宽度不扩展结果
{a,b}、{N{a}}各项宽度之和;各项是 self-determined
cond ? a : b两个结果分支共同决定宽度和类型
位选1 位且 unsigned
部分选择选择宽度且 unsigned

安全写法:

wire [7:0] a, b;
wire [8:0] sum = {1'b0, a} + {1'b0, b};
wire signed [7:0] s;
wire signed [7:0] half = s >>> 1;
场景语义实践建议
a == b含未知位且无法判定时为 xRTL 普通比较
a === b把 x/z 也作为字面值比较Testbench 自检
if (cond)cond 为 x/z 时走 else不要让未知控制关键路径
cond ? a : b条件未知时逐位合并 a/b比 if 更能暴露部分未知
case0/1/x/z 精确逐位匹配默认选择
casezz/? 为通配符仅用于明确掩码意图
casexx/z/? 都为通配符避免,容易吞掉设计错误

括号优先于背运算符优先级。混合 signed/unsigned、比较、移位或三目运算时,显式扩宽和转换比依赖隐式规则可靠。

flowchart LR
A["Active<br/>求值、阻塞赋值、连续赋值更新"] --> B["Inactive<br/>#0 事件"]
B --> C["NBA update<br/>非阻塞赋值更新"]
C --> D["Monitor<br/>$strobe / $monitor"]
D --> E["下一个时间槽"]

Active 区内不同并发过程的先后顺序未定义,是仿真竞态的主要来源。#0 只把事件移到 Inactive 区,并不能建立可靠同步协议。

always @(posedge clk) begin
q1 <= d;
q2 <= q1;
end

两个右值都在 Active 区求值,更新进入 NBA 区,因此这段代码描述两级流水。对同一过程、同一时间点排入的多个 NBA,标准保留源码顺序;不同过程同时写同一变量仍可能不确定,应保持单写者。

写法采样时刻更新时刻
#5 a = b;延迟结束后立即
a = #5 b;进入语句时延迟结束后,过程阻塞
#5 a <= b;延迟结束后当时的 NBA 区
a <= #5 b;进入语句时5 个时间单位后的 NBA 区
事件标准识别的主要跃迁
posedge0->1、0->x/z、x/z->1
negedge1->0、1->x/z、x/z->0

向量边沿只检查最低有效位。always 必须包含能让时间前进或等待事件的控制,否则会形成零延时死循环。

always @* begin
y = 1'b0;
case (sel)
1'b0: y = a;
1'b1: y = b;
default: y = 1'bx;
endcase
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
q <= 1'b0;
else
q <= d;
end

begin-end 顺序执行过程语句;fork-join 并发启动分支。命名块可建立作用域,也可被 disable 终止。循环应区分固定次数、可综合展开与仅用于 Testbench 的运行时控制。

模块、端口、参数与 generate

跳转到“模块、端口、参数与 generate”
flowchart TD
T["top"] --> U0["u_core"]
T --> U1["u_io"]
U0 --> R0["g_lane[0].u_reg"]
U0 --> R1["g_lane[1].u_reg"]
  • 参数覆盖使用位置或命名方式之一,不能混用;实例端口连接也不能混用两种方式。
  • localparam 表示不可从实例外覆盖的本地常量。
  • 优先使用 #(.WIDTH(8)),避免跨层级、难追踪的 defparam。
  • generate 条件必须在 elaboration 时确定;显式命名生成块,避免依赖工具生成的 genblkN。
  • 层次名是作用域路径,不是文件路径。向上引用和跨层引用会增加复用难度。
module pipe #(parameter WIDTH = 8) (
input wire clk,
input wire [WIDTH-1:0] d,
output reg [WIDTH-1:0] q
);
always @(posedge clk)
q <= d;
endmodule

门级、路径延迟与时序检查

跳转到“门级、路径延迟与时序检查”

门/开关原语和 UDP 用于低层模型;RTL 学习者应能读懂,但通常不手写复杂强度网络。多驱动 net 会根据值与强度解析,无法唯一决定时产生 x。

(a => y) :并行路径,按对应关系描述 N 条路径
(a *> y) :全连接路径,描述输入到输出的 N x M 组合
timing check约束对象典型含义
$setup / $hold / $setuphold数据与参考边沿建立、保持或组合窗口
$recovery / $removal / $recrem异步控制与时钟异步释放约束
$skew / $timeskew / $fullskew两个事件偏斜上限与事件窗口
$width脉冲最小脉宽
$period周期事件最小周期
$nochange数据窗口指定区间内不允许改变
flowchart LR
A["综合后的网表"] --> B["specify 路径和 timing checks"]
C["布局布线延迟"] --> D["SDF"]
D -->|"$sdf_annotate"| B
B --> E["门级时序仿真"]

SDF 的 DELAY 对应模块/器件延迟,TIMINGCHECK 对应系统时序检查,INTERCONNECT 对应互连延迟,LABEL 可覆盖参数类数据。它们服务于后仿真,不是综合电路行为。

Testbench、系统任务与 VCD

跳转到“Testbench、系统任务与 VCD”
目的常用接口
即时输出$display、$write
NBA 后观察$strobe、$monitor
文件 I/O$fopen、$fclose、$fgets、$fscanf
存储器初始化$readmemb、$readmemh
时间$time、$stime、$realtime、$timeformat
控制仿真$finish、$stop
命令行参数$test$plusargs、$value$plusargs
数学/转换$clog2 等系统函数
flowchart LR
A["$dumpfile"] --> B["$dumpvars(level, scope)"]
B --> C["仿真值变化"]
C --> D["四态 VCD"]
E["$dumpoff / $dumpon"] --> C
F["$dumpflush / $dumpall"] --> D

$dumpvars(0, top) 递归记录 top 下全部层级;$dumpvars(1, top) 只记录本层。大型设计应限制层级和信号范围,避免波形文件失控。

建议每个独立编译单元明确环境:

`resetall
`default_nettype none
module example(/* ... */);
// ...
endmodule
`default_nettype wire
  • `define 是预处理文本替换,不是类型安全函数;带副作用的实参若在宏体中出现多次,也会被求值多次。
  • 递归宏非法。用完局部宏后 `undef;`resetall 不会清除宏定义。
  • `include 按文本插入文件,需控制搜索路径和重复包含。
  • `timescale 指定时间单位/精度;同一设计不能出现一部分模块声明、一部分完全未声明的混合状态。
  • `celldefine、`default_nettype、`unconnected_drive 等指令会改变后续文本语义,库文件应恢复环境。

新工具扩展应使用 VPI,不再使用已弃用的 TF/ACC。

flowchart LR
A["vlog_startup_routines[]"] --> B["vpi_register_systf"]
B --> C["compiletf / sizetf"]
B --> D["calltf"]
D --> E["vpi_handle"]
D --> F["vpi_iterate + vpi_scan"]
E --> G["vpi_get / vpi_get_str"]
F --> H["vpi_get_value / vpi_put_value"]

VPI 四态向量用 aval/bval 编码:00=0、10=1、11=X、01=Z。对象关系与回调生命周期比单个函数名更重要,配套头文件以 Annex G 的 vpi_user.h 为准。

Clause 28 的 protected envelope 是标准当年的加密封装互操作机制,不等于现代安全建议。其算法登记表包含已经不安全的 DES、MD5、SHA-1;新系统不得据此选型。

flowchart LR
P["Verilog 明文"] --> S["对称加密"]
K["随机会话密钥"] --> S
K --> A["用授权方公钥封装"]
S --> E["protected envelope"]
A --> E
  • Annex A:规范性 BNF,语法有歧义时的最终检索入口。
  • Annex B:规范性关键字表,检查标识符冲突。
  • Annex C/D:信息性内容且依赖实现,不应当作可移植语义保证。
  • Annex E/F:已弃用 PLI 头文件,仅维护旧工具时查阅。
  • Annex G:规范性 vpi_user.h。
  • Annex H:信息性的加密流程示例,仅用于理解封装结构。
  • Annex I:参考文献。
  1. 能解释 wire、reg 与物理组合/时序电路为何不是一一对应。
  2. 能手算混合位宽、signed/unsigned、移位和截断结果。
  3. 能按 Active、Inactive、NBA、Monitor 判断一个时间槽内的输出。
  4. 能识别多过程写同一变量、#0、casex 和零延时 always 的风险。
  5. 能写参数化模块、命名端口连接和命名 generate 块。
  6. 能区分 RTL 仿真、门级时序仿真、SDF 回标和 VCD 波形记录。
  7. 能判断何时只需 HDL,何时才需要 VPI。

逐章页码、全部图表系列和 Syntax Box 覆盖清单见 IEEE 1364-2005 参考地图。