参考:vrilog数字系统设计 夏宇闻 【第3版】 5.7
生成块理解
生成语句可以动态的生成verilog代码,方便参数化模块的生成,大大的简化程序的编写过程,常用于以下情况:
- 对矢量中的多个位进行重复操作
- 进行多个模块的实例引用的重复操作
- 根据参数的定义来确定程序中是否应该包含某段Verilog代码
生成语句对primitive 和module 进行复制结构建模, 除了允许复制产生 primitive 和 module 的多个实例化,同时也可以复制产生多个net、reg、parameter、assign、always、initial、task、function。编写代码必须在关键字generate-endgenerate指定范围内 。
generate 语句有 generate-for、genreate-if 和 generate-case 三种语句。
generate-for 语句
- generate-for 语句必须用 genvar 关键字定义 for 的索引变量;索引变量必须是正整数,不可用“X”或”Z“或者“负值“。
- for 的内容必须用 begin…end 块包起来,哪怕只有一句;
- begin…end 块必须起个名字;
- genvar 变量可以声明在 generate 语句内,也可以声明在 generate 语句外。
例 1:例化多个module
genvar xdata_i;
reg [15:0] xdata_delay[xdata_delay_num-1:0];
reg xdata_en[xdata_delay_num-1:0];
reg [31:0] xdata_in[xdata_delay_num-1:0];
generate for(xdata_i=0; xdata_i<2; xdata_i = xdata_i + 1) begin: xdata_load_delay
xdata_load_ram xdata_delay (
.rst(~drophead_end),
.clk(sys_clk),
.delay(xdata_delay[xdata_i]),
.xdata_en(xdata_en[xdata_i]),
.xdata(xdata_in[xdata_i]),
.xdata_out(xdata_out_temp[xdata_i])
);
end
例化图示:
例 2:多层 generate 语句用法
module GENERATE_FOR_2;
localparam SIZE = 2;
genvar i,j,k,l;
generate
for(i=0; i<SIZE; i=i+1) begin:B1
DEMO1 INST1();
for(j=0;j<SIZE; j=j+1) begin:B2
DEMO2 INST2();
for(k=0; k<SIZE; k=k+1) begin:B3
DEMO3 INST3();
end
end
if(i>=0)
for(l=0; l<SIZE; l=l+1)begin:B4
DEMO4 INST4();
end
end
endgenerate
endmodule
例化图示:
例3:定义局部变量以及赋值
本例实现3个方面:在 begin…end 内部定义局部变量,genvar 变量声明在语句内,实现赋值。
module generate_for_3#(
parameter DATA_WIDTH = 2
)(
input clk,
input rst_n,
input [DATA_WIDTH-1:0] a,
input [DATA_WIDTH-1:0] b,
input [DATA_WIDTH-1:0] c,
output [DATA_WIDTH-1:0] out
);
reg [DATA_WIDTH-1:0] sum_reg;
wire [DATA_WIDTH-1:0] sum;
generate
genvar i;
for(i=0; i<DATA_WIDTH; i=i+1) begin: bit
wire sum_temp; // generated net declaration
xor out1 (sum_temp,a[i],b[i]);
and out2 (sum[i],sum_temp,c[i]);
assign out[i] = sum[i];
always @(posedge clk)begin
if(!rst_n)
sum_reg <= 0;
else
sum_reg <= sum;
end
end
endgenerate
endmodule
仿真结果如下图:
testbentch代码如下:
//~ `New testbench
`timescale 1ns / 1ps
module tb_generate_for_3;
// generate_for_3 Parameters
parameter PERIOD = 10;
parameter DATA_WIDTH = 2;
// generate_for_3 Inputs
reg clk=0;
reg rst_n=0;
reg [DATA_WIDTH-1:0] a = 0 ;
reg [DATA_WIDTH-1:0] b = 0 ;
reg [DATA_WIDTH-1:0] c = 0 ;
initial
begin
forever #(PERIOD/2) clk=~clk;
end
initial
begin
#(PERIOD*2) rst_n = 1;
end
generate_for_3 #(
.DATA_WIDTH ( 2 ))
u_generate_for_3 (
.clk (clk ),
.rst_n (rst_n ),
.a ( a [DATA_WIDTH-1:0] ),
.b ( b [DATA_WIDTH-1:0] ),
.c ( c [DATA_WIDTH-1:0] )
);
initial
begin
a = 2'b01;
b = 2'b11;
c = 2'b10;
#500;
a = 2'b11;
b = 2'b00;
c = 2'b01;
#500;
a = 2'b10;
b = 2'b01;
c = 2'b00;
#1500;
$finish;
end
endmodule
generate-if 语句
generate-if语句根据条件不同产生不同的实例化:根据模块参数(常量)的条件是否满足来选择其中一段代码生成相应的电路
例:
module generate_if_1;
localparam SIZE = 3;
wire [7:0] o_tdata;
wire o_tvalid;
generate
if(SIZE>9)
DEMO1 inst_1();
else if(SIZE==2)
begin
assign o_tdata = 8'd255;
assign o_tvalid = 1'd1;
end
else
DEMO2 inst_2();
endgenerate
endmodule
例化示意图如下:
generate-case 语句
用法跟 generate-if 语句一样,参数也必须是常数,只是采用 case 语句的形式。
例:
module generate_case;
localparam WIDTH = 3;
generate
case(WIDTH)
1:DEMO1 INST_1();
2:DEMO2 INST_2();
default: DEMO3 INST_3();
endcase
endgenerate
endmodule
例化示意图如下: