關鍵詞:deassign,force,release

過程連續賦值是過程賦值的一種。這種賦值語句能夠替換其他所有 wire 或 reg 的賦值,改寫了 wire 或 reg 型變量的當前值。

與過程賦值不同的是,過程連續賦值的表達式能被連續的驅動到 wire 或 reg 型變量中,即過程連續賦值發生作用時,右端表達式中任意操作數的變化都會引起過程連續賦值語句的重新執行。

過程連續性賦值主要有 2 種,assign-deassign 和 force-release。

assign, deassign

assign(過程賦值操作)與 deassign (取消過程賦值操作)表示第一類過程連續賦值語句。賦值對象隻能是寄存器或寄存器組,而不能是 wire 型變量。

賦值過程中對寄存器連續賦值,寄存器中的值被保留直到被重新賦值。

例如,一個帶複位端的 D 觸發器可以用下麵代碼描述:

實例

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 改寫,完成相同的功能。

即在複位信號為 0 時,Q 端被 assign 語句賦值,始終輸出為 0。

複位信號為 1 時,Q 端被 deassign 語句取消賦值,在時鍾上升沿被重新賦值。

實例

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, release

force (強製賦值操作)與 release(取消強製賦值)表示第二類過程連續賦值語句。

使用方法和效果,和 assign 與 deassign 類似,但賦值對象可以是 reg 型變量,也可以是 wire 型變量。

因為是無條件強製賦值,一般多用於交互式調試過程,不要在設計模塊中使用。

當 force 作用在寄存器上時,寄存器當前值被覆蓋;release 時該寄存器值將繼續保留強製賦值時的值。之後,該寄存器的值可以被原有的過程賦值語句改變。

當 force 作用在線網上時,線網值也會被強製賦值。但是,一旦 release 該線網型變量,其值馬上變為原有的驅動值。

為直觀的觀察兩種類型變量強製賦值的區別,利用第一節中的計數器 counter10 作為設計模塊,testbench 設計如下。

實例

`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

仿真結果如下。

由圖可知,在 cnt_temp 等於 4 時(80ns), cnt_temp 被強製賦值為 6,cout 被強製賦值為 1。

release 時(120ns), cnt_temp 為寄存器類型,仍然保持原有值不變,直到時鍾上升沿對其進行加法賦值操作,值才變為 7 。

而 120ns 時,由於 cout 是線網型變量,其值不能保存。原碼 counter10 模型中存在驅動語句: assign cout = (cnt_temp==4'd9) ,所以 cout 值變為 0 。

源碼下載

Download