首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Verilog中generate的使用

Verilog中generate的使用

作者头像
数字IC小站
发布于 2020-07-01 02:49:25
发布于 2020-07-01 02:49:25
5.1K00
代码可运行
举报
文章被收录于专栏:数字IC小站数字IC小站
运行总次数:0
代码可运行

Verilog中的generate语句常用于编写可配置的、可综合的RTL的设计结构。它可用于创建模块的多个实例化,或者有条件的实例化代码块。然而,有时候很困惑generate的使用方法,因此看下generate的几种常用用法。

generate的结构类型

我们常用generate语句做三件事情。一个是用来构造循环结构,用来多次实例化某个模块。一个是构造条件generate结构,用来在多个块之间最多选择一个代码块,条件generate结构包含if--generate结构和case--generate形式。还有一个是用来断言。

在Verilog中,generate在建模(elaboration)阶段实施,出现预处理之后,正式模拟仿真之前。因此。generate结构中的所有表达式都必须是常量表达式,并在建模(elaboration)时确定。例如,generate结构可能受参数值的影响,但不受动态变量的影响。

Verilog中的generate块创建了新的作用域和新的层次结构,就像实例化模块一样。因此在尝试对generate块中的信号进行引用时,很容易因此混乱,因此请记住这一点。

1.generate循环结构

generate循环的语法与for循环语句的语法很相似。但是在使用时必须先在genvar声明中声明循环中使用的索引变量名,然后才能使用它。genvar声明的索引变量被用作整数用来判断generate循环。genvar声明可以是generate结构的内部或外部区域,并且相同的循环索引变量可以在多个generate循环中,只要这些环不嵌套。genvar只有在建模的时候才会出现,在仿真时就已经消失了。

在“展开”生成循环的每个实例中,将创建一个隐式localparam,其名称和类型与循环索引变量相同。它的值是“展开”循环的特定实例的“索引”。可以从RTL引用此localparam以控制生成的代码,甚至可以由分层引用来引用。

Verilog中generate循环中的generate块可以命名也可以不命名。如果已命名,则会创建一个generate块实例数组。如果未命名,则有些仿真工具会出现警告,因此,最好始终对它们进行命名。

我们来看个关于generate循环的例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module alu ( input   a, b,            output  sum, cout);  assign sum  = a ^ b;  assign cout = a & b;endmodule
module my_design    #(parameter N=4)        (   input [N-1:0] a, b,            output [N-1:0] sum, cout);
    genvar i;
    // Generate for loop to instantiate N times    generate (optional)        for (i = 0; i < N; i++) begin:gen          alu alu_inst (a[i], b[i], sum[i], cout[i]);        end    endgenerateendmodule

仿真代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module tb;  parameter N = 2;  reg  [N-1:0] a, b;  wire [N-1:0] sum, cout;
  my_design #(.N(N)) md( .a(a), .b(b), .sum(sum), .cout(cout));
  initial begin    a <= 0;    b <= 0;     $monitor ("a=0x%0h b=0x%0h sum=0x%0h cout=0x%0h", a, b, sum, cout);
    #10 a <= 'h2;    b <= 'h3;    #20 b <= 'h4;    #10 a <= 'h5;  endendmodule

仿真结果如上所述,那么generate for循环和普通的for循环相比有什么优点呢?通常,generate for循环和普通 for循环之间的主要区别在于generate for循环正在为每次迭代生成一个实例。这意味着在上述示例中将始终有2个实例块(与常规循环情况下的1个块相反)。

2.条件if-generate构造

条件语句从很多的备选块中选择最多一个generate块,请注意,在这我说的是最多,因为有可能是一个也不选择的。在建模中,条件必须为常量表达式。

条件if-generate不关心是否命名,并且可以不具有begin / end。当然,上述两个条件只能包含一项。它也会创建单独的范围和层次结构级别,这个和generate循环是一样的。由于最多选择一个代码块,因此在单个的if-generate中以相同的名称命名所有的备用代码块是合法的,而且这有助于保持对代码的分层引用。但是,不同的generate构造中必须具有不同的名称。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module mux_assign ( input a, b, sel,                   output out);  assign out = sel ? a : b;
  initial      $display ("mux_assign is instantiated");endmodule
