Verilog中的assign


(一)

assign 用於描述組合邏輯,用阻塞賦值,但assign語句是並行執行,(說明:阻塞賦值串行操作是局限於在behavior structual 描述內部,也就是指在initial and always block內部。)

所有的assign和always是並行執行的。

對assign之后不能加塊,實現組合邏輯只能用逐句的使用assign 組合邏輯,如果不考慮門的延時的話當然可以理解為瞬時執行的,因此沒有並行和順序之分,並行和順序是針對時序邏輯來說的。值得注意的是所有的時序塊都是並行執行的。initial塊只在信號進入模塊后執行1次而always塊是由敏感事件作為中斷來觸發執行的。

assign 用於連續賦值語句,if-else用於RTL級描述中,被賦值的變量都是reg類型。reg類型賦值分blocked和nonblocked,即=和<=,不需要再使用assign。

(二)

一、引入語法的概念

 1、只有寄存器類型的信號才可以在always和initial 語句中進行賦值,類型定義通過reg語句實現。
  2、always 語句是一直重復執行,由敏感表(always 語句括號內的變量)中的變量觸發。
  3、always 語句從0 時刻開始。
  4、在begin 和end 之間的語句是順序執行,屬於串行語句。

 

二、總結下幾種assign用法:

1.作為信號量輸出,通過寄存器連續賦值

output [3:0]oLED;

 

//internal signal

 

reg [3:0]sr_LED; //用獨熱碼表示LED亮燈位置。

 

assign  oLED[3:0] = ~ sr_LED[3:0]; //向LED燈接口輸出信號。

2.作為信號量輸出,通過寄存器拼接數據位實現。

 

output [15: 0] oSI_DATA;

 

//internal signal

  reg [ 3: 0] s_HEX;

  reg [ 7: 0] s_SEGBINARY; // s_SEGBINARY[2] should be the DOT

  reg [ 3: 0] s_SEG_SEL;

 

assign oSI_DATA = {iLED_SEL,s_SEG_SEL,s_SEGBINARY};

3.作為信號量輸出,通過判斷條件,賦值給信號

 

 

output[ 1: 0] oSEG_STATE;

output        oCP_PLUSE;

wire s_CNTEQCYCLE; 

 

parameter PARAM_7SEG_CYCLE = 32'd2500000;

 

reg [ 1: 0] sr_SEG_STATE;

reg [31: 0] sr_cnt;

reg         sr_cp_pluse;  

assign oSEG_STATE = sr_SEG_STATE;

assign oCP_PLUSE = sr_cp_pluse;

 

assign s_CNTEQCYCLE = ( sr_cnt == PARAM_7SEG_CYCLE ) ? 1 : 0;

 

 

 

4.作為輸出信號量,通過輸入信號量賦值給輸出,同樣可以輸入信號量和寄存器組合邏輯,賦值給輸出信號量。
input        iCLK50M;
input        iCP_PULSE;
input[15:0]  iSI_DATA;
output       oSI;
output       oCP;
reg [ 3: 0] sr_cnt;
reg [15: 0] sr_si_data;
reg sr_cp;
reg sr_en;
assign oSI = sr_si_data[15];
assign oCP = sr_en & iCLK50M;
三、對比輸出寄存器變量和信號量

下面是功能相同但寫法不同的兩段代碼:

第一段A

module assign_test_a (
                       clk,
                       lhold,
                       lholda
);

input clk;
input lhold;
output lholda;

reg lholda;

always @(posedge clk)
if (lhold)
 lholda<=lhold;
else
 lholda<=0;

endmodule


第二段B
module assign_test_b (
                       clk,
                       lhold,
                       lholda
);
input clk;
input lhold;
output lholda;

reg lholda_r;
  always @(posedge clk)
  if (lhold)
     lholda_r<=lhold;
  else
     lholda_r<=0;

 assign  lholda=lholda_r;
endmodule

 

兩端代碼生成的電路時一樣的,沒有區別,只是在應用上有區別


第一段A分析

 

 


第二段B的分析

Quartus RTL圖

  加入assign風格的綜合結果


Xillinx RTL圖

 

分析:

1. 從代碼角度來看。 A是直接把內部reg信號做為輸出,因此相對外部來說,外部信號引腳lholda沒有選擇的連接到reg輸出信號。 這里其實暗含了用根導線直接把reg的輸出與lholda連接起來。因此B代碼就是把這個暗含的明顯化。因此他們的RTL沒有多大區別。
2. 從實用角度來說,這里的意義比較大。當內部有多個信號需要輸出,可是輸出引腳只有一個,那么這時就可以進行選擇。如下:
assign  lholda= (條件)? (lholda_ra): lholda_rb;  可以嵌套使用。
   或者在這種情況下也非常有用。
     Lholda 與 內部的reg輸出lholda_ra, lholda_rb,…., 存在邏輯函數關系


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM