Verilog 過程連續(xù)賦值

2022-05-17 11:16 更新

關(guān)鍵詞:deassign,force,release

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

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

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

assign, deassign

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

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

例如,一個帶復(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ù)位信號為 0 時,Q 端被 ?assign? 語句賦值,始終輸出為 0。

復(fù)位信號為 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?(取消強制賦值)表示第二類過程連續(xù)賦值語句。

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

因為是無條件強制賦值,一般多用于交互式調(diào)試過程,不要在設(shè)計模塊中使用。

當(dāng) ?force? 作用在寄存器上時,寄存器當(dāng)前值被覆蓋;release 時該寄存器值將繼續(xù)保留強制賦值時的值。之后,該寄存器的值可以被原有的過程賦值語句改變。

當(dāng) ?force? 作用在線網(wǎng)上時,線網(wǎng)值也會被強制賦值。但是,一旦 ?release? 該線網(wǎng)型變量,其值馬上變?yōu)樵械尿?qū)動值。

為直觀的觀察兩種類型變量強制賦值的區(qū)別,利用第一節(jié)中的計數(shù)器 counter10 作為設(shè)計模塊,testbench 設(shè)計如下。

`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 時(80ns), ?cnt_temp? 被強制賦值為 6,cout 被強制賦值為 1。

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

而 120ns 時,由于 cout 是線網(wǎng)型變量,其值不能保存。原碼 counter10 模型中存在驅(qū)動語句: ?assign cout = (cnt_temp==4'd9)? ,所以 cout 值變?yōu)?nbsp;0 。


點擊這里下載源碼


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號