原创 【博客大赛】小梅哥和你一起深入学习FPGA之Verilog HDL基础语法讲解之模块代码基本结构

2016-1-29 17:59 2165 19 11 分类: FPGA/CPLD 文集: FPGA深入学习

         小梅哥接触过不少的从0开始接触Verilog语法的朋友,他们对于语法的掌握基本趋近于0,对于使用Verilog描述一个逻辑模块的最基本结构都不清楚,因此这里小梅哥特地使用一个例子来介绍一下使用Verilog设计数字逻辑模块的一般结构。

         本章主要讲解Verilog基础语法的内容,文章以一个最简单的例子“二选一多路器”来引入一个最简单的Verilog设计文件的基本结构。

以下为本章中例子中的代码:

01  /*=======================================

02  *   file neme : mux2.v

03  *   author :   小梅哥

04  *   Verison    :   V1.0

05  *   date       :   2015年07月01日

06  *   description:

07  *          当sel为0时,将输入端口in_a上的数据通过out端口输出,

08  *      否则将输入端口in_b上的数据通过out端口输出

09  =======================================*/

10

11  module mux2(in_a,in_b,sel,out);

12

13     input [1:0]   in_a;  //输入端口in_a

14     input [1:0] in_b; //输入端口in_b

15    

16     input [0:0]   sel;   //通路选择线

17    

18     output [1:0] out; //输出端口out

19

20  /*--------------------------------------------  

21     当sel为0时,选择将in_a端口的数据通过out端口输出,

22     当sel为1时,选择将in_b端口的数据通过out端口输出.

23  --------------------------------------------*/  

24     assign out = (sel == 1'b0)? in_a : in_b;

25

26  endmodule

 

         (注:最左侧一列行号是作者为了讲解方便加上的,不属于代码内容,请知悉)

以上代码描述的电路如下图所示:

1.jpg

图:二选一多路器电路模型

 

第1到9行:

         该部分为文件头,记录了本设计文件中的一些基本信息如设计者、版本号、修改历史以及代码实现的功能描述。在编译时,该部分属于注释内容,将不被综合成任何内容。

 

第11行:module mux2(in_a,in_b,sel,out);

         该行第一个字符串“module”为Verilog中的一个保留字(关键词),该保留字的出现表明了一个模块内容的开始。相对应的,第26行的“endmodule”也是一个保留字,该保留字的出现表明了一个模块内容的结束。在Verilog语法中,module和encmodule总是成对出现,module和encmodule之间的内容则是用户代码。

         module之后是一个空格(或制表符“tab”),空格或制表符数量不一定限定为1个,也可以是多个,对结果没有任何影响。紧跟空格之后的mux2则是模块名称,该名称由用户自己定义,但一般要求与设计内容有一定关系,通过该名称能够体现出模块的功能或作用,例如这里使用mux2表明这是一个二选一多路器,让人一目了然。换个例子,如果要做PWM波生成模块,则可以直接以PWM作为模块名(module PWM(……);)这样简洁直观,一看就能理解模块的功能。

         mux2之后使用圆括号括起来的部分则是端口列表,该列表中列出了该模块所有需要外部输入或者需要输出到外部的信号,信号间以英文中的逗号“,”隔开。端口名的命名也尽量能够代表该端口信号的实际功能或意义,例如“in_a”,很清晰的就能告诉读者这是数据输入通道的a端口。

 

第13行到18行:

13       input [1:0]   in_a;  //输入端口in_a

14       input [1:0] in_b; //输入端口in_b

15      

16       input [0:0]   sel;   //通路选择线

17      

18       output [1:0] out; //输出端口out

         这里蓝色保留字“input”和“output”是端口类型,input表示该端口是本模块的输入型端口,output表示该端口是本模块的输出型端口。另外,在实际项目中,还有一种很常见的端口类型是双向端口,Verilog中用关键字“inout”来表示。在本例中,由于没有使用到双向端口,因此不做介绍,该部分内容将在后面以一个单独的章节来进行讲解。

         第13行紧跟着“input”之后用方括号括起来的部分[1:0]表示端口的宽度,这里表示输入端口in_a的位宽为2。需要注意的是,定义位宽时虽然写成[1:0][0:1]表示的位宽是一致的,但是Verilog中习惯使用[MSB:LSB]的形式,请大家在自己写代码时也统一遵照这一要求。当位宽为1时,位宽定义部分可以省略,例如第16行的[0:0]是可以省略的,即写成input sel;input [0:0] sel;效果是一样的。

 

第20行到23行:

         该部分为注释内容,注释主要是为了方便阅读和理解代码,在综合电路时会被忽略。Verilog语法中,注释的格式与C语言中一致,也支持单行注释和块注释。单行注释以“//”开始,有效作用域只在以此符号开始的本行紧随其后的内容,换行后就不起作用了。例如第13行的“//输入端口in_a”就是注释内容,换行后第14行就不再是被注释掉的内容了。第20行到第23行为块注释,块注释以“/*    */”组织,两个“*”之间的内容即为注释内容,此种注释方式支持换行,注释内容以“/*”开始,换行后注释属性依然有效,直到出现“*/”,则注释部分结束。不过需要注意的是,块注释不支持嵌套,当强行使用这种方式时会导致编译错误。例如以下这种格式就是错误的:

/* 

一级块注释内容

/* 

二级块注释内容

*/

……

*/

第24行:24     assign out = (sel == 1'b0)? in_a : in_b;

         这一行为赋值语句,这里是Verilog中最基础的一种赋值方式——连续赋值语句。这段代码的意义就是“判断括号中的条件是否成立,若成立,则将in_a的值赋给out,否则,则将in_b的值赋给out”,即通过这种方式实现了根据条件选择通道的功能。其中,“?”之后“:”之前的信号为括号中条件满足时需要赋给out的的源信号,“:”之后的信号则是括号中条件不满足时需要赋给out的源信号。此种赋值方式还支持多重选择,例如下面的代码:

assign out = (sel1 == 1'b0)? in_a : (sel2 == 1)? in_b : in_c;

 

         这里有三个数据输入端口“in_a , in_b , in_c”,两个选择输入端口“sel1 , sel2”。该句话的意思就是,当第一个括号中的条件满足时,则将in_a的数据赋值给out,否则再判断第二个括号中的条件是否满足,满足则将in_b的值赋给out,不满足则将in_c的值赋给out。括号中的内容可以直接简写为(!sel1)或者(!sel2),这一点与C语言一样。

 

         通过这一章,我们学习了采用Verilog HDL设计简单的模块的基本代码结构,包括声明模块的”module   endmodule”、端口的定义、端口类型以及位宽的声明、注释内容的格式以及连续赋值语句的写法,而且通过此例子完成了一个简单的二选一多路器的设计。希望对于Verilog HDL语法零基础的读者在看罢此文后能够关闭此文档,在Quartus II或Modelsim、ISE等工具中实际动手敲一遍。可结合前面介绍Altera 公司FPGA器件开发流程一章中的步骤,实际建立工程并输入代码,然后分析和综合,通过综合工具,查看自己编写的代码是否有错误,如有错误,则根据软件提示加以改正。

         下一章,将以此模块的测试文件(testbench)为例,介绍Testbench的基本语法。

 

 如有更多问题,欢迎留言,也可加入技术支持群一起交流学习。群号:472607506

 

小梅哥

芯航线电子工作室

 

 

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户1465088 2016-2-2 21:37

不错,简单实用,解释得很详细!

用户1768597 2014-8-8 22:57

tiny6410 程序运行起来点击屏幕时会死机,有时会重启,按下按键时会产生下降沿中断,然后死机(就是卡住)。请大家帮忙看看是怎么回事?使用中断还需要设置其他么?
相关推荐阅读
小梅哥 2019-09-04 22:10
小梅哥FPGA时序分析笔记(6.2)深入现象看本质——庖丁解牛之FPGA内数据传输模型
通过上一节,我们了解了FPGA内部数据的传输形式,接下来我们就可以根据上一节的内容来总结一下FPGA内部的数据传输模型了。 时钟和数据传输路径 通过上一节内容中,我绘制的那个FPGA内部数据在逻辑...
小梅哥 2019-09-01 21:28
小梅哥FPGA时序分析笔记(6.1)深入现象看本质——庖丁解牛之FPGA可编程原理
上一次发博客,已经是2个月前了,这中间两个月,干了件很有意义的事情,尤其是对于自己来说,感觉学到了非常多的知识和经验,每天都很忙,忙到没时间逛网站博客,终于忙完闲下来了,连载的事情可不能忘,终于可以书...
小梅哥 2019-07-02 08:57
小梅哥FPGA时序分析笔记(五)I/O约束显神威——深入龙潭
大家一定对我上一节的突然结尾表示一脸茫然:我是来学习时序约束的,然后你告诉我时序约束里面IO约束很重要,然我又跟着你的文章继续往下看,本以为你就要讲如何进行IO约束了,结果呢,你一个取反时钟就把我们打...
小梅哥 2019-06-30 11:07
小梅哥FPGA时序分析笔记(四)I/O时序定成败——化险为夷
小梅哥FPGA时序分析从遥望到领悟系列没有遇见过I/O时序问题,没有通过I/O约束方式实际解决过I/O时序问题,就很难明白I/O约束的重要性,也很难相信各种EDA软件真的有那么的傻白甜。 我遇到的最...
小梅哥 2019-06-22 10:32
小梅哥FPGA时序分析笔记(三)时钟约束真重要——事实说话
小梅哥FPGA时序分析从遥望到领悟系列以前,那是在以前,经常有网友(原谅我行文动不动就是网友说,网友问,毕竟我是卖开发板的,正面接触学FPGA的网友相对多一些,所以这些也都是事实存在的事情)问我:小梅...
小梅哥 2019-06-21 10:33
小梅哥FPGA时序分析笔记(二)时钟质量是生命——初遇时序
小梅哥FPGA时序分析从遥望到领悟系列第一次遇到时序问题并通过相应的手段解决问题,算是2年前做百兆以太网图像传输的时候了吧。当时遇到的问题为:同一个工程,每次编译结果的效果都不一样,有的时候编译了,下...
EE直播间
更多
我要评论
1
19
关闭 站长推荐上一条 /3 下一条