module mux_case (input a, b, sel,                 output reg out);  always @ (a or b or sel) begin      case (sel)        0 : out = a;           1 : out = b;      endcase  end
  initial    $display ("mux_case is instantiated");endmodule
module my_design (    input a, b, sel,                     output out);  parameter USE_CASE = 0;
  generate    if (USE_CASE) begin:u1      mux_case mc (.a(a), .b(b), .sel(sel), .out(out));    end    else begin:u1      mux_assign ma (.a(a), .b(b), .sel(sel), .out(out));    end  endgenerate
endmodulemodule tb;  reg a, b, sel;  wire out;  integer i;
  my_design #(.USE_CASE(0)) u0 ( .a(a), .b(b), .sel(sel), .out(out));
  initial begin      a <= 0;    b <= 0;    sel <= 0;
    for (i = 0; i < 5; i = i + 1) begin      #10 a <= $random;            b <= $random;          sel <= $random;      $display ("i=%0d a=0x%0h b=0x%0h sel=0x%0h out=0x%0h", i, a, b, sel, out);    end  end
  initial begin
    $dumpfile("dump.vcd");    $dumpvars(1);  endendmodule

仿真结果如下:因此,generate可以代替if..else,并且是在不需要时钟的情况下,可以选择实例化不同的模块。注意,此种写法中,是不含有genvar的。

3.条件case-generate构造

与if-generate类似,case-generate也可用于从几个块中有条件地选择一个代码块。它的用法类似于基本case语句,并且if-generate中的所有规则也适用于case-generate块。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module test;  parameter p = 0, q = 0;  wire a, b, c;
  //---------------------------------------------------------  // Code to either generate a u1.g1 instance or no instance.  // The u1.g1 instance of one of the following gates:  // (and, or, xor, xnor) is generated if  // {p,q} == {1,0}, {1,2}, {2,0}, {2,1}, {2,2}, {2, default}  //---------------------------------------------------------
if (p == 2)    case (q)      0, 1, 2:        begin : u1 // If p==2 and q==0,1, or 2, then instantiate          xor g1(a, b, c); // XOR with hierarchical name test.u1.g1        end      default:        begin : u1 // If p==2 and q!=0,1, or 2, then instantiate          xnor g1(a, b, c); // XNOR with hierarchical name test.u1.g1        end    endcase
endmodule

此generate构造将最多选择一个名为u1的块。该块中的门实例的层级名称为test.u1.g1。

4.断言和形式验证

在编写断言时,generate构造也非常有用,这反过来有助于形式验证。例如,如果有一个具有8个REQquest输入和8个ACK输出的仲裁器块,那么与其编写单个断言来覆盖所有8个REQ / ACK对,不如将其分解为具有1个REQ / ACK的8个独立断言每个声明对。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
genvar k;generate    for (k=0; k < 8; k++) begin        req_a: assert property (req[k] |=> ack[k]);    endendgenerate

换个例子,假设我们需要对一个双向的系统,含有客户端和服务器端,需要对双向进行断言,我们可以使用generate构造,将属性定义为assert或者assume等。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module client_server_properties (/*IOs go here*/);    parameter CLIENT_IS_DUT = 1;    parameter SERVER_IS_DUT = 0;
    `define CLIENT_ASSERT (name, prop, msg) \        generate if (CLIENT_IS_DUT) begin \           name: assert property (prop) else $error (msg); \        end else begin \           name: assume property (prop) else $error (msg); \        end \        endgenerate
    `define SERVER_ASSERT (name, prop, msg) \        generate if (SERVER_IS_DUT) begin \           name: assert property (prop) else $error (msg); \        end else begin \           name: assume property (prop) else $error (msg); \        end \        endgenerate
    // Properties    property client_ack;        @(posedge clk) disable iff (reset)        (req |=> ack);    endproperty    `CLIENT_ASSERT(client_ack_A, client_ack, "No ACK received");
endmodule

5.层次化访问生成的模块

前面也提到过,使用generate会产生层次化,并且选择的模块或者产生的模块都会具有一个名称。如果未命名,则编译器将自动分配一个通用名称。

