寫在前面的話
在設計中,很多情況下我們需要編寫很多結構相同但參數不同的賦值語句或邏輯語句塊,當參數量很大的情況下,原始的列舉就會變得很笨拙甚至是不可行的。C語言處理這種問題通常情況下會使用如for循環語句來完成多次的相同操作。而verilog 語言呢?同樣的為我們提供了generate語句塊來幫助我們完成這些過程。接下來,夢翼師兄將和大家一起開始generate語句的學習。
基本概念
generate的主要功能就是對module,net,reg,parameter,assign,always,task,function進行復制,genvar是generate語句中的一種變量類型,用以在 generate-for 語句中聲明一個正整數的索引變量 (如果將“X”或“Z”或者“負值”賦給genvar 變量將會出錯)。genvar 變量可以聲明在 generate 語句內,也可以聲明在 generate 語句外。
generate 語句有 generate-for、generate-if 和 generate-case 三種語句,下面夢翼師兄和大家一起來學習這三種語句。
genrate-for
使用generate_for的時候,必須要注意以下幾點要求:
a) 必須使用genvar申明一個正整數變量,用作for的判斷變量;
b) for里面的內嵌語句,必須寫在begin_end里面,哪怕只有一句;
c) begin_end需要一個名字。
例1:利用generate_for來復制assign語句
/**************************************************** * Engineer : 夢翼師兄 * QQ : 761664056 * E_mail : zxopenwjf@126.com * The module function : generate_for_assign模塊 *****************************************************/ 01 module for_test(indata, t0, t1, t2, t3); 02 03 input [7:0] indata; //輸入8位位寬indata 04 output [1:0] t0, t1, t2, t3; //輸出2位位寬t0,t1,t2,t3; 05 06 wire [1:0] temp [3:0]; //定義位寬為2,深度為4的temp 07 genvar i; 08 09 generate for(i=0; i<4; i=i+1 ) //generate for模塊復制 10 begin : gfor_block 11 assign temp[i] = indata[2*i+1:2*i]; 12 end 13 endgenerate 14 15 assign t0 = temp[0]; //t0等於temp[0] 16 assign t1 = temp[1]; //t1等於temp[1] 17 assign t2 = temp[2]; //t2等於temp[2] 18 assign t3 = temp[3]; //t3等於temp[3] 19 20 endmodule |
編寫的測試代碼如下:
/**************************************************** * Engineer : 夢翼師兄 * QQ : 761664056 * The module function :for_test的測試模塊 *****************************************************/ 01 `timescale 1ns/1ps 02 module tb; 03 04 reg [7:0] indata; //輸入8位位寬indata 05 wire [1:0] t0, t1, t2, t3; //輸出2位位寬t0,t1,t2,t3; 06 07//----------寫入2組數據------------ 08 initial 09 begin 10 indata = 8'b1011_1011; 11 #100 indata = 8'b0101_1010; 12 end 13 14 //---------模塊例化-------------- 15 for_test for_test( 16 .indata(indata), 17 .t0(t0), 18 .t1(t1), 19 .t2(t2), 20 .t3(t3) 21 ); 22 23 endmodule |
仿真波形如下:
觀察波形可以得到:
temp[0] = indata[1:0];
temp[1] = indata[3:2];
temp[2] = indata[5:4];
temp[3] = indata[7:6];
由此得出for_test模塊第9~13行可以這樣展開:
assign temp[0] = indata[1:0];
assign temp[1] = indata[3:2];
assign temp[2] = indata[5:4];
assign temp[3] = indata[7:6];
我們發現,這段代碼是通過i的增加來重復執行temp[i] = indata[2*i+1:2*i] 這條語句的,所以generate_for可以復制assign語句。
例2:利用generate_for來復制always語句
/**************************************************** * Engineer : 夢翼師兄 * QQ : 761664056 * The module function : generate_for_always模塊 *****************************************************/ 01 module for_test1(indata, t0, t1, t2, t3); 02 03 input [7:0] indata; //輸入8位位寬indata 04 output [1:0] t0, t1, t2, t3; //輸出2位位寬t0,t1,t2,t3; 05 06 reg [1:0] temp [3:0]; //定義位寬為2,深度為4的temp 07 genvar i; 08 09 generate for(i=0; i<4; i=i+1 )//generate for模塊復制 10 begin : gfor_block 11 always @ (*) 12 temp[i] = indata [2*i+1:2*i] 13 end 14 endgenerate 15 16 assign t0 = temp[0]; //t0等於temp[0] 17 assign t1 = temp[1]; //t1等於temp[1] 18 assign t2 = temp[2]; //t2等於temp[2] 19 assign t3 = temp[3]; //t3等於temp[3] 20 21 endmodule |
編寫的測試代碼如下:
/**************************************************** * Engineer : 夢翼師兄 * QQ : 761664056 * The module function :for_test1的測試模塊 *****************************************************/ 01 `timescale 1ns/1ps 02 module tb; 03 04 reg [7:0] indata; //輸入8位位寬indata 05 wire [1:0] t0, t1, t2, t3; //輸出2位位寬t0,t1,t2,t3; 06 07//----------寫入2組數據------------ 08 initial 09 begin 10 indata = 8'b1011_1011; 11 #100 indata = 8'b0101_1010; 12 end 13 14 //---------模塊例化--------------- 15 for_test1 for_test1( 16 .indata(indata), 17 .t0(t0), 18 .t1(t1), 19 .t2(t2), 20 .t3(t3) 21 ); 22 23 endmodule |
仿真波形如下:
觀察波形可以得到:
temp[0] = indata[1:0];
temp[1] = indata[3:2];
temp[2] = indata[5:4];
temp[3] = indata[7:6];
由此得到for_test1模塊第9~14行我們可以這樣展開:
always @ (*)
temp[0] = indata[1:0];
always @ (*)
temp[1] = indata[3:2];
always @ (*)
temp[2] = indata[5:4];
always @ (*)
temp[3] = indata[7:6];
我們發現,這段代碼是通過i的增加來重復執行
always @ (*)
temp[i] = indata[2*i+1:2*i]
這條語句的,所以generate_for可以復制always語句。
例3:利用多個generate_for來實現模塊復制
/**************************************************** * Engineer : 夢翼師兄 * QQ : 761664056 * The module function : generate_for_多個模塊 *****************************************************/ 01 module for_test2(indata, t0, t1, t2, t3); 02 03 input [7:0] indata; //輸入8位位寬indata 04 output [1:0] t0, t1, t2, t3; //輸出2位位寬t0,t1,t2,t3; 05 06 wire [1:0] temp [3:0]; //定義位寬為2,深度為4的temp 07 genvar i, j; 08 09 generate for(i=0; i<4; i=i+1) //generate for模塊復制 10 begin : gfor_block_a 11 for(j=0; j<2; j=j+1) 12 begin : gfor_block_b 13 assign temp[i][j] = indata[2*i+j]; 14 end 15 end 16 endgenerate 17 18 assign t0 = temp[0]; //t0等於temp[0] 19 assign t1 = temp[1]; //t1等於temp[1] 20 assign t2 = temp[2]; //t2等於temp[2] 21 assign t3 = temp[3]; //t3等於temp[3] 22 endmodule |
編寫的測試代碼如下:
/**************************************************** * Engineer : 夢翼師兄 * QQ : 761664056 * The module function :for_test2的測試模塊 *****************************************************/ 01 `timescale 1ns/1ps 02 module tb; 03 04 reg [7:0] indata; //輸入8位位寬indata 05 wire [1:0] t0, t1, t2, t3; //輸出2位位寬t0,t1,t2,t3; 06 07//----------寫入2組數據------------ 08 initial 09 begin 10 indata = 8'b1011_1011; 11 #100 indata = 8'b0101_1010; 12 end 13 14 //---------模塊例化--------------- 15 for_test2 for_test2( 16 .indata(indata), 17 .t0(t0), 18 .t1(t1), 19 .t2(t2), 20 .t3(t3) 21 ); 22 23 endmodule |
仿真波形如下:
觀察波形可以得到:
temp[0] [0] = indata[0];
temp[0] [1] = indata[1];
temp[1] [0] = indata[2];
temp[1] [0] = indata[3];
temp[2] [0] = indata[4];
temp[2] [1] = indata[5];
temp[3] [0] = indata[6];
temp[3] [1] = indata[7];
由此得到for_test2模塊第9~16行可以這樣展開:
assign temp[0] [0] = indata[0];
assign temp[0] [1] = indata[1];
assign temp[1] [0] = indata[2];
assign temp[1] [0] = indata[3];
assign temp[2] [0] = indata[4];
assign temp[2] [1] = indata[5];
assign temp[3] [0] = indata[6];
assign temp[3] [1] = indata[7];
我們發現,這段代碼是通過i和j的增加來重復執行
temp[i][j] = indata[2*i+j]
這條語句的,所以generate_for可以實現模塊的復制。
genrate-if
generate_for是用於復制模塊,而generate_if則是根據模塊的參數(必須是常量)作為條件判斷,來產生滿足條件的電路。如:
/**************************************************** * Engineer : 夢翼師兄 * QQ : 761664056 * The module function : generate_if模塊 *****************************************************/ 01 module if_test(a, b, c, d); 02 03 input a, b, c; //輸入信號a,b,c 04 output d; //輸出信號d 05 06 localparam WIDE = 8; //參數模塊,用於選擇產生的電路 07 08 generate 09 if(WIDE <10) //當WIDE小於10,d等於abc相或 10 assign d = a | b | c; 11 else //當WIDE大於等於10,d等於abc相與 12 assign d = a & b & c; 13 endgenerate 14 15 endmodule |
該代碼生成的RTL電路圖如下:
當把WIDE改成等於12的時候,代碼如下:
/**************************************************** * Engineer : 夢翼師兄 * QQ : 761664056 * The module function : generate_if模塊 *****************************************************/ 01 module if_test(a, b, c, d); 02 03 input a, b, c; //輸入信號a,b,c 04 output d; //輸出信號d 05 06 localparam WIDE = 12; //參數模塊,用於選擇生產的電路 07 08 generate 09 if(WIDE <10) //當WIDE小於10,d等於abc相或 10 assign d = a | b | c; 11 else //當WIDE大於等於10,d等於abc相與 12 assign d = a & b & c; 13 endgenerate 14 15 endmodule |
該代碼生成的RTL電路圖如下:
從上面2個不同的WIDE值得出的RTL圖可知,generate_if是根據模塊的參數來作為判斷條件,來產生滿足條件的電路,當WIDE等於8時,d等於abc相或,對應於我們代碼的第9~10行;當WIDE等於12時,d等於abc相與,對應於我們代碼的第11~12行。
generate-case
generate_case其實跟generate_if一樣的,都是根據模塊的參數(必須是常量)作為條件判斷,來生成滿足條件的電路,不同的地方僅僅是改成使用case 的語法而已。如:
/**************************************************** * Engineer : 夢翼師兄 * QQ : 761664056 * The module function : generate_case模塊 *****************************************************/ 01 module case_test(a, b, c, d); 02 03 input a, b, c; //輸入信號a,b,c 04 output d; //輸出信號d 05 06 localparam WIDE = 12; //參數模塊,用於選擇生產的電路 07 08 generate 09 case(WIDE) 10 0 : //當WIDE等於0,d等於abc相或 11 assign d = a | b | c; 12 13 1 : //當WIDE等於1,d等於abc相與 14 assign d = a & b & c; 15 16 default : //當WIDE不等於1或0,d等於a與b或c 17 assign d = a & b | c; 18 19 endcase 20 endgenerate 21 22 endmodule |
該代碼生成的RTL電路圖如下:
我們將參數WIDE設置位0,生成的RTL電路圖如下:
將參數WIDE設置位1,生成的RTL電路圖如下:
從上面3個不同的WIDE值得出的RTL圖可知,generate_case也是根據模塊的參數來作為條件判斷,來產生滿足條件的電路,當WIDE等於12時,d等於a與b或c,對應於我們代碼的第16~17行;當WIDE等於0時,d等於abc相或,對應於我們代碼的第10~11行;當WIDE等於1時,d等於abc相與,對應於我們代碼的第13~14行。