Verilog中的赋值方式:
assign 引导的continuous 赋值
用于nets类型的数据,比如wire,左边的值随着右边的值连续变化,可理解为线网, 比如
wire carry_out, sum_out;
wire carry_in, a_in, b_in;
assign {carry_out, sum_out} = a_in + b_in + carry_in;
procedural 赋值
用于variable类型的数据比如reg, integer, real, time 和realtime类型的数据。这种赋值方式一般在always或者initial结构中,或者是在定义的时候也可声明 比如:
reg clk;
always #1; clk = ~clk;
initial clk = 1'b1;
reg test_reg = 1'b1;
具体还有阻塞赋值与非阻塞赋值的区别,这个下次单独总结
还有一种特殊的赋值方式
procedural continuous赋值
这种赋值由 assign/deassign 和 force/release引导
assign / deassign
assign对variable会覆盖掉
主要用于variable或者variable 的拼接,但不能用于variable 的bit select或者 part select
比如说用一个assign引导的procedural continuous写一个带预置位和清零的d触发器
module dff(q, d, clk, clr, preset);
input d;
input clk, clr, preset;
output q;
wire d;
wire clk, clr, preset;
reg q;
always @(preset, clr)begin
if(!clr)
assign q = 0;
else if(!preset)
assign q = 1'b1;
else
deassign q;
end
always @(posedge clk)begin
q = d; // 这里用的是阻塞赋值
end
endmodule
如果clr或者preset为0时,那么时钟的上升沿不会影响到q, 当他们都为高时,q被deassign, 回到正常的procedural 赋值。
至于为什么用阻塞赋值,等我明白了再写。
force / release
force/release 可以用于net, variable, bit-select of vector net, part-select of vector net,或者他们的拼接
force用于variable会覆盖掉过程赋值,或者assign引导的过程连续(procedural assign)赋值,直到release
force用于net会覆盖掉所有net的drive或者continuous assign,直到release
example
module test
reg a, b, c, d;
wire e;
and u_and(e, a, b, d);
initial begin
$monitor(" %d : d = %d, e = %d", $stime, d, e);
assign d = a & b & c;
a = 1;
b= 0;
c = 1;
#10;
force d = (a | b | c); // force右边可以是表达式,只要a, b, c其中一个改变,左边值就会变化
force e = (a | b | c);
#10;
release d;
release e;
#10;
$finish;
end
endmodule
结果
0: d=0; e = 0;
10: d = 1; e = 1; // force 强制变为或
20: d= 0; e = 0;