Verilog初级教程(12)Verilog中的generate块
文章目录
- 前言
- 正文
- generate for
- generate if
- generate case
- 参考资料
- 本系列博文
前言
verilog中的generate块可以称为生成块,所谓生成,可以理解为复制。如果不太好理解,下面我们继续使用generate块。
generate块应用的场合通常是对模块进行批量例化,或者有条件的例化,使用参数进行控制对哪些模块进行例化,或者例化多少。
不仅限于模块例化,当同一个操作或模块实例需要多次重复,或者某些代码需要根据给定的Verilog参数有条件地包含时,这些语句特别方便。
generate块可以分为generate for和generate if或者generate case。
正文
下面根据实际例子对这几个generate块语句进行分析。
generate for
先设计一个半加器:
// Design for a half-adder
module ha ( input a, b,output sum, cout);assign sum = a ^ b;assign cout = a & b;
endmodule
下面对半加器模块例化N次,N为输入变量的位宽,例如:
input [N-1:0] a, b;
每一次对输入变量的一位进行加法运算。
如下:
// A top level design that contains N instances of half adder
module my_design#(parameter N=2)( input [N-1:0] a, b,output [N-1:0] sum, cout);// Declare a temporary loop variable to be used during// generation and won't be available during simulationgenvar i;// Generate for loop to instantiate N timesgeneratefor (i = 0; i < N; i = i + 1) beginha u0 (a[i], b[i], sum[i], cout[i]);endendgenerate
endmodule
a[0]和b[0]的输出sum[0]和cout[0],而a[N-1]和b[N-1]的输出sum[1]和cout[1]。
对应的RTL图可想而知,就是多个半加器的复制。
如果N = 2,则为:
generate if
generate if中的条件必须是参数,这是很重要的一点,初学者容易误用,例如将generate if(),括号内给一个变量,根据其值选择执行哪一块语句。
下面设计一个仅用于仿真的例子:
我们先设计两个待选择模块:
// Design #1: Multiplexer design uses an "assign" statement to assign
// out signal
module mux_assign ( input a, b, sel,output out);assign out = sel ? a : b;// The initial display statement is used so that// we know which design got instantiated from simulation// logsinitial$display ("mux_assign is instantiated");
endmodule
// Design #2: Multiplexer design uses a "case" statement to drive
// out signal
module mux_case (input a, b, sel,output reg out);always @ (a or b or sel) begincase (sel)0 : out = a;1 : out = b;endcaseend// The initial display statement is used so that// we know which design got instantiated from simulation// logsinitial$display ("mux_case is instantiated");
endmodule
下面使用generate if语句来选择例化哪一个模块:
// Top Level Design: Use a parameter to choose either one
module my_design ( input a, b, sel,output out);parameter USE_CASE = 0;// Use a "generate" block to instantiate either mux_case// or mux_assign using an if else construct with generategenerateif (USE_CASE)mux_case mc (.a(a), .b(b), .sel(sel), .out(out));elsemux_assign ma (.a(a), .b(b), .sel(sel), .out(out));endgenerateendmodule
USE_CASE就是一个参数,根据参数的值来选择例化哪一个模块。
设计仿真文件来验证:
module tb;// Declare testbench variablesreg a, b, sel;wire out;integer i;// Instantiate top level design and set USE_CASE parameter to 1 so that// the design using case statement is instantiatedmy_design #(.USE_CASE(1)) u0 ( .a(a), .b(b), .sel(sel), .out(out));initial begin// Initialize testbench variablesa <= 0;b <= 0;sel <= 0;// Assign random values to DUT inputs with some delayfor (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);endend
endmodule
上面仿真文件中将USE_CASE代入参数为1,因此,应该例化的是mux_case 被执行。
// When USE_CASE = 1
ncsim> run
mux_case is instantiated
i=0 a=0x0 b=0x0 sel=0x0 out=0x0
i=1 a=0x0 b=0x1 sel=0x1 out=0x1
i=2 a=0x1 b=0x1 sel=0x1 out=0x1
i=3 a=0x1 b=0x0 sel=0x1 out=0x0
i=4 a=0x1 b=0x0 sel=0x1 out=0x0
ncsim: *W,RNQUIE: Simulation is complete.
generate case
generate case语句和generate if语句用法无异,和普通的if与case一致,if具有优先级,case没有优先级。
举个例子,介绍其使用方法。
先设计一个半加器:
// Design #1: Half adder
module ha (input a, b,output reg sum, cout);always @ (a or b){cout, sum} = a + b;initial$display ("Half adder instantiation");
endmodule
在设计一个全加器:
// Design #2: Full adder
module fa (input a, b, cin,output reg sum, cout);always @ (a or b or cin){cout, sum} = a + b + cin;initial$display ("Full adder instantiation");
endmodule
设计顶层模块,令参数为ADDER_TYPE = 1;则如下:
// Top level design: Choose between half adder and full adder
module my_adder (input a, b, cin,output sum, cout);parameter ADDER_TYPE = 1;generatecase(ADDER_TYPE)0 : ha u0 (.a(a), .b(b), .sum(sum), .cout(cout));1 : fa u1 (.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout));endcaseendgenerate
endmodule
设计仿真文件:
module tb;reg a, b, cin;wire sum, cout;my_adder #(.ADDER_TYPE(0)) u0 (.a(a), .b(b), .cin(cin), .sum(sum), .cout(cout));initial begina <= 0;b <= 0;cin <= 0;$monitor("a=0x%0h b=0x%0h cin=0x%0h cout=0%0h sum=0x%0h",a, b, cin, cout, sum);for (int i = 0; i < 5; i = i + 1) begin#10 a <= $random;b <= $random;cin <= $random;endend
endmodule
可见,代入参数为0,应该例化的为半加器模块:
ncsim> run
Half adder instantiation
a=0x0 b=0x0 cin=0x0 cout=00 sum=0x0
a=0x0 b=0x1 cin=0x1 cout=00 sum=0x1
a=0x1 b=0x1 cin=0x1 cout=01 sum=0x0
a=0x1 b=0x0 cin=0x1 cout=00 sum=0x1
ncsim: *W,RNQUIE: Simulation is complete.
参考资料
参考资料
本系列博文
Verilog初级教程(11)Verilog中的initial块
Verilog初级教程(10)Verilog的always块
Verilog初级教程(9)Verilog的运算符
Verilog初级教程(8)Verilog中的assign语句
Verilog初级教程(7)Verilog模块例化以及悬空端口的处理
Verilog初级教程(6)Verilog模块与端口
Verilog初级教程(5)Verilog中的多维数组和存储器
Verilog初级教程(4)Verilog中的标量与向量
Verilog初级教程(3)Verilog 数据类型
Verilog初级教程(2)Verilog HDL的初级语法
Verilog初级教程(1)认识 Verilog HDL
芯片设计抽象层及其设计风格
Verilog以及VHDL所倡导的的代码准则
FPGA/ASIC初学者应该学习Verilog还是VHDL?
- 个人微信公众号: FPGA LAB
Verilog初级教程(12)Verilog中的generate块相关推荐
- Verilog初级教程(23)Verilog仿真中的显示任务
文章目录 前言 正文 Display/Write Tasks Verilog Strobes Verilog Continuous Monitors Verilog Format Specifiers ...
- Verilog初级教程(21)Verilog中的延迟控制语句
文章目录 前言 正文 延迟控制语句 事件控制语句 Named Events Event or operator 往期回顾 参考资料及推荐关注 前言 Verilog中的延迟控制有两种类型–延迟和事件表达 ...
- Verilog初级教程(20)Verilog中的`ifdef 条件编译语句
文章目录 前言 正文 语法 示例 Testbench文件 往期回顾 参考资料及推荐关注 前言 `ifdef条件编译语句在逻辑设计中还是很常见的,但也常见一些滥用的情况,这应该避免. 应该在什么情况下使 ...
- Verilog初级教程(15)Verilog中的阻塞与非阻塞语句
文章目录 前言 正文 阻塞赋值 非阻塞赋值 往期回顾 参考资料以及推荐关注 前言 本文通过仿真的方式,形象的说明阻塞赋值以及非阻塞赋值的区别,希望和其他教程相辅相成,共同辅助理解. 正文 阻塞赋值 阻 ...
- Verilog初级教程(14)Verilog中的赋值语句
文章目录 前言 正文 合理的左值 过程性赋值(Procedural assignment) 连续赋值 过程连续性赋值 往期回顾 前言 何为赋值语句?即将值放到线网或者变量上,这种操作称为赋值,英文:a ...
- Verilog初级教程(19)Verilog中的参数
文章目录 前言 正文 模块参数 覆盖参数 例子说明 递增计数器 递减计数器 Specify参数 模块参数与Specify参数的区别 往期回顾 参考资料及推荐关注 前言 Verilog中的参数是使得设计 ...
- Verilog初级教程(16)Verilog中的控制块
文章目录 前言 正文 条件语句if 语法 硬件实现 循环语句 forever repeat while for 往期回顾 参考资料及推荐关注 前言 硬件行为的实现离不开条件语句和其他控制逻辑流的方式. ...
- Verilog初级教程(11)Verilog中的initial块
文章目录 前言 正文 语法格式 initial块是用来干什么的? initial块何时开始又何时结束? 一个模块中允许有多少个initial块? 参考资料 写在最后 前言 仿真中通常会依次执行一组Ve ...
- Verilog初级教程(2)Verilog HDL的初级语法
文章目录 前言 正文 注释 空格 操作符 数字格式 字符串 标识符 关键字 verilog修订 写在最后 前言 学习Verilog和学习任何一门编程语言一样,都需要从语法开始,不会语法去学习设计是几乎 ...
最新文章
- C#二进制文件编程实践
- Java实现MD5加密和文件校验
- 2019年末逆向复习系列之努比亚Cookie生成逆向分析
- php for linux配置文件,linux配置php运行环境
- 【OpenGL从入门到精通(三)】第一个点的理论
- 尽快更新!Chrome 修复两个已遭在野利用的 0day
- JAVA 导出 Excel, JS 导出 Excel
- 让你页面速度飞起来的前端性能优化方案
- java 开关按钮_SwitchButton开关按钮的多种实现方式
- SQL server日志清理
- 续费Enom域名的三种办法
- 虚拟串口软件VSPD下载安装及使用 包含XCOM串口调试软件
- Android实现简单的计算器
- Unity中使用Post Processing 开自发光效果
- 京东第一位博士后出站 看看他研究的是什么“黑科技”
- 使用微信小程序拨打电话
- **在一个字符串中寻找另外一个字符串**
- 关于计算机领域的各种学习交流网站
- 用组策略统一域中所有客户端桌面
- sofa启动的默认加载参数
热门文章
- poj1730Pollard分解
- 深入理解Kinect for Windows开发
- 测试人员如何赢得开发人员的尊重
- 大学计算机专业和物理专业哪个难,大学里最难毕业的3大专业,尤其是最后一个...
- 深度优先遍历_二叉树的深度优先遍历,理解框架真的能够套用题目吗?不了解执行过程可能很难。...
- nodejs html转excel,Node.js excel sheetjs/js-xlsx
- 第十六届全国大学生智能车竞赛比赛获奖证书格式说明以及下载链接
- 2021年春季学期-信号与系统-第十一次作业参考答案-第八小题
- 克隆树莓Raspberry Pi Mode4 的TF卡
- java 默认字符集 iso_当服务器的默认字符集是UTF-8时,Perl并使用ISO-8859-1字符集...