要访问generate块中的模块项,您必须使用<generate_blk_name>.<module_item_name>进行分层访问。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
module dimm(addr, ba, rasx, casx, csx, wex, cke, clk, dqm, data, dev_id);    parameter [31:0] MEM_WIDTH = 16, MEM_SIZE = 8;    ...     genvar i;    case ({MEM_SIZE, MEM_WIDTH})        {32'd8, 32'd16}: // 8Meg x 16 bits wide        begin: memory            for (i=0; i<4; i=i+1) begin:word16                sms_08b216t0 p(.clk(clk), .csb(csx), .cke(cke),.ba(ba),                    .addr(addr), .rasb(rasx), .casb(casx),                    .web(wex), .udqm(dqm[2*i+1]), .ldqm(dqm[2*i]),                    .dqi(data[15+16*i:16*i]), .dev_id(dev_id));                // The hierarchical instance names are:                // memory.word16[3].p, memory.word16[2].p,                // memory.word16[1].p, memory.word16[0].p,                // and the task memory.read_mem            end            task read_mem;                input [31:0] address;                output [63:0] data;                begin // call read_mem in sms module                    word16[3].p.read_mem(address, data[63:48]);                    word16[2].p.read_mem(address, data[47:32]);                    word16[1].p.read_mem(address, data[31:16]);                    word16[0].p.read_mem(address, data[15: 0]);                end            endtask        end    ...    endcaseendmodule

总结

generate构造是创建可配置RTL的强大方法,该RTL可以根据参数设置具有不同的行为。generate循环允许代码由索引控制多次实例化。条件generate可以有条件地实例化代码。关于generate构造的最重要建议是始终为它们命名,这有助于简化层次结构引用和代码维护。

