关于Verilog HDL的一些技巧、易错、易忘点(不定期更新)
本文记录一些关于Verilog HDL的一些技巧、易错、易忘点等(主要是语法上),一方面是方便自己忘记语法时进行查阅翻看,另一方面是分享给大家,如果有错的话,希望大家能够评论指出。
关键词:
·技巧篇:
组合逻辑输出类型选择;
语法上的变量交换;
·易忘篇:
case/casex/casez语句;
循环语句;
数制和操作符;
数据类型;
·易错:
数据的截位与扩位
子模块例化中隐式线网赋值
技巧篇:
1、组合逻辑输出:描述一个纯组合逻辑电路时,尽量不要把输出定义成输出类型,例如描述下面的电路:
1 module mux #(parameter N=2)( 2 3 input [N-1:0] a, // sel=00时,选择该输入 4 5 input [N-1:0] b, // sel=01时,选择该输入 6 7 input [N-1:0] c, // sel=10时,选择该输入 8 9 input [N-1:0] d, // sel=11时,选择该输入 10 11 input [1:0] sel, //选择器 12 13 output[N-1:0] mux_out);// 选择器结果输出 14 15 reg [N-1:0] mux_temp; // 临时变量,用于防止其他调用者误认为输出锁存 16 17 assign mux_out=mux_temp; 18 19 //always_comb //该语句在systemverilog中可以替换下面的语句并检查 20 21 always @ (a or b or c or d or sel) 22 23 case (sel) 24 25 0 : mux_temp = a; 26 27 1 : mux_temp = b; 28 29 2 : mux_temp = c; 30 31 3 : mux_temp = d; 32 33 default : $display("Error with sel signal"); 34 35 endcase 36 37 endmodule
2、语法上的变量交换:在always 语句块内部,任何一个语句块(以begin 开始,end 结束)都是串行执行的,只是存在赋值立刻生效还是事后生效的差异,即后面将要重点论述的阻塞赋值和非阻塞赋值两种区别(这两种赋值语句综合的区别请看我的另一篇博文,链接为:
http://www.cnblogs.com/IClearner/p/7188875.html)。
对于下面的代码,从纯语法上讲:
1 always@(*)begin 2 3 temp=b; 4 5 b=a; 6 7 a=temp; 8 9 end
上面的例子,就是一个串行执行的例子,能够完成 a 与 b 的数值交换,如果不是串行执行,上述代码将很难完成类似各类程序控制。
易忘篇/陌生篇:
1、case语句的各种注意情况及对应综合电路
(留坑,以后填)
2、循环语句:循环语句,主要包含 for、while、forever、repeat 四类语句,但只有 for 语句才有可能具备可综合性,其余均为测试验证所准备。
循环语句 for 的语法为:
for(表达式 1;表达式 2;表达式 3) 语句
其实可以将 for 语句理解为:
for(循环变量赋初值;循环结束条件;循环变量增值)执行语句
·for 循环的例子如下,这是最原始的一个8bit 乘法器实现,其中<<表示左移,等效于乘以2 的移位次方:
module mac_8 #(parameter size = 8)(input wire [size-1:0] opa, opb,output reg [2*size-1:0] mult_out); reg[2*size-1:0] result; integer bindex; always @(*)beginresult = opb[0]?opa:0;for( bindex=1; bindex<=size-1; bindex=bindex+1 )begin//根据乘法特性,判断后是否进行移位if(opb[bindex]) result = result + (opa<<(bindex));endmult_out = result; end endmodule
仿真波形如下所示:
(上述例子也可以当做技巧看,也就是使用位移实现乘法运算)
3、数制与操作符
这里数制和操作符...其实我已经基本是滚瓜烂熟了,放在这里是给初学者查询的...
上面那个图是我在word写的,在Verilog中,一般一个整数我们称呼为 xx位xx进制数。数的位数和符号数的易忘点,图已经说明了。
通常有时候,一些初学者往往不知道位数与值之间的关系,我当初也不知道,现在我来给自己备忘一下:
3'b101:3位的二进制数101,(在我们的惯用的数制:10进制)数值大小为5;
3'd6:3位的10进制数6,等效于3'b110;数制大小为6;
3'd9:由于只有3位,十进制数9的数值为4位:4‘b1001;所以3‘d9的数值高位被阶段,3'd9表示真实的数值为3’d1或者3‘b001,数值大小为1
用例 |
说明 |
'hAE |
8 位十六进制数 |
10'b10 |
左边添 0 占位,实际为 10'b0000000010 |
10'bx1x0 |
左边添 x 占位,实际为 10'bxxxxxxx1x0 |
3'b1001_0011 |
3'b011 相等 |
运算类别 |
符号 |
运算符含义 |
||
算术运算符 |
+ |
加法(二元运算符) |
||
- |
减法(二元运算符) |
|||
* |
乘法(二元运算符) |
|||
/ |
除法(二元运算符) |
|||
% |
取模(二元运算符) |
|||
关系运算符 |
> |
大于 |
||
< |
小于 |
|||
>= |
不小于 |
|||
<= |
不大于 |
|||
== |
逻辑相等 |
|||
!= |
逻辑不等 |
|||
逻辑运算符 |
&& |
逻辑与 |
||
|| |
逻辑或 |
|||
! |
逻辑非 |
|||
按位逻辑运算符 |
~ |
一元非,相当于非门运算 |
||
& |
二元与,相当于与门运算 |
|||
| |
二元或,相当于或门运算 |
|||
^ |
二元异或,相当于异或门运算 |
|||
~^,^~ |
二元异或非即同或,相当于同或门运算 |
|||
移位运算符 |
>> |
右移 |
||
<< |
左移 |
|||
赋值运算符 |
= |
阻塞赋值,等效于立即生效 |
||
<= |
非阻塞赋值,等效于当前模块结束后赋值,或者下个时钟 周期赋值生效 |
|||
缩减运算符 |
& |
一元与,相当于数据 bit 逐个进行与操作 |
||
| |
一元或,相当于数据 bit 逐个进行或操作 |
|||
^ |
一元异或,相当于数据 bit 逐个进行异或操作 |
|||
~^ |
一元同或,相当于数据 bit 逐个进行同或操作 |
单元运算符:可以带一个操作数,操作数放在运算符的右边。
二元运算符:可以带二个操作数,操作数放在运算符的两边。
三元运算符:可以带三个操作数,这三个数用三目运算符分隔开。
缩减运算符是对单个操作数进行或与非递推运算,最后的运算结果是一位的二进制数。缩减运算符目前支持或与非三种操作。具体运算过程如下:第一步先将操作数的第一位与第二位进行或与非运算,第二步将运算结果与第三位进行或与非运算,依次类推,直至最后一位。
拼接运算符则与缩减运算符相反,主要目的是将两个或多个信号的某些位拼接起来进行运算操作。拼接运算不消耗任何逻辑资源,只是一个单纯的连线逻辑。其使用方法如下:
{信号1的某几位,信号2的某几位,..,..,信号n的某几位}
即把某些信号的某些位详细地列出来,中间用逗号分开,最后用大括号括起来表示一个整体信号。例如:
{a,b[3:0],c,3'b101}
也可以写成如下形式:
{a,b[3],b[2],b[1],b[0],c,1'b1,1'b0,1'b1}
在位拼接表达式中不允许存在没有指明位数的信号。这是因为在计算拼接信号的位宽的大小时必需知道其中每个信号的位宽。位拼接还可以用重复法来简化表达式,例如:
{6{a}}//这等同于{a,a,a,a,a,a,a},a可为任意比特位宽
位拼接还可以用嵌套的方式来表达,例如:
{c,{3{a,b}}}//这等同于{c,a,b,a,b,a,b}
用于表示重复的表达式如上例中的6 和3,必须是常数表达式或者参数。
4、数据类型:
·当一个wire 类型的信号没有被驱动时,缺省值为Z(高阻)。
·有一种专门针对存储器模型(RAM)的定义方法,例如:
(* ramstyle ="MLAB"*)reg[31:0] RegFile1[15:0];
(* ramstyle ="MLAB"*)reg[31:0] RegFile2[15:0];
在ASIC 设计中,这种描述方式只会被识别为一系列的寄存器堆,并不会被识别为RAM;ASIC 中应当利用RAM 单元库(IP)例化的方法描述RAM。而在FPGA 中,综合器首先将这种描述识别为RAM 的声明,并通过识别对象的行为确认描述对象是RAM 还是寄存器堆。如果后续的描述行为满足RAM 的特征,就自动替换为FPGA 内部内置的RAM 单元库,否则将识别为寄存器堆。上例的RegFile1 与RegFile2 对象在Altera FPGA 中,将被识别为16 个32bit 位宽的RAM,而且指定为MLAB 类型。
易错篇
1、数据的截位与扩位
(1)扩位操作
位宽扩展:如果所规定的位宽太小,那个将会截断高的几个位(如2’b1101,将变成2'b01),如果指定的位宽太大,则会用0或者x/z来向左扩展数值,但不会扩展符号位。
对于有符号数:如果位宽位宽小于数值规定,符号位可能被截断(如数-4‘sd15,即1111_0001,将会被截断,代表的值为+1,即0001);
如果位宽大于数值规定,都是用0来扩充,因此负数可能被扩充为正数。
①在定点计算中,经过加法和乘法运算后,输出结果的位宽会增加。但如果继续使用和输入操作数同等位宽的数来表示结果,就会丢失有用的比特信息,造成输出结果错误。
②例如,在有限字长的情况下,若两个M 位的数相加,其结果最高可能为M +1位;若两个M 位的数相乘,其结果最多可为2M 位。
③4 比特加法运算中的扩位现象:
有符号数):
4'b0101 和4'b0111 分别对应着+5 和+7,二者相加后本应为+12,即5'b01100。但由于位宽限制,如不扩位,只能保留低4 位,即4'b1100,对应着-4,造成严重的计算错误。类似的错误还会造成负数相加变成正数。
无符号数):
4'b1111 + 4'b1111 = 5'11110 ,但是由于加数是4 位,在Verilog语言中只保留低4 位,就会得到4'b1111 + 4'b1111 = 4'1110 的结果,这样就会造成计算错误。
注意:
①无论是有符号数还是无符号数,高位宽的变量(或者数)赋值给低位宽的变量(或者数),低位宽将只能接收到高位宽数的的低位数值。
②低位宽赋值给高位宽时,有:无符号数/变量 给 无符号数/变量,符号数/变量 给 符号数/变量,这两个都不会出错;
无符号数/变量 给 符号数/变量,符号数/变量 给 无符号数/变量 时将出现错误。
(2)截位操作
①在有限字长的情况下,若两个M 位的数相加,其结果就是M +1位;若两个M 位的数相乘,其结果就是2M 位。但在实际的操作过程中,考虑到资源的问题,不能任由相加、相乘操作来增加操作数的位宽,必须进行截断。
②例如,两个16 位数相乘后,其结果为32 位,如再和一个16 位数相乘,结果就变为48 位,这样下去,用不了几个乘法操作就会使操作数的位宽剧增,所占用的硬件资源也会很多。因此,需要将乘积结果进行截位,寄存在M 位的寄存器中。
(3)截位与扩位规范(Verilog中)
①加法实现规范,扩展符号位后相加。
1 reg[12:0] Adder_Out; 2 reg[11:0] Adder_In1,Adder_In2; 3 Adder_Out <= {Adder_In1[11],Adder_In1} + {Adder_In2[11],Adder_In2};
②对于截取乘法的结果,需要加溢出保护的截取规范。例如要截取12 比特输出的第6 位到第2 位,其实现代码为:
1 if((addRakeOut[11:6] == 0) || (addRakeOut[11:6] == 63)) 2 tmptraffic <= addRakeOut[6:2]; 3 else 4 tmptraffic <= (addRakeOut[11] == 1) ? 16 : 15;
或者:
1 if((addRakeOut[11:6] == 6'b000000) || (addRakeOut[11:6] == 6'b111111)) 2 tmptraffic <= addRakeOut[6:2]; 3 else 4 tmptraffic <= (addRakeOut[11] == 1) ? 5’b10000 : 5’sb01111;
③移位操作规范,移位操作的截位和加法器的截位规则类似,如16 比特数据的左、右1 比特移位示例:
1 reg[15:0] Data; 2 if((Data[15:14] == 2'b00) || (Data[15:14] == 2'b11)) 3 Data <= {Data[14:0],1'b0};//左移一位 4 else 5 Data <= (Data[15]) ? 16'b1000_0000_0000_0000 : 16'b0111_1111_1111_1111; 6 //右移一位 7 Data <= {Data[15],Data[15:1]};
2、子模块例化中隐式线网赋值时
子模块例化时,要用线网类型的变量 连接 被调用的子模块端口信号 和主模块的 信号,当这个线网变量没有在主模块中声明时,该线网变量的位宽有以下情况:
①如果该线网变量是用于连接 主模块的端口信号 和 被调用的子模块的端口信号,那么该线网变量的位宽 跟 主模块端口的位宽相同。
②如果该线网变量只在主模块里起连接作用(如连接两个 被调用的子模块),该线网位宽默认为1位。
③Verilog判断隐式线网变量的位宽从顶层环境开始,也就是判断隐式线网的位宽并不参看被调用的子模块端口的位宽。
转载于:https://www.cnblogs.com/IClearner/p/7203887.html
关于Verilog HDL的一些技巧、易错、易忘点(不定期更新)相关推荐
- 计算机信息处理技术的基础知识列举出一些易错易混淆知识点,计算机考证实训报告指导书.doc...
计算机考证实训报告指导书 实训目的: 掌握计算机信息处理与应用的基础知识,掌握以Windows XP和Microsoft Office 2003为工作平台,应用计算机高效率.高质量地进行信息处理的基本 ...
- Linux - 易错知识点整理(待更新)
Linux - 易错知识点整理(待更新) 本文根据CSDN Linux进阶技能树整理的易错知识点(带练),参考资料Linux常用命令大全(非常全!!!),Linux面试题(2020最新版)(带问/练) ...
- Java进阶3 - 易错知识点整理(待更新)
Java进阶3 - 易错知识点整理(待更新) 该章节是Java进阶2- 易错知识点整理的续篇: 在前一章节中介绍了 ORM框架,中间件相关的面试题,而在该章节中主要记录关于项目部署中间件,监控与性能优 ...
- 三本类计算机行色专业,高考倒计时50天:物理34个易错易忘知识点
今天是4月18日,距离2016年高考(微博)还有50天. 今天的内容有四部分:第一部分:高招小贴士:第二部分:2016年高校招生政策,今天介绍天津大学(微博)2016年的招生政策:第三部分:高考志愿填 ...
- MySQL初阶 - 易错知识点整理(待更新)
MySQL初阶 - 易错知识点整理(待更新) Note:这里根据 CSDN Mysql技能树 整理的易错题,可参考MySQL 有这一篇就够,MySQL详细学习教程(建议收藏),MySQL 菜鸟教程 文 ...
- 关于Verilog HDL的一些技巧、易错、易忘点
关键词: ·技巧篇: 组合逻辑输出类型选择; 语法上的变量交换; ·易忘篇: case/casex/casez语句; 循环语句: 数制和操作符: 数据类型: ·易错: 数据的截位与扩位 子模块例化中隐 ...
- Verilog hdl 宏定义编译报错
1.今天使用quartus 9.1 编译文本文件使用宏定义时编译器报错,不使用则正确.原因不明. 如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ...
- java打印等腰三角形_可打印丨四年级数学易错易失分的26个知识点总结(附例题+答案),给孩子收藏!...
朗读君提醒 点击图片跳转至小程序 即可[下载打印] ▼ 1. 列式计算时,一定要注意除和除以的区别:a除以b或a被b除列式为:a÷b,a除b,或用a去除b,列式为:b÷a2. 边长为4cm的正方形,半 ...
- 计算机二级考试C语言选择题知识点总结,易错点总结(持续更新)
最近要考计算机二级c语言,是因为自我感觉 自己的编程能力实在是太差了,课堂上有没有好好的学,所以简单抽时间看看二级的题库,做一些经常出错的知识点的总结!有错的希望大家能够提出来,谢谢大家了! 但是知识 ...
最新文章
- 减少该死的 if else 嵌套
- sap gateway development mode
- 【渝粤题库】国家开放大学2021春1542投资学题目
- imagex使用方法_Microsoft OneDrive 的使用心得,真香
- 信息学奥赛C++语言:某年某月天数
- Visual C++ 2008入门经典 第二十一章更新数据源
- 微信技术总监周颢:一亿用户背后的架构秘密
- 用xml模块方式导出多种offcie文件
- signature=c9b7b92b79e9a32ac6be9993bfe5df5a,这字幕= =太销魂了
- 实验过程中收获的经验、教训、感想
- 计算机小学生二年级知识,小学二年级语文知识点之拼音技巧
- VS 由于找不到ucrtbased.dll,无法继续执行代码。
- input发送a.jax_Java EE 7和JAX-RS 2.0
- 在计算机中 IDF MDF是什么意思?
- 【认知】什么规律或观念使人与人赚的钱产生了巨大差别?
- 什么是特斯拉?他和爱迪生相爱相杀。
- CentOS7安装EDA软件的若干问题解决
- 孕妇各个时期阶段营养食谱(分10个月)
- 极光大数据:2017年Q2 app榜单
- Xavier红外相机(IP摄像头)开发记录