深入理解 Verilog 赋值语句:类型、语法与最佳实践
将值赋给网络和变量称为赋值。Verilog 中有三种基本形式:
- 过程赋值
- 连续赋值
- 过程连续赋值
合法的左值(LHS)
赋值语句包含右侧表达式(RHS)和左侧目标(LHS),中间用等号(=)或非阻塞赋值符号(<=)连接。
| 赋值类型 | 左侧允许的对象 |
|---|---|
| 过程赋值 |
|
| 连续赋值 |
|
| 过程连续赋值 |
|
RHS 可以是任意求值表达式,LHS 指明接收该值的网络或变量。
module tb;
reg clk;
wire a, b, c, d, e, f;
reg z, y;
// clk 在 LHS,~clk 构成 RHS
always #10 clk = ~clk;
// y 是 LHS,常量 1 是 RHS
assign y = 1;
// f 是 LHS,a,b,d,e 的表达式构成 RHS
assign f = (a | b) ^ (d & e);
always @ (posedge clk) begin
// z 是 LHS,a,b,c,d 的表达式构成 RHS
z <= a + b + c + d;
end
initial begin
// 变量名在左侧形成 LHS,0 是 RHS
a <= 0; b <= 0; c <= 0; d <= 0; e <= 0; clk <= 0;
end
endmodule过程赋值
过程赋值出现在 always、initial、task 和 function 等过程块中,用于给变量赋值。变量将保持该值,直到下一次对同一变量赋值。
赋值在仿真执行到该语句时发生,可通过 if-else、case 语句及循环机制等控制流语句灵活控制。
reg [7:0] data;
integer count;
real period;
initial begin
data = 8'h3e;
period = 4.23;
count = 0;
end
always @ (posedge clk)
count++;变量声明赋值
可在变量声明时给出初始值。该赋值无持续时间,保持值直到下一次赋值。注意:不允许对数组进行声明赋值。
module my_block;
reg [31:0] data = 32'hdead_cafe;
initial begin
#20 data = 32'h1234_5678;
// data 从时刻 0 到 20 保持 dead_cafe
// 20 时刻更新为 12345678
end
endmodulereg [3:0] a = 4'b4; // 等价于
reg [3:0] a;
initial a = 4'b4;若变量在声明时初始化,且在 initial 块中于时刻 0 再次赋值,求值顺序不确定,可能得到 8'h05 或 8'hee。
module my_block;
reg [7:0] addr = 8'h05;
initial addr = 8'hee;
endmodulereg [3:0] array [3:0] = 0; // 非法
integer i = 0, j; // 声明 i,j 并赋 i=0
real r2 = 4.5, r3 = 8; // 声明 r2,r3 并分别赋 4.5, 8
time startTime = 40; // 声明 time 变量初值 40过程块与赋值将在后续章节详述。
连续赋值
点击查看分步仿真示例!
用于给标量和向量网络赋值,每当 RHS 发生变化即重新求值并更新 LHS。它提供了一种无需指定门级互连即可建模组合逻辑的方法,便于用逻辑表达式驱动网络。
// 与门建模示例
wire a, b, c;
assign a = b & c;当 b 或 c 变化时,RHS 表达式重新求值,a 更新为新值。
网络声明赋值
可在声明网络的同一语句中进行连续赋值。因网络只能声明一次,故每个网络仅允许一次声明赋值。
wire penable = 1;过程连续赋值
这类过程语句允许表达式持续赋给网络或变量,分两种:
assign...deassignforce...release
assign / deassign
覆盖对变量的所有过程赋值,用 deassign 解除。变量值保持不变,直到通过过程或过程连续赋值获得新值。assign 的 LHS 不能是位选、部分选或数组引用,但可以是变量或变量拼接。
reg q;
initial begin
assign q = 0;
#10 deassign q;
endforce / release
类似 assign - deassign,但也可用于网络和变量。LHS 可以是网络的位选、部分选、变量或网络,但不能是数组引用和变量的位/部分选。force 覆盖该变量的所有其他赋值,直到用 release 释放。
reg o, a, b;
initial begin
force o = a & b;
...
release o;
end
Verilog
- C 语言变量详解:类型、命名规则、定义声明与内存管理
- Verilog 入门:数字电路设计完整教程
- 掌握 Verilog 拼接操作:实用指南
- Verilog阻塞与非阻塞赋值:关键区别详解
- 掌握Verilog函数:高效RTL设计的复用利器
- 理解Verilog任务:函数vs任务、语法与用法全解析
- Verilog 时钟发生器设计与实现指南
- 掌握 Verilog 数学函数:高效硬件设计的利器
- 掌握 Verilog $timeformat:精度控制与显示格式化
- 理解与打印 Verilog 任意作用域下的 Timescale
- 掌握 Verilog 文件 I/O:打开、读取、写入和关闭
- Verilog 入门指南:Hello World 示例