硬件設計熱門培訓內容之Verilog指令_assign用法

時間:2018-12-06 17:18:00

一、引入語法的概念

 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

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

分析:

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

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

assign是一種線的賦值語句,例如 
wire  a,b;
reg   c;
可以寫成  assign  a= 1'b1;
但是不能寫成  assign c=1'b1;
普通的io口也可以直接賦值 ,其實io口在電路上就是一種wire

ouput[15:0]   d;
assing  d=16'h1234;
------------------------------------------------------------------
----------------------------------------
reg 與 寄存器
實際上應該反過來講:

- 如果要綜合寄存器,需要同時滿足倆個條件:
   1。定義為reg,
   2. 在always @posedge(negedge) block中賦值

- 如果要綜合組合邏輯,可以(任意)
   a. 定義為wire, 用assign賦值
   b. 定義為reg, 只在always @(a b c d) block中賦值

在verilog語言中的reg 類型只是語法意義上。reg類型的變量不能通過assign賦值,而wire類型的變量不能在always block中賦值。參加運算的變量(賦值號的右邊)沒有類型檢查的限制。

? 江苏快3号码表