Verilog HDL的程序结构及其描述

摘要:
主要是Verilog HDL的程序结构和描述。让我们看看Verilog HDL的程序结构来描述数字电路。让我们首先描述一些所需的Verilog HDL程序。输入端口只能是网络类型。如果未写入数据类型,则默认为导线类型。结构化描述是一点一点地实例化(子模块、单个门)以实现系统/设计功能。也就是说,一些verilog行为语句用于实现设计需求/功能。

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

一、Verilog HDL的程序结构

  首先我们不开始讲Verilog HDL的语法,我们从Verilog HDL的程序结构出发。相信大家都看过芯片吧,它有个名字,有个外壳,外壳向外伸出有引脚(BGA封装的那种请不要乱搅和...),然后芯片它可以实现一定的功能。

  Ok,知道这些之后,我们就来看看Verilog HDL的描述数字电路的程序结构吧。

在解释结构的时候,我拿芯片设计这个例子来打一个不恰当的比方。

Verilog HDL的程序结构及其描述第1张Verilog HDL的程序结构及其描述第2张

VerilogHDL程序的大致结构就是这么一个形式,每一个模块的结构都是一致的只不过语句之间存在一些差别,每一部分的具体描述将在后面进行。

 

二、verilog程序结构的简单描述

  OK,现在让我们现在开始了解一下一些语法和注意事项(注意,我这里不会把语法讲得很细很细,我主要是描述一些(我,或者初学者)易忘的,关键的语法和知识点),描述的顺序不一定按照上面的各个部分哟,我们先描述一些VerilogHDL程序必须的。

首先是模块说明

  module  和 endmodule ,这两个关键词成对出现,一般的内容都会囊括在这两个两个关键词之间。一个verilog(.v)文件可以有多个module ...endmodule,但是为了方便管理,建议只实现一个。

  此外无论是能够综合成电路的verilog程序还是只是仿真的程序,都需要以模块的形式给出。

 

模块名:

  ①模块名的定义要符合标识符的定义,至于什么是标识符,以后会说的。此外也要注意书写的规范性。

 

端口说明:

  ①端口可以比方成芯片的输入输入管脚,它只有三种类型:输入,输出,双向;

  ②端口有一些附加属性,如数据类型、符号特性、位宽等;input端口只能是线网类型,output可以是寄存器类型也可以是线网类型,inout也只能是线网类型。至于线网类型和寄存器类型,在以后的数据类型中会介绍。

  ③当端口是总线类型时,可以简单地理解为端口有多位时,对应于同时描述芯片的多个管脚时,可以给端口加上位宽。即input wire  [M:N]  a;如果M>N,则为降序,a[M]为最高位,位宽为M-N+1位;如果M<N,则最高位位a[N]位,位宽位N-M+1位;

  ④端口的属性声明顺序可以是:

    端口的输入输出   数据类型   有无符号   位宽   端口名称 ;

    如:output  reg  signed  [7:0] a;

  注:数据类型没有写则默认为wire 型,有无符号没有写默认为无符号型;位宽没有写默认为1bit 。

  ⑤当书写完端口声明是,括号后面的‘;’千万不要忘记。

 

程序主体:

  ①前面我们提及到verilog的描述层次中有一个结构化描述,结构化的描述就是一点一点地例化(子模块、单元门)来实现系统/设计的功能。程序的主体可以是只例化一些门单元,但是verilog的这种纯结构化方式的显然是无法满足现代设计要求的,因此纯结构化方式已经被遗弃。

  ②程序的主体可以是行为描述,也就是通过一些verilog的行为语句来实现设计的要求/功能。行为描述主要有:控制流描述,过程描述,块语句,时序控制等。对于行为描述,有可综合的,有不可综合的,可综合的行为描述语句/语法就可以认为是RTL级描述时用到的,而不可综合的行为描述语句/语法可以认为是仿真/建模时用到的。

  ③下面大概说一下行为描述情况,也就是行为描述中无论是可综合还是不可综合都可以使用的情况,具体的可综合和不可综合的行为级描述语法在后面会描述。

控制流描述:以assign关键字开头的语句描述称为控制流描述,主要用来实现一些简单的组合逻辑。

块语句:包含在关键字begin...end 、fork ...join之间的语句称为块语句。

过程描述:由initial模块、always模块、function模块、task模块这四个模块实现的过程。

时序控制:延时控制、敏感信号控制语句等

  ④块语句可以有一个名字,写在begin/fork后面(如beign:adder_disc ),给它一个名字有什么好处呢?好处有两个,一个是可以在块内部定义寄存器变量(注意哦,只能寄存器变量,这个寄存器变量在块内部使用),另外一个就是可以用disable这个关键字来中断语句块的执行(具体怎么弄,请参看其他书籍,这里不详述)

  ⑤begin...end内的语句是串行的,这是从语法的结果上讲的,但是它是可以综合的,综合出来的实际电路是并行的,也就是实际电路中,各条语句之间并不全是串行的,这里需要建立一个概念,方便讲解以后的阻塞赋值和非阻塞赋值。而fork...join 内的语句是同时进行的,然而这是不可综合的。

  ⑥一个程序的主体中可以有多个initial模块、always模块、function模块、task模块。Function模块和task模块以后介绍。多个Initial模块、always模块之间是并行的,但是initial只执行一次,而always是反复执行。

  initial一般是不可综合的,用在仿真当中;在进行仿真时,通常被用来描述测试模块的初始化、监视、波形生成等功能。

  always用在可综合的描述当中,一般情况下由敏感列表触发(至于什么是敏感列表,敏感列表怎么用,请参考其他书籍,我后面也会做一些记载),也就是用在描述RTL级的描述当中,通常被用来对硬件的功能进行描述,可以实现组合逻辑和实现逻辑的功能。

  上面没有给出initial格式和always格式只是提了一下简单应用。

  ⑦程序的主体大多可以由结构描述和行为描述构成

 

 

