verilog语法-----generate结构
文章主要观点是从verilog-IEEE-2005里面提取的,讲的不透彻的,可以查看英文原本
Generate constructs
generate constructs用于在一个module中生成有条件的或嵌套的generate blocks。generate blocks是一个或多个module的集合。generate blocks可能不包含端口声明,参数声明,特定块或specparam声明。包含generate blocks在内的所有其他中module,允许出现在generate blocks中。generate blocks使参数值影响模型结构称为可能。它能更简洁地描述具有重复结构的模块,并使递归模块实例化成为可能。
有两种generate结构:循环和条件。 循环构造允许将单个generate blocks多次实例化为module的块。包括if-generate和case-generate构造的条件generate结构,最多可以从一组可替代的generate 块中实例化一个generate块。术语“generate scheme”是指确定哪个或多少个generate块需要被实例化。 它包括条件表达式,大小写替换和循环生成构造中出现的控制语句。
在模型生成期间评估generate scheme。 评估在HDL完成之后,simulation之前; 它涉及module实例化,计算参数值,解析层次结构名称(请参见12.5),建立网络连接,及为simulation准备模型。尽管generate scheme使用的语法类似于行为声明,但重要的是要它们不会在仿真时执行。 它在评估的时候完成,在simulation开始之前得到结果。 因此,generate scheme中的所有表达式都应为常量表达式,并在评估时确定。 有关详细说明的更多信息,请参见12.8。
一个generate结构的生成可以由一个或多个实例化的generate block构成。一个实例化的generate block在某种方式上和一个实例化的module是类似的。它创建了一个新的层次结构。它使block中的对象,行为构造和模块实例可以加入到已实现的模块中。这些结构添加到一个module中和一个已存在的module中加入module是类似的,只不过可以直接引用封闭范围中的对象声明(请参见12.7)。实例化的命名生成块中的名称可以按12.5中的描述分层引用。
关键字generate和endgenerate可以在模块中使用以定义generate region。generate region是module描述中可能会出现generate constructs的文本范围。使用generate regions是可选的。 使用generate region 时,模块中没有语义差异。 编译器可能会选择识别generate region,以针对误用的generate关键字生成不通的错误消息。generate region不会嵌套,它们只能直接出现在module内。 如果使用了generate关键字,则应与endgenerate关键字匹配。
The syntax for generate constructs is given in Syntax 12-5.
Loop generate constructs
循环generate constructs允许使用类似于for循环语句的语法将generate block实例化多次。循环索引变量必须在genvar声明中声明,然后才能在循环generate scheme中使用。
genvar在elaboration 期间用作整数,以评估generate循环并创建generate块的实例,但在仿真时不存在。genvar不得在循环生成方案以外的任何地方引用。
循环生成方案中的初始化和迭代分配都应分配给相同的genvar。初始化分配不得引用右侧的循环索引变量(如genvar i)。
在循环generate construct的generate block 中,有一个隐式localparam声明。这是一个整数参数,具有与循环索引变量相同的名称和类型,并且它在generate块的每个实例中的值都是在实例化时索引变量的值。此参数可以在generate块中可以使用具有整数值的常规参数的任何位置使用。
可以使用层次结构名称进行引用.
由于此隐式localparam与genvar具有相同的名称,因此在循环generate block中对此名称的任何引用将是对localparam的引用,而不是对genvar的引用。结果,不可能有两个使用相同genvar的嵌套循环生成构造.
循环generate constructs中的generate块可以命名或不命名,它们只能包含一项,而不必由begin / end关键字包围。即使没有开始/结束关键字,它仍然是一个生成块,与所有生成块一样,它在实例化时包括单独的作用域和新的层次结构级别。
如果generate块被命名,则它是generate block实例数组的声明。此数组中的索引值是elaboration过程中genvar假定的值。
这可以是一个间断数组,因为genvar值不必形成连续的整数范围。即使循环generate scheme未生成generate block的实例,也认为该数组声明。如果generate块未命名,除了在generate块本身实例化的层次结构中之外,不能使用层次结构名称来引用其中的声明。
如果generate block实例数组的名称与任何其他声明(包括任何其他generate block实例数组)发生冲突,则将是一个错误。如果循环generate scheme没有终止,那将是一个错误。如果在循环generate scheme的评估期间重复一个genvar值,将是一个错误。如果在评估循环generate scheme的过程中将genvar的任何位设置为x或z,将是一个错误。
Example 1—Examples of legal and illegal generate loops
示例3和示例4中的模型是使用循环生成Verilog门基元进位链加法器的参数化模块。 示例3在generate循环外部使用二维网络声明在门基元之间建立连接,而示例4在generate循环内部使用net声明来为循环的每次迭代生成连接门基元所需的线网。
Example 3—Generated ripple adder with two-dimensional net declaration outside of the generate loop
Example 4—Generated ripple adder with net declaration inside of the generate loop
备注:
这篇文章是博客里面最常见的一个,但是包含错误: 特点(2),(3)是错误的
https://blog.csdn.net/weixin_33714884/article/details/93500760?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-4
==========================================================================================
example 1----综合实现正确
module iddr_ctrl(
input wire rst_n,
//from phy
input wire[3:0] rx_dat,//双沿4bit数据 一个时钟周期传输8bit数据
input wire rx_ctrl,//上升沿对应dv 下降沿对应err
input wire rx_clk,//phy传输来的时钟相移90
//to mac
output reg[7:0] rx_data,//单沿8bit数据
output reg rx_en//8bit数据对应有效信号
);
wire tmp_dv;
wire tmp_err;
wire[7:0] tmp_data;
IDDR #(
.DDR_CLK_EDGE("OPPOSITE_EDGE"), // "OPPOSITE_EDGE", "SAME_EDGE"
// or "SAME_EDGE_PIPELINED"
.INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1
.INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1
.SRTYPE("ASYNC") // Set/Reset type: "SYNC" or "ASYNC"
) IDDR_dv (
.Q1(tmp_dv), // 1-bit output for positive edge of clock
.Q2(tmp_err), // 1-bit output for negative edge of clock
.C(rx_clk), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D(rx_ctrl), // 1-bit DDR data input
.R(1'b0), // 1-bit reset
.S(~rst_n) // 1-bit set
);
genvar i;
generate
for (i=0; i < 4; i=i+1)
begin
IDDR #(
.DDR_CLK_EDGE("OPPOSITE_EDGE"), // "OPPOSITE_EDGE", "SAME_EDGE"
// or "SAME_EDGE_PIPELINED"
.INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1
.INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1
.SRTYPE("ASYNC") // Set/Reset type: "SYNC" or "ASYNC"
) IDDR_data (
.Q1(tmp_data[i]), // 1-bit output for positive edge of clock
.Q2(tmp_data[i+4]), // 1-bit output for negative edge of clock
.C(rx_clk), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D(rx_dat[i]), // 1-bit DDR data input
.R(1'b0), // 1-bit reset
.S(~rst_n) // 1-bit set
);
end
endgenerate
always @(posedge rx_clk or negedge rst_n)
if(!rst_n)
rx_en <= 1'b0;
else
rx_en <= tmp_dv;
always @(posedge rx_clk or negedge rst_n)
if(!rst_n)
rx_data <= 8'b0;
else
rx_data <= tmp_data;
endmodule
example 2 ----综合,实现正确
module gry2bin #(
parameter length = 4
)
(
input wire [length-1:0] Gry,
output reg [length-1:0] Bin
);
integer i;
generate
always @(*)
begin
Bin[length - 1'b1] = Gry[length - 1'b1];
//generate
for(i=0; i<=length-2; i=i+1) begin
Bin[i] = Bin[i + 1'b1] ^ Gry[i] ;
end
//endgenerate
end
endgenerate
endmodule
example 3 ----综合错误
module gry2bin #(
parameter length = 4
)
(
input wire [length-1:0] Gry,
output reg [length-1:0] Bin
);
integer i;
always @(*)
begin
Bin[length - 1'b1] = Gry[length - 1'b1];
generate
for(i=0; i<=length-2; i=i+1) begin
Bin[i] = Bin[i + 1'b1] ^ Gry[i] ;
end
endgenerate
end
endmodule