generae 在Verilog中的使用
Verilog-2001之generate語句的用法
Verilog-1995 支援通過以宣告例項陣列的形式對primitive和module進行復制結構建模。而在Verilog-2001裡,新增加的generate語句拓展了這種用法(其思想來源於VHDL語言)。除了允許複製產生primitive和module的多個例項化,同時也可以複製產生多個net、reg、parameter、assign、always、initial、task、function。
在generate中引入了一種新的變數型別:genvar,用以在generate-for語句中宣告一個正整數的索引變數(如果將“X”或“Z”或者“負值”賦給genvar 變數,將會出錯)。genvar 變數可以宣告在generate語句內,也可以宣告在generate語句外。
generate語句有generate-for、genreate-if和generate-case三種語句;
generate-for語.
①generate-for語句必需用genvar關鍵字定義for的索引變數;
②for的內容必須用begin…end塊包起來,哪怕只有一句;
③begin…end塊必須起個名字;
例1:一個引數化的gray-code to binary-code 轉換器;這裡採用複製產生多個assign語句的形式來實現;
module gray2bin1 (bin, gray); parameter SIZE = 8; // this module is parameterizable output [SIZE-1:0] bin; input [SIZE-1:0] gray; genvar i; generate for(i=0; i<SIZE; i=i+1) begin:bit assign bin[i] = ^gray[SIZE-1:i]; end endgenerate endmodule
等同於下面的語句:
assign bin[0] = ^gray[SIZE-1:0];
assign bin[1] = ^gray[SIZE-1:1];
assign bin[2] = ^gray[SIZE-1:2];
assign bin[3] = ^gray[SIZE-1:3];
assign bin[4] = ^gray[SIZE-1:4];
assign bin[5] = ^gray[SIZE-1:5];
assign bin[6] = ^gray[SIZE-1:6];
assign bin[7] = ^gray[SIZE-1:7];
例2:還是例1的gray-code to binary-code 轉換器;不過這裡採用複製產生多個always語句的形式來實現;
module gray2bin2 (bin, gray);
parameter SIZE = 8; // this module is parameterizable
output [SIZE-1:0] bin;
input [SIZE-1:0] gray;
reg [SIZE-1:0] bin;
genvar i;
generate
for(i=0; i<SIZE; i=i+1)
begin:bit
always @(gray[SIZE-1:i]) // fixed part select
bin[i] = ^gray[SIZE-1:i];
end
endgenerate
endmodule
等同於下面的語句:
always @(gray[SIZE-1:0]) //fixed part select
bin[0] = ^gray[SIZE-1:0];
always @(gray[SIZE-1:1]) // fixed part select
bin[1] = ^gray[SIZE-1:1];
always @(gray[SIZE-1:2]) // fixed part select
bin[2] = ^gray[SIZE-1:2];
always @(gray[SIZE-1:3]) // fixed part select
bin[3] = ^gray[SIZE-1:3];
always @(gray[SIZE-1:4]) // fixed part select
bin[4] = ^gray[SIZE-1:4];
always @(gray[SIZE-1:5]) // fixed part select
bin[5] = ^gray[SIZE-1:5];
always @(gray[SIZE-1:6]) // fixed part select
bin[6] = ^gray[SIZE-1:6];
always @(gray[SIZE-1:7]) // fixed part select
bin[7] = ^gray[SIZE-1:7];
例3:一個行波進位加法器,在begin…end內部定義區域性變數,並且在generate語句內定義genvar變數;
moduleaddergen1 (co, sum, a, b, ci);
parameter SIZE = 4;
output [SIZE-1:0] sum;
output co;
input [SIZE-1:0] a, b;
input ci;
wire [SIZE :0] c;
assign c[0] = ci;
generate
genvar i;
for(i=0; i<SIZE; i=i+1)
begin:bit
wiret1, t2, t3; // generated net declaration
xorg1 (t1, a[i], b[i]);
xorg2 (sum[i], t1, c[i]);
andg3 (t2, a[i], b[i]);
andg4 (t3, t1, c[i]);
org5 (c[i+1], t2, t3);
end
endgenerate
assign co = c[SIZE];
endmodule
等同於下面的語句:
wire bit[0].t1, bit[0].t2, bit[0].t3;
xor bit[0].g1 (bit[0].t1, a[0], b[0]);
xor bit[0].g2 (sum[0], bit[0].t1, c[0]);
and bit[0].g3 (bit[0].t2, a[0], b[0]);
and bit[0].g4 (bit[0].t3, bit[0].t1, c[0]);
or bit[0].g5 (c[0+1], bit[0].t2, bit[0].t3);
wire bit[1].t1, bit[1].t2, bit[1].t3;
xor bit[1].g1 (bit[1].t1, a[1], b[1]);
xor bit[1].g2 (sum[1], bit[1].t1, c[1]);
and bit[1].g3 (bit[1].t2, a[1], b[1]);
and bit[1].g4 (bit[1].t3, bit[1].t1, c[1]);
or bit[1].g5 (c[1+1], bit[1].t2, bit[1].t3);
wire bit[2].t1, bit[2].t2, bit[2].t3;
xor bit[2].g1 (bit[2].t1, a[2], b[2]);
xor bit[2].g2 (sum[2], bit[2].t1, c[2]);
and bit[2].g3 (bit[2].t2, a[2], b[2]);
and bit[2].g4 (bit[2].t3, bit[2].t1, c[2]);
or bit[2].g5 (c[2+1], bit[2].t2, bit[2].t3);
wire bit[3].t1, bit[3].t2, bit[3].t3;
xor bit[3].g1 (bit[3].t1, a[3], b[3]);
xor bit[3].g2 (sum[3], bit[3].t1, c[3]);
and bit[3].g3 (bit[3].t2, a[3], b[3]);
and bit[3].g4 (bit[3].t3, bit[3].t1, c[3]);
or bit[3].g5 (c[3+1], bit[3].t2, bit[3].t3);
這樣,複製產生的例項名稱為:
xor gates: bit[0].g1 bit[1].g1 bit[2].g1 bit[3].g1
bit[0].g2 bit[1].g2 bit[2].g2 bit[3].g2
and gates: bit[0].g3 bit[1].g3 bit[2].g3 bit[3].g3
bit[0].g4 bit[1].g4 bit[2].g4 bit[3].g4
or gates: bit[0].g5 bit[1].g5 bit[2].g5 bit[3].g5
複製產生的wire組為:
bit[0].t1 bit[1].t1 bit[2].t1 bit[3].t1
bit[0].t2 bit[1].t2 bit[2].t2 bit[3].t2
bit[0].t3 bit[1].t3 bit[2].t3 bit[3].t3
可見,給begin…end塊命名的用途!
例4:一個行波進位加法器,使用外部定義的變數,這樣就不會對外部變數做變動;
module addergen1 (co, sum, a, b, ci);
parameter SIZE = 4;
output [SIZE-1:0] sum;
output co;
input [SIZE-1:0] a, b;
input ci;
wire [SIZE :0] c;
wire [SIZE-1:0] t [1:3];
genvar i;
assign c[0] = ci;
generate
for(i=0; i<SIZE; i=i+1)
begin:bit
xorg1 ( t[1][i], a[i], b[i]);
xorg2 ( sum[i], t[1][i], c[i]);
andg3 ( t[2][i], a[i], b[i]);
andg4 ( t[3][i], t[1][i], c[i]);
org5 ( c[i+1], t[2][i], t[3][i]);
end
endgenerate
assign co = c[SIZE];
endmodule
這樣,複製產生的例項名稱為:
xor gates: bit[0].g1 bit[1].g1 bit[2].g1 bit[3].g1
bit[0].g2 bit[1].g2 bit[2].g2 bit[3].g2
and gates: bit[0].g3 bit[1].g3 bit[2].g3 bit[3].g3
bit[0].g4 bit[1].g4 bit[2].g4 bit[3].g4
or gates: bit[0].g5 bit[1].g5 bit[2].g5 bit[3].g5
而外部變數t與a,b,sum等一樣,沒有複製產生新的變數組
例5:多層generate語句所複製產生的例項命名方式;
parameterSIZE = 2;
genvari, j, k, m;
generate
for(i=0; i<SIZE; i=i+1)
begin:B1// scope B1[i]
M1 N1(); // instantiates B1[i].N1
for(j=0; j<SIZE; j=j+1)
begin:B2// scope B1[i].B2[j]
M2 N2(); // instantiates B1[i].B2[j].N2
for(k=0; k<SIZE; k=k+1)
begin:B3// scope B1[i].B2[j].B3[k]
M3 N3(); // instantiates B1[i].B2[j].B3[k].N3
end
end
if(i>0)
for(m=0; m<SIZE; m=m+1)
begin:B4// scope B1[i].B4[m]
M4 N4(); // instantiates B1[i].B4[m].N4
end
end
endgenerate
下面是複製產生的例項名稱的幾個例子:
B1[0].N1 B1[1].N1
B1[0].B2[0].N2 B1[0].B2[1].N2
B1[0].B2[0].B3[0].N3 B1[0].B2[0].B3[1].N3
B1[0].B2[1].B3[0].N3
B1[1].B4[0].N4 B1[1].B4[1].N4
generate-if語.
根據條件不同產生不同的例項化,即根據模組引數(.量)的條件是否滿足來選擇其中一段程式碼生成相應的電路,例如ifdef …elsif else …endif;
例1:
module generate_if (a,b,c,y);
input a,b,c;
output y;
localparam SIZE = 12;// 引數常量
generate
if (SIZE < 8)
assign y = a & b & c;
else if (SIZE == 8)
assign y = a & b | c;
else
assign y = a | b | c;// 最後該語句生成電路;
endgenerate
endmodule
例2:
module multiplier(a,b,product);
parameter a_width = 8, b_width = 8;
localparam product_width = a_width+b_width;
// localparamcan not be modifieddirectly with thedefparamstatementor the module instance statement,它是內部使用的區域性引數#
input[a_width-1:0] a;
input[b_width-1:0] b;
output[product_width-1:0] product;
generate
if((a_width < 8) || (b_width < 8))
CLA_multiplier #(a_width,b_width) u0(a, b, product);
// instantiate a CLA multiplier
else
WALLACE_multiplier #(a_width,b_width)u1(a,b,product);
// instantiate a Wallace-tree multiplier
endgenerate
// The generated instance name is u1
endmodule
注意:這裡的條件都是常量條件,非常量條件不能綜合;
generate-case語.
跟generate-if語句一樣的用法,只是採用case語句的形式
例1:
generate
case(WIDTH)
1: adder_1bit x1(co, sum, a, b, ci);
// 1-bit adder implementation
2: adder_2bit x1(co, sum, a, b, ci);
// 2-bit adder implementation
default: adder_cla #(WIDTH) x1(co, sum, a, b, ci);
// others -carry look-ahead adder
endcase
// The generated instance name is x1
endgenerate