模块的例化:

  ①模块的例化主要是为实现总体的功能,比如说我要设计一块芯片,这个芯片的某个功能可以有某个芯片来完成,那我就可以调用这个芯片,例化就是调用这么一个概念。

  ②例化可以使用位置映射,也可使用名称映射,由于位置映射可读性太差,容易出错,所有建议使用名称映射。下面是名称映射的格式:

被调用(例化)的模块名字     自定义的例化模块名(
  .被调用(例化)模块的端口名     (本模块中的线网变量名),
  ...

  .被调用(例化)模块的端口名     (本模块中的线网变量名)
);

  ③悬空处理:

  在模块例化时,如果被例化的模块输入管脚悬空,则该输入为高阻Z,相当于与外界隔绝,但是实际电路中...

  如果将输出管脚悬空,则该输出管脚将被废弃掉。

  ④不同端口位宽处理

  当模块例化端口和被例化的端口位宽不同时,端口通过无符号数的右对齐截断方式进行匹配。举个例子说:

         Verilog HDL的程序结构及其描述第3张Verilog HDL的程序结构及其描述第4张

 

参数定义与映射:

  ①参数定义就是parameter 那一部分了,也就是可以用一个标识符表示一个固定的参数,当然`define这种宏定义也可以实现这种功能,这样子提高程序的可维护性和可读性。

使用`define时语法为:`define  A  2'b10 或者`define A 2.
  一般把`define宏定义语句放在模块最前面,并且要注意,无论是在子模块还是顶层模块中,A 的值都代表2(调用时为 `A)(全局参数)。
使用parameter定义的语法为 parameter  A = 2或者parameter A= 2’d2;
一般放在模块名字和模块端口列表之间:模块名 #(parameter A = XX,.....)(端口列表);使用parameter定义的参数只在当前模块中有用(局部参数)

localparam定义时,上层模块不能调用传递参数。

  ②参数传递:

参数传递就是在编译或者仿真的时候,进行维护时,对参数空闲重新复制而更改其值。传递的参数是子模块中定义的parameter,传递的方法有两种:

  (1)使用’#’符号:在同一模块中使用’#’符号,参数赋值顺序必须与原始模块定义的顺序相同,并不是一定要给所以的参数赋值,但是不允许跳过任何一个参数,即使是保持不变的值也要写在相应的位置。说了这么一大坨,还是举个例子吧:

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

这样子,A_WITH就是x1,B_WITH不改变,但是要写在相应的位置。

  (2)使用defparam关键字

直接上格式:

       Verilog HDL的程序结构及其描述第6张

 

 

 

免责声明:文章转载自《Verilog HDL的程序结构及其描述》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇解决resteasy上传表单文件名乱码EPANET中读取INPUT文件的函数文件——INPUT1.C/INPUT2.C/INPUT3.C下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【Shell脚本学习1】Shell简介:什么是Shell,Shell命令的两种执行方式

Shell本身是一个用C语言编写的程序,它是用户使用Unix/Linux的桥梁,用户的大部分工作都是通过Shell完成的。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。 它虽然不是Unix/Linux系...

C语言高级部分总结

C语言高级部分总结 嵌入式ARM 3天前 信息来源于网络 一、内存大话题 1.0、内存就是程序的立足之地,体现内存重要性。 1.1、内存理解: 内存物理看是有很多个Bank(就是行列阵式的存储芯片),每一个Bank的列就是位宽 ,每一行就是Words,则存储单元数量=行数(words)×列数(位宽)×Bank的数量;通常也用M×W的方式来表示芯片的容量(或...

React Native Android原生模块开发实战|教程|心得|怎样创建React Native Android原生模块

尊重版权,未经授权不得转载 本文出自:贾鹏辉的技术博客(http://blog.csdn.net/fengyuzhengfan/article/details/54691503) 告诉大家一个好消息。为大家精心准备的React Native视频教程公布了,大家现能够看视频学React Native了。 前言 一直想写一下我在React Nativ...

JS实现 Tab栏切换案例

要求:当鼠标点击上面相应的选项卡(tab),下面页面的内容也随之而改变。 结构分析:   全部的内容都放到一个大的盒子里面,盒子里面又可以分为上面和下面两个盒子。   上面的盒子放了 5个li,装着5个小的选项卡,默认会有一个被选中;   下面的盒子也包含了 5个 div 模块,模块内容与上面的选项一一对应,当前默认的只有第一个 div会被显示出来。 实现...

Springboot使用MessageSource读取资源文件

1、项目开发过程中的提示文字信息可以在资源文件中进行定义,而且资源文件是实现国际化技术的主要手段。如果想在SpringBoot里面进行资源文件的配置,只需要做一些简单的application.yml配置即可,而且所有注入的资源文件都可以像最初的Spring处理那样,直接使用MessageSource进行读取。 首先,在src/main/resources源...

embed 元素的用法

embed (一)、基本语法: embed src=url 说明:embed可以用来插入各种多媒体,格式可以是 Midi、Wav、AIFF、AU、MP3等等,Netscape及新版的IE 都支持。url为音频或视频文件及其路径,可以是相对路径或绝对路径。 示例:<embed src="http://t.zoukankan.com/your.mid"&...