End

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-01-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数字IC小站 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【Verilog我思我用】-generate
在使用xilinx官方例程《XAPP585》实现CameraLink接口发送或者接收数据时,有个程序还是值得学习的,下面把这段程序截出来:
碎碎思
2023/08/30
8390
【Verilog我思我用】-generate
HDLBits:在线学习Verilog(八 · Problem 35-39)
Problem 35: Always nolatches(Always nolatches)
数字积木
2021/04/15
7120
一周掌握FPGA Verilog HDL语法 day 6
大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。
FPGA技术江湖
2020/12/29
5660
一周掌握FPGA Verilog HDL语法 day 6
一周掌握FPGA Verilog HDL语法 day 7
大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。
FPGA技术江湖
2020/12/29
6680
一周掌握FPGA Verilog HDL语法 day 7
HDLBits:在线学习 Verilog (四 · Problem 15-19)
Problem 15 : Vector concatenation operator
数字积木
2021/04/15
7920
基于FPGA的模拟 I²C协议系统设计(下)
今天给大侠带来基于FPGA的 模拟 I²C 协议设计,由于篇幅较长,分三篇。今天带来第三篇,下篇,程序的仿真与测试。话不多说,上货。
FPGA技术江湖
2021/05/21
7580
基于FPGA的模拟 I²C协议系统设计(下)
一周掌握FPGA Verilog HDL语法 day 6
今天给大侠带来的是一周掌握FPGA Verilog HDL 语法,今天开启第六天。
FPGA技术江湖
2025/03/27
1010
一周掌握FPGA Verilog HDL语法 day 6
【收藏】FPGA数字IC刷题58个Verilog代码及讲解(状态机、跨时钟、同步/异步FIFO、DMUX、奇数/小数分频)
牛客 Verilog 刷题入门篇1~24 + 进阶篇1~34 题解代码,所有代码均能通过测试,配合视频讲解效果更佳。本文给出代码,部分题目给出必要说明。 很多题目本身出题有些问题,着重理解题目,没必要钻牛角尖。
FPGA探索者
2022/11/01
3.1K0
【收藏】FPGA数字IC刷题58个Verilog代码及讲解(状态机、跨时钟、同步/异步FIFO、DMUX、奇数/小数分频)
一周掌握FPGA Verilog HDL语法 day 4
大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。
FPGA技术江湖
2020/12/29
1.2K0
一周掌握FPGA Verilog HDL语法 day 4
HDLBits:在线学习 Verilog (九 · Problem 40 - 44)
Problem 40 Combinational for-loop: 255-bit population count
数字积木
2021/04/15
1.1K0
FPGA:Verilog HDL程序的基本结构
一般使用Primitive(内部元件)、自定义的下层模块对电路描述。主要用于层次化设计中。
timerring
2023/02/16
4000
FPGA:Verilog HDL程序的基本结构
基于FPGA的直接扩频通信系统设计(中)Verilog 实现
今天给大侠带来直接扩频通信,由于篇幅较长,分三篇。今天带来中篇,也是第二篇,系统的 verilog 实现 。话不多说,上货。
FPGA技术江湖
2021/05/21
7150
基于FPGA的直接扩频通信系统设计(中)Verilog 实现
verilog经典教程(ps入门教程自学图解)
input关键词,模块的输入信号,比如input Clk,Clk是外面关键输入的时钟信号;
全栈程序员站长
2022/08/01
1.6K0
verilog经典教程(ps入门教程自学图解)
HDLBits:在线学习Verilog( 五 · Problem 20-24)
Problem 20: Connecting ports by position(Module pos)
数字积木
2021/04/15
8410
基于迭代单元的恢复余数开方器基于迭代单元的恢复余数开方器
基于迭代单元的恢复余数开方器 基本算法 该开方器的算法与“手算”(以前并不知道开方还有这种手算的方法)算法相似,使用迭代解决,文字描述如下 将0为余数的初值a,0作为结果初值b 将被开方数前两位{I(2m + 1),I(2m)}取出,与01比较大小。若前两位大,则{I(2m + 1),I(2m)} - 01为输出余数(a(m)),输出结果1(b(m)),否则{I(2m + 1),I(2m)}为输出余数(a(m)),输出结果0(b(m)) 将被开方数的从高位数第3,4位{I(2m - 1),I(2m - 2
月见樽
2018/04/27
1.2K0
题解 | Verilog刷题解析及对应笔试面试注意点【6-9】(涉及==和===、for展开问题等)
目的:不仅仅是解题,更多的是想从真实的FPGA和数字IC实习秋招和实际工程应用角度,解读一些【笔试面试】所注意的知识点,做了一些扩展。
FPGA探索者
2022/05/26
1.3K0
题解 | Verilog刷题解析及对应笔试面试注意点【6-9】(涉及==和===、for展开问题等)
基于迭代单元的不恢复余数开方器基于迭代单元的不恢复余数开方器
基于迭代单元的不恢复余数开方器 基本算法 与恢复余数开方器类似,不恢复余数开方器也是通过迭代完成运算的,基本算法的伪代码如下所示 Ra = 被开方数(位宽2W) Re = 余数(初值为0) Dout = 0 for i in W -> 0 { if(Re > 0) { Re = {Re,Ra[2i - 1],Ra[2i]} - {Dout,2'b01} } else { Re = {Re,Ra[2i - 1],Ra[2i]} + {Dout,2'b11} } Dout = {
月见樽
2018/04/27
1.2K0
全并行流水线移位相加乘法器
基本算法 与分时复用的移位相加类似,取消分时复用,使用面积换时间,使用流水线设计,流水线填满后可以一个时钟周期计算出一个结果 分别计算乘数的移位结果,并与被乘数对应位相与 使用加法树将结果相加 RTL代码 移位部分 固定移位单元代码如下,当被乘数第n位为1时,输出乘数移位向左移位n位的结果 module shift_unit #( parameter WIDTH = 4, parameter SHIFT_NUM = 0 )( input clk, // Clock in
月见樽
2018/04/27
1.1K0
基于FPGA的VGA/LCD显示控制器系统设计(下)
今天给大侠带来基于FPGA的VGA/LCD显示控制器设计,由于篇幅较长,分三篇。今天带来第三篇,下篇,程序的仿真与测试以及总结,话不多说,上货。
FPGA技术江湖
2021/05/21
8160
题解 | Verilog刷题解析及对应笔试面试注意点【1-5】(涉及复位、有符号数问题等)
目的:不仅仅是解题,更多的是想从真实的FPGA和数字IC实习秋招和实际工程应用角度,解读一些【笔试面试】所注意的知识点,做了一些扩展。
FPGA探索者
2022/05/26
8500
题解 | Verilog刷题解析及对应笔试面试注意点【1-5】(涉及复位、有符号数问题等)
推荐阅读
相关推荐
【Verilog我思我用】-generate
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验