# Verilog 赋值

将值放在导线和变量上称为赋值。有以下三种基本形式:

  • 过程式(procedural)
  • 持续性(continuous)
  • 过程式持续性(procedural continuous)

# 合法左值

赋值有两个部分 - 右侧 (RHS) 和左侧 (LHS),中间有一个等号 (=) 或一个小于等号 (<=)。

赋值类型 左值
过程式 变量(标量/向量)
变量向量、整数或者时间的位选择和部分选择
内存字(memory word)
上述任意内容的拼接
持续性 导线(向量/标量)
导线向量的位选择或者部分选择
上述内容的拼接
过程式持续性 导线或者变量(标量/向量)
导线向量的位选择和部分选择

RHS 可以包含计算结果为最终值的任何表达式,而 LHS 表示将 RHS 中的值赋给的导线或变量。

module tb;
    reg clk;
    wire a, b, c, d, e, f;
    reg  z, y;

    // clk is on the LHS and the not of clk forms RHS
    always #10 clk = ~clk;

    // y is the LHS and the constant 1 is RHS
    assign y = 1;

    // f is the LHS, and the expression of a,b,d,e forms the RHS
    assign f = (a | b) ^ (d & e);

    always @ (posedge clk) begin
        // z is the LHS, and the expression of a,b,c,d forms the RHS
        z <= a + b + c + d;
    end

    initial begin
        // Variable names on the left form LHS while 0 is RHS
        a <= 0; b <= 0; c <= 0; d <= 0; e <= 0;
        clk <= 0;
    end
endmodule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 过程式赋值

过程赋值发生在过程中,例如 alwaysinitialtaskfunctions ,用于将值赋给变量。该变量将保持该值,直到下一次分配给同一变量。

当模拟器在仿真期间的某个时间点执行此语句时,该值将被放置到变量上。这可以通过使用控制流语句(如 if-else-ifcase 语句和循环机制)以我们想要的方式进行控制和修改。

reg [7:0]  data;
integer    count;
real       period;

initial begin
	data = 8'h3e;
	period = 4.23;
	count = 0;
end

always @ (posedge clk)
	count++;
1
2
3
4
5
6
7
8
9
10
11
12

# 变量声明赋值

初始值可以在声明时放置到变量上,如下所示。初始值会一直保持,直到对同一变量进行下一次赋值。请注意,不允许对数组声明赋初值。

module my_block;
	reg [31:0] data = 32'hdead_cafe;

	initial begin
		#20  data = 32'h1234_5678;    // data will have dead_cafe from time 0 to time 20
	                                  // At time 20, data will get 12345678
	end
endmodule
1
2
3
4
5
6
7
8
reg [3:0] a = 4'b4;

// is equivalent to

reg [3:0] a;
initial a = 4'b4;
1
2
3
4
5
6

如果变量在声明期间和初始块(initial block)中的时间 0 都有初始化,如下所示,则无法保证赋值生效的时间顺序,因此变量值可能是 8'h058'hee ,这是不确定的。

module my_block;
	reg [7:0]  addr = 8'h05;

	initial
        addr = 8'hee;
endmodule
1
2
3
4
5
6
reg [3:0] array [3:0] = 0;           // illegal
integer i = 0, j;                    // declares two integers i,j and i is assigned 0
real r2 = 4.5, r3 = 8;               // declares two real numbers r2,r3 and are assigned 4.5, 8 resp.
time startTime = 40;                 // declares time variable with initial value 40
1
2
3
4

过程式的程序块以及其中的赋值在后面的章节中更详细地介绍。

# 持续性赋值

这用于将值给导线标量和导线向量赋值,并在 RHS 发生变化时随之改变。它提供了一种在不指定门互连的情况下对组合逻辑进行建模的方法,并使得用逻辑表达式驱动导线变得更加容易。

// Example model of an AND gate
wire  a, b, c;

assign a = b & c;
1
2
3
4

每当 bc 更改其值时,将评估(evaluate) RHS 中的整个表达式,并使用新值更新 a

# 导线声明赋值

这允许我们在声明导线的同一语句上放置连续赋值。请注意,由于导线只能声明一次,因此它只能进行一次声明赋值。

wire  penable = 1;
1

# 过程式连续性赋值

这些是允许将表达式连续分配给导线或变量的过程式语句,有两种类型:

  • assign ... deassign
  • force ... release

# assign - deassign

这将覆盖对变量的所有过程式赋值,并通过 deassign 该变量来停用。变量的值将保持不变,直到变量通过过程式或过程式连续性赋值获得新值。赋值语句的 LHS 不能是位选择、部分选择或数组引用,但可以是变量或变量的拼接。

reg q;

initial begin
	assign q = 0;
	#10 deassign q;
end
1
2
3
4
5
6

# force - release

这些类似于 assign - deassign 语句,但可以应用于导线和变量。 LHS 可以是导线的位选择、导线的部分选择、变量或导线,但不能是数组的引用和变量的位/部分选择。 force 语句将覆盖对变量所做的所有其他分配,直到使用 release 关键字释放它。

reg o, a, b;

initial begin
	force o = a & b;
	// ...
	release o;
end
1
2
3
4
5
6
7
最后更新: 2022/10/6 01:12:51