verilog中generate用法及参数传递
一:generate
Verilog-2001添加了generate循环,允许产生module和primitive的多个实例化,同时也可以产生多个variable,net,task,function,continous assignment,initial和always。在generate语句中可以引入if-else和case语句,根据条件不同产生不同的实例化。
用法:
1. generate语法有generate for, genreate if和generate case三种
2. generate for语句必须有genvar关键字定义for的变量
3. for 的内容必须加begin和end
4. 必须给for语段起个名字
例子:
1. generate for例子:
generate for
1 generate
2
3 genvar i; //generate 8 samll fifo for in_data[i] 8X72
4
5 for(i=0; i<NUM_QUEUES; i=i+1) begin: in_arb_queues //NUM_QUEUES = 8
6
7 small_fifo
8
9 #( .WIDTH(DATA_WIDTH+CTRL_WIDTH),
10
11 .MAX_DEPTH_BITS(2))
12
13 in_arb_fifo
14
15 (// Outputs
16
17 .dout ({fifo_out_ctrl[i], fifo_out_data[i]}),
18
19 .full (),
20
21 .nearly_full (nearly_full[i]),
22
23 .prog_full (),
24
25 .empty (empty[i]),
26
27 // Inputs
28
29 .din ({in_ctrl[i], in_data[i]}),
30
31 .wr_en (in_wr[i]),
32
33 .rd_en (rd_en[i]),
34
35 .reset (reset),
36
37 .clk (clk));
38
39 end // block: in_arb_queues
40
41 endgenerate
2
3 genvar i; //generate 8 samll fifo for in_data[i] 8X72
4
5 for(i=0; i<NUM_QUEUES; i=i+1) begin: in_arb_queues //NUM_QUEUES = 8
6
7 small_fifo
8
9 #( .WIDTH(DATA_WIDTH+CTRL_WIDTH),
10
11 .MAX_DEPTH_BITS(2))
12
13 in_arb_fifo
14
15 (// Outputs
16
17 .dout ({fifo_out_ctrl[i], fifo_out_data[i]}),
18
19 .full (),
20
21 .nearly_full (nearly_full[i]),
22
23 .prog_full (),
24
25 .empty (empty[i]),
26
27 // Inputs
28
29 .din ({in_ctrl[i], in_data[i]}),
30
31 .wr_en (in_wr[i]),
32
33 .rd_en (rd_en[i]),
34
35 .reset (reset),
36
37 .clk (clk));
38
39 end // block: in_arb_queues
40
41 endgenerate
2.generate if例子:
generate if
1 generate
2
3 if (REG_WIDTH == WRITE_WIDTH) begin : new_data_a_generation
4
5 assign new_data_a = merge_update ? merge_wr_data : held_wr_data_a;
6
7 end
8
9 else begin
10
11 assign new_data_a = merge_update ?
12
13 {{(REG_WIDTH - WRITE_WIDTH - 1){merge_wr_data_sign}}, merge_wr_data} :
14
15 {{(REG_WIDTH - WRITE_WIDTH){held_wr_data_sign_a}}, held_wr_data_a};
16
17 end
18
19 endgenerate
2
3 if (REG_WIDTH == WRITE_WIDTH) begin : new_data_a_generation
4
5 assign new_data_a = merge_update ? merge_wr_data : held_wr_data_a;
6
7 end
8
9 else begin
10
11 assign new_data_a = merge_update ?
12
13 {{(REG_WIDTH - WRITE_WIDTH - 1){merge_wr_data_sign}}, merge_wr_data} :
14
15 {{(REG_WIDTH - WRITE_WIDTH){held_wr_data_sign_a}}, held_wr_data_a};
16
17 end
18
19 endgenerate
3.generate还可以进行多个assign赋值!
generate assign
1 module anytest_v(
2 input clk,
3 input[7:0] datain,
4 output[7:0] dataout,
5 output finish
6 );
7
8 wire[7:0] mem[31:0];
9 wire[32*8-1:0] xxx;
10 //reg[7:0] i;
11 generate
12 genvar i;
13 for(i=0;i<=31;i=i+1)
14 begin :wiertech
15 assign mem[i]= 8'b0;
16 end
17 endgenerate
18 endmodule
2 input clk,
3 input[7:0] datain,
4 output[7:0] dataout,
5 output finish
6 );
7
8 wire[7:0] mem[31:0];
9 wire[32*8-1:0] xxx;
10 //reg[7:0] i;
11 generate
12 genvar i;
13 for(i=0;i<=31;i=i+1)
14 begin :wiertech
15 assign mem[i]= 8'b0;
16 end
17 endgenerate
18 endmodule
ps: 对于a[8*i+:8] this is the so-called "Indexed vector part selects"
在Verilog-1995中,可以选择向量的任一位输出,也可以选择向量的连续几位输出,不过此时连续几位的始末数值的index需要是常量。而在Verilog-2001中,可以用变量作为index,进行part select。
[base_expr +: width_expr] //positive offset
[base_expr -: width_expr] //negative offset
[base_expr -: width_expr] //negative offset
reg [63:0] word;
reg [3:0] byte_num; //a value from 0 to 7
wire [7:0] byteN = word[byte_num*8 +: 8];
reg [3:0] byte_num; //a value from 0 to 7
wire [7:0] byteN = word[byte_num*8 +: 8];
二、参数传递
类似VHDL的Generic语句,Verilog也可以在例化时传递参数
传递的参数是子模块中定义的parameter。
传递的方法:
1、
module_name #( parameter1, parameter2) inst_name( port_map);
2、
module_name #( .parameter_name(para_value), .parameter_name(para_value)) inst_name (port map);
用#方法和port map的写法差不多
module multiplier (a, b, product);
parameter a_width = 8, b_width = 8;
localparam product_width = a_width+b_width;
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) u1 (a, b, product);
else
WALLACE_multiplier #(a_width, b_width) u1 (a, b, product);
endgenerate
endmodule
parameter a_width = 8, b_width = 8;
localparam product_width = a_width+b_width;
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) u1 (a, b, product);
else
WALLACE_multiplier #(a_width, b_width) u1 (a, b, product);
endgenerate
endmodule