本文记录一些关于Verilog HDL的一些技巧、易错、易忘点等(主要是语法上),一方面是方便自己忘记语法时进行查阅翻看,另一方面是分享给大家,如果有错的话,希望大家能够评论指出。

关键词:

  ·技巧篇:

      组合逻辑输出类型选择;

      语法上的变量交换;

  ·易忘篇:

      case/casex/casez语句;

      循环语句;

      数制和操作符;

      数据类型;

  ·易错:

      数据的截位与扩位

      子模块例化中隐式线网赋值

技巧篇:

  1、组合逻辑输出:描述一个纯组合逻辑电路时,尽量不要把输出定义成输出类型,例如描述下面的电路:

 module mux #(parameter N=)(

 input [N-:] a, // sel=00时,选择该输入

 input [N-:] b, // sel=01时,选择该输入

 input [N-:] c, // sel=10时,选择该输入

 input [N-:] d, // sel=11时,选择该输入

 input [:] sel, //选择器

 output[N-:] mux_out);// 选择器结果输出

 reg [N-:] mux_temp; // 临时变量,用于防止其他调用者误认为输出锁存

 assign mux_out=mux_temp;

 //always_comb //该语句在systemverilog中可以替换下面的语句并检查

 always @ (a or b or c or d or sel)

   case (sel)

      : mux_temp = a;

      : mux_temp = b;

      : mux_temp = c;

      : mux_temp = d;
  
    default : $display("Error with sel signal");   endcase endmodule

  2、语法上的变量交换:在always 语句块内部,任何一个语句块(以begin 开始,end 结束)都是串行执行的,只是存在赋值立刻生效还是事后生效的差异,即后面将要重点论述的阻塞赋值和非阻塞赋值两种区别(这两种赋值语句综合的区别请看我的另一篇博文,链接为:

        http://www.cnblogs.com/IClearner/p/7188875.html)。

对于下面的代码,从纯语法上讲:

 always@(*)begin

     temp=b;

     b=a;

     a=temp;

 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 = )(
input wire [size-:] opa, opb,
output reg [*size-:] mult_out
);
reg[*size-:] result;
integer bindex;
always @(*)begin
result = opb[]?opa:;
for( bindex=; bindex<=size-; bindex=bindex+ )begin//根据乘法特性,判断后是否进行移位
if(opb[bindex]) result = result + (opa<<(bindex));
end
mult_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 单元库,否则将识别为寄存器堆。上例的RegFile1RegFile2 对象在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中

  ①加法实现规范,扩展符号位后相加。

   reg[:] Adder_Out;
  reg[:] Adder_In1,Adder_In2;
  Adder_Out <= {Adder_In1[],Adder_In1} + {Adder_In2[],Adder_In2};

  ②对于截取乘法的结果,需要加溢出保护的截取规范。例如要截取12 比特输出的第6 位到第2 位,其实现代码为:

 if((addRakeOut[:] == ) || (addRakeOut[:] == ))
tmptraffic <= addRakeOut[:];
else
tmptraffic <= (addRakeOut[] == ) ? : ;

或者:

 if((addRakeOut[:] == 'b000000) || (addRakeOut[11:6] == 6'b111111))
tmptraffic <= addRakeOut[:];
else
tmptraffic <= (addRakeOut[] == ) ? ’b10000 : ’sb01111;

  ③移位操作规范,移位操作的截位和加法器的截位规则类似,如16 比特数据的左、右1 比特移位示例:

 reg[:] Data;
if((Data[:] == 'b00) || (Data[15:14] == 2'b11))
Data <= {Data[:],'b0};//左移一位
else
Data <= (Data[]) ? 'b1000_0000_0000_0000 : 16'b0111_1111_1111_1111;
//右移一位
Data <= {Data[],Data[:]};

 2、子模块例化中隐式线网赋值时

  子模块例化时,要用线网类型的变量  连接  被调用的子模块端口信号  和主模块的 信号,当这个线网变量没有在主模块中声明时,该线网变量的位宽有以下情况:

  ①如果该线网变量是用于连接 主模块的端口信号 和  被调用的子模块的端口信号,那么该线网变量的位宽 跟 主模块端口的位宽相同。

  ②如果该线网变量只在主模块里起连接作用(如连接两个 被调用的子模块),该线网位宽默认为1位。

  ③Verilog判断隐式线网变量的位宽从顶层环境开始,也就是判断隐式线网的位宽并不参看被调用的子模块端口的位宽。

关于Verilog HDL的一些技巧、易错、易忘点(不定期更新)的更多相关文章

  1. 易错java知识点总结(持续更新)

    1. 2.java转义字符的理解 参考知乎大神:http://www.zhihu.com/question/29232624 正向和逆向处理转义字符 正向:把两个字符 \ n 识别为一个转义字符 ne ...

  2. C++笔试易错题集(持续更新)

    1.如下代码输出结果是什么? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include<stdio.h> char *myString() {     ...

  3. Django框架学习易错和易忘点

    一.get在几处的用法 1.获取前端数据 request.POST.get('xxx') #当存在多个值时,默认取列表最后一个元素:所以当存在多个值时,使用getlist 2.获取数据库数据 mode ...

  4. 自己动手写处理器之第二阶段(2)——Verilog HDL简单介绍

    将陆续上传本人写的新书<自己动手写处理器>(尚未出版),今天是第六篇.我尽量每周四篇 2.3 Verilog HDL简单介绍 本书实现的OpenMIPS处理器是使用Verilog HDL编 ...

  5. Verilog HDL的程序结构及其描述

    这篇博文是写给要入门Verilog HDL及其初学者的,也算是我对Verilog  HDL学习的一个总结,主要是Verilog HDL的程序结构及其描述,如果有错,欢迎评论指出. 一.Verilog ...

  6. 浅谈Verilog HDL代码编写风格

    消失了好久,没有写文章,也没有做笔记,因为最近再赶一个比赛,时间很紧,昨天周六终于结束了,所以趁着周末这会儿有时间,写点东西,记录下来.首先我学习FPGA才一年多,我知道自己没有资格谈论一些比较深层次 ...

  7. verilog HDL -模块代码基本结构

    1--verilog HDL 语言的预编译指令作用:指示在编译verliog HDL源代码前,需要执行哪些操作. 2--模块内容是嵌在module 和endmodule两个语句之间.每个模块实现特定的 ...

  8. Verilog HDL 使用规范(一)

    本博文参考:<大规模逻辑设计指导书>,对于写出规范的代码,培养良好的代码风格颇有裨益. wire and register 一个reg变量只能在一个always语句中赋值: 这个说明至关重 ...

  9. Sublime Text 2 和 Verilog HDL

    Sublime Text 2 和 Verilog HDL Date  Fri 04 July 2014 Tags Sublime Text / Vivado Sublime Text 代码编辑器之于程 ...

随机推荐

  1. 防火墙上开放Oracle服务端口1521的方法

    近来由于工作需要,在Windows XP平台上安装了Oracle9i数据库作为测试之用,一切正常.但当客户机连接服务器时却总是超时,我首先想到了防火墙,当我打开1521端口时,连接操作仍然失败.我又怀 ...

  2. C#码农的大数据之路 - 使用C#编写MR作业

    系列目录 写在前面 从Hadoop出现至今,大数据几乎就是Java平台专属一般.虽然Hadoop或Spark也提供了接口可以与其他语言一起使用,但作为基于JVM运行的框架,Java系语言有着天生优势. ...

  3. 每天一个Linux命令—— crontab

    一.简介 1. Linux中有许多周期性执行的任务,这些任务由cron守护进程完成,因此cron这个系统服务是默认启动的. 2.Linux中调度任务分为两类:系统任务调度和用户任务调度,系统任务调度即 ...

  4. Android高效内存1:一张图片占用多少内存

    在做内存优化的时候,我们发现除了解决内存泄露问题,剩下的就只有想办法减少真实的内存占用.而在App中,大部分内存可能被我们图片占用了,所以减少图片的内存占用可以带来直接的效果.本文就简单介绍一张图片到 ...

  5. MySql俩种分页区别(注意)

    注意俩个分页的区别哦~ SELECT * FROM city LIMIT 2 OFFSET 1; 从第二条记录开始 取二条记录 如下: SELECT * FROM city LIMIT 3,2; 从第 ...

  6. 9.并发包非阻塞队列ConcurrentLinkedQueue

    jdk1.7.0_79  队列是一种非常常用的数据结构,一进一出,先进先出. 在Java并发包中提供了两种类型的队列,非阻塞队列与阻塞队列,当然它们都是线程安全的,无需担心在多线程并发环境所带来的不可 ...

  7. iOS gcd 串行,并行,同步,异步代码研究

    参考文章: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #527eff } span.s1 { } http: ...

  8. 同是办公软件,wps和office有什么区别?

    今天完美小编为大家带来的是wps和office有什么区别教程,那么到底有什么区别呢?相信很多朋友都模棱两可,说不出所以然,看看下面的教程,相信你会选择更适合你的那一款软件.一起来看看吧! 1.两者特点 ...

  9. 快速压缩PNG文件在线工具

    https://tinypng.com/ 直接拖移要压缩文件即可

  10. HttpClient+Jsoup 抓取网页信息(网易贵金属为例)

    废话不多说直接讲讲今天要做的事. 利用HttpClient和Jsoup技术抓取网页信息.HttpClient是支持HTTP协议的客户端编程工具包,并且它支持HTTP协议. jsoup 是一款基于 Ja ...