過(guò)程連續(xù)賦值是過(guò)程賦值的一種。這種賦值語(yǔ)句能夠替換其他所有 wire 或 reg 的賦值,改寫了 wire 或 reg 型變量的當(dāng)前值。
與過(guò)程賦值不同的是,過(guò)程連續(xù)賦值的表達(dá)式能被連續(xù)的驅(qū)動(dòng)到 wire 或 reg 型變量中,即過(guò)程連續(xù)賦值發(fā)生作用時(shí),右端表達(dá)式中任意操作數(shù)的變化都會(huì)引起過(guò)程連續(xù)賦值語(yǔ)句的重新執(zhí)行。
過(guò)程連續(xù)性賦值主要有 2 種,?assign-deassign
? 和 ?force-release
?。
?assign
?(過(guò)程賦值操作)與 ?deassign
? (取消過(guò)程賦值操作)表示第一類過(guò)程連續(xù)賦值語(yǔ)句。賦值對(duì)象只能是寄存器或寄存器組,而不能是 wire 型變量。
賦值過(guò)程中對(duì)寄存器連續(xù)賦值,寄存器中的值被保留直到被重新賦值。
例如,一個(gè)帶復(fù)位端的 D 觸發(fā)器可以用下面代碼描述:
module dff_normal(
input rstn,
input clk,
input D,
output reg Q
);
always @(posedge clk or negedge rstn) begin
if(!rstn) begin //Q = 0 after reset effective
Q <= 1'b0 ;
end
else begin
Q <= D ; //Q = D at posedge of clock
end
end
endmodule
下面,用 ?assign
? 與 ?deassign
? 改寫,完成相同的功能。
即在復(fù)位信號(hào)為 0 時(shí),Q 端被 ?assign
? 語(yǔ)句賦值,始終輸出為 0。
復(fù)位信號(hào)為 1 時(shí),Q 端被 ?deassign
? 語(yǔ)句取消賦值,在時(shí)鐘上升沿被重新賦值。
module dff_assign(
input rstn,
input clk,
input D,
output reg Q
);
always @(posedge clk) begin
Q <= D ; //Q = D at posedge of clock
end
always @(negedge rstn) begin
if(!rstn) begin
assign Q = 1'b0 ; //change Q value when reset effective
end
else begin //cancel the Q value overlay,
deassign Q ; //and Q remains 0-value until the coming of clock posedge
end
end
endmodule
?force
? (強(qiáng)制賦值操作)與 ?release
?(取消強(qiáng)制賦值)表示第二類過(guò)程連續(xù)賦值語(yǔ)句。
使用方法和效果,和 ?assign
? 與 ?deassign
? 類似,但賦值對(duì)象可以是 reg 型變量,也可以是 wire 型變量。
因?yàn)槭菬o(wú)條件強(qiáng)制賦值,一般多用于交互式調(diào)試過(guò)程,不要在設(shè)計(jì)模塊中使用。
當(dāng) ?force
? 作用在寄存器上時(shí),寄存器當(dāng)前值被覆蓋;release 時(shí)該寄存器值將繼續(xù)保留強(qiáng)制賦值時(shí)的值。之后,該寄存器的值可以被原有的過(guò)程賦值語(yǔ)句改變。
當(dāng) ?force
? 作用在線網(wǎng)上時(shí),線網(wǎng)值也會(huì)被強(qiáng)制賦值。但是,一旦 ?release
? 該線網(wǎng)型變量,其值馬上變?yōu)樵械尿?qū)動(dòng)值。
為直觀的觀察兩種類型變量強(qiáng)制賦值的區(qū)別,利用第一節(jié)中的計(jì)數(shù)器 counter10 作為設(shè)計(jì)模塊,testbench 設(shè)計(jì)如下。
`timescale 1ns/1ns
module test ;
reg rstn ;
reg clk ;
reg [3:0] cnt ;
wire cout ;
counter10 u_counter (
.rstn (rstn),
.clk (clk),
.cnt (cnt),
.cout (cout));
initial begin
clk = 0 ;
rstn = 0 ;
#10 ;
rstn = 1'b1 ;
wait (test.u_counter.cnt_temp == 4'd4) ;
@(negedge clk) ;
force test.u_counter.cnt_temp = 4'd6 ;
force test.u_counter.cout = 1'b1 ;
#40 ;
@(negedge clk) ;
release test.u_counter.cnt_temp ;
release test.u_counter.cout ;
end
initial begin
clk = 0 ;
forever #10 clk = ~ clk ;
end
//finish the simulation
always begin
#1000;
if ($time >= 1000) $finish ;
end
endmodule // test
仿真結(jié)果如下。
由圖可知,在 ?cnt_temp
? 等于 4 時(shí)(80ns), ?cnt_temp
? 被強(qiáng)制賦值為 6,cout 被強(qiáng)制賦值為 1。
release 時(shí)(120ns), ?cnt_temp
? 為寄存器類型,仍然保持原有值不變,直到時(shí)鐘上升沿對(duì)其進(jìn)行加法賦值操作,值才變?yōu)?nbsp;7 。
而 120ns 時(shí),由于 cout 是線網(wǎng)型變量,其值不能保存。原碼 counter10 模型中存在驅(qū)動(dòng)語(yǔ)句: ?assign cout = (cnt_temp==4'd9)
? ,所以 cout 值變?yōu)?nbsp;0 。
點(diǎn)擊這里下載源碼
更多建議: