【Verilog HDL数字系统设计】【笔记】Verilog HDL的基本语法

Verilog HDL 基本语法


Verilog HDL程序的基本结构

Verilog HDL程序由模块组成
一个完整的模块由模块端口定义模块内容组成
模块内容包括I/O声明信号类型声明功能表述
基本结构

module 模块名(端口定义);
	I/O声明;			//代码
	   功能描述;		//代码
endmodule

语法:

  • module 与 endmodule 定义一个模块的起始与解释
    module后跟模块名
    模块名必须以英文字母开头可以包括英文字母,数字和下划线
  • 除了endmodule,所有的语句以英文结尾结尾
  • 语句可以是单条语句,也可以是begin和end构成的复合语句 (后面会讲到)
  • 注释风格与C语言类似

模块端口定义

模块端口定义用来声明设计模块的输入/输出端口
格式:module 模块名 (端口1,端口2,端口3,···) ;
模块的端口是设计实体的对外引脚,是使用时外界可以看到的部分,多个端口之间用逗号

模块内容

模块内容用于对信号的I/O状态及信号类型进行声明,并描述模块的功能

I/O声明

模块的I/O声明用来声明各端口信号流动方向,包括输入,输出,双向
格式:

  • 输入声明
    信号位宽为1位,声明格式:input 端口1,端口2,端口3,.....
    信号位宽大于1位,声明格式:input[msb:lsb] 端口1,端口2,端口3,....

  • 输出声明
    信号位宽为1位,声明格式:output 端口1,端口2,端口3,....
    信号位宽大于1位,声明格式: output[msb,lsb] 端口1,端口2,端口3,....

  • 输入/输出声明
    inout

信号类型声明

信号类型声明用来说明电路的功能描述中所用信号数据类型
常用的信号类型有wire(连线型)reg(寄存器型)整型(integer),实型(real),时间型(time)

功能描述

功能描述是Verilog HDL程序的主要部分,在电路上相当于器件的内部结构

  • assign语句
    assign后加赋值语句,一般对组合逻辑进行描述,称为连续赋值方式
  • 实例元件实现
    利用Verilog HDL提供的元件库实现一个逻辑关系
    格式:元件名 实例化后元件名(输入/输出端)
    模块中的实例化后的元件名称必须唯一
  • always块
    常用于组合和时序逻辑的功能描述
    程序运行中,某些条件满足时,就重复执行always块中的语句
    格式:`always@(触发条件)
  • initial块实现
    与always块语句相似,但只执行一次,用于电路初始化

Verilog HDL的数据类型

Verilog HDL中共有19种数据类型

常量

程序运行过程中,值不能改变的量称为常量,分为三种:整型,实型,字符串型

整型

整型常量格式为:<位宽>'<进制><数值>
位宽:为对应的二进制宽度
进制:二进制,十进制,八进制,十六进制
数值:

  • 二进制数值用四种基本值表示:0,1,x,z

x表示未知,z表示高阻

  • 位宽可缺省,将由机器系统决定,至少为32位
  • 既缺少位宽又缺少进制的为十进制数
实型

实型数可以用十进制计数法科学计数法表示

科学计数法标志为e/E,例如6E-2表示0.06

字符串型

字符串是用双引号括起来的字符序列,它必须写在同一行
字符串中的每个字符都是以ASCII码的进行存放的

参数常量

用parameter定义常量,即定义一个标识符代表一个常量,称为参数常量或符号常量
格式:parameter 标识符 = 表达式/常量

变量

程序运行过程中,其值可以改变的量称为变量

wire型

wire是网络数据类型之一,表示结构实体之间的物理连接
网络类型变量不能储存值,而且必须受到驱动器驱动,没有驱动器连接到变量上时其值为高阻值
输入/输出信号默认自动定义为wire型
定义格式:wire[msb:lsb] 变量1,变量2,变量3,.....

wire为定义符,msb与lsb表示变量的最高位和最低位的编号,位宽由其决定
如果不指定位宽,则位宽默认为1
定义多个变量时,用逗号隔开

reg型

reg型为寄存器型,是数据存储单元的抽象,对应的是具有状态保持功能的电路元件
reg型变量只能在在alwaysinitial块中被赋值
若reg型变量未被初始化,则其值为未知x
reg型与wire型变量的区别是:wire型需要持续驱动,而reg型保持保持最后一次赋值
定义格式:reg[msb:lsb] 变量1,变量2,变量3,....

memory型

memory型为存储器型,通过建立reg型数组描述
定义格式:reg[msb:lsb] 存储单元 [n:m]...

[n:m]表示存储单元的编号范围

integer型

integer型是32位带符号整型变量,用于对循环控制变量的说明,不可综合,不与任何物理电路相对应
定义格式:integer 变量.....

time型

time型用于存储和处理时间,是64位无符号数
定义格式:time 变量....

real型

real型是64位符号实型变量,用于存储和处理实型数据
定义格式:real 变量.....

Verilog HDL的运算符

算术运算符

  • + 加法运算符或正值运算符
  • - 减法运算符或负值运算符
  • * 乘法运算符
  • / 除法运算符
  • % 取模运算符

逻辑运算符

  • && 逻辑与
  • || 逻辑或
  • ! 逻辑非

逻辑运算符操作的结果为0或1

关系运算符

>,>=,<,<=

等值运算符

  • == 逻辑相等
  • != 逻辑不等
  • ===逻辑全等
  • !==非全等

操作数中某些位可能是x或z,这样用==比较的结果就是x
===运算符按进行比较,每一位都相等才会判断为相等

位运算符

位运算符即对两个数按位进行逻辑运算

位数不同时,在位数少的数的高位自动补0

缩减运算符

移位运算符

条件运算符

拼接运算符

运算符的优先级

Verilog HDL的基本语句

赋值语句

赋值语句分为两种:连续赋值语句过程赋值语句

连续赋值语句

连续赋值语句用来驱动wire型变量,且变量必须事先定义
只要输入端操作数发生变化,该语句就重新计算并刷新赋值结果
用来描述组合逻辑
连续赋值语句格式:`assign #(延时量)wire 型变量名 = 赋值表达式
含义:只要右边赋值表达式中有变量发生变化,就重新计算表达式的值,新结果在指定的延时时间单位以后赋值给wire型变量,不指定延时量则默认为0

过程赋值语句

过程赋值语句在initialalways语句块内赋值
对于reg,memory integer,time,real型变量赋值
这些变量将在下一次赋值之前保持原来的值
分为两类:阻塞赋值非阻塞赋值

  • 阻塞赋值
    赋值符:“=”,在语句结束时完成赋值操作
    格式:变量 = 赋值表达式

  • 非阻塞赋值
    赋值符:“<=”,在块结束时才完成赋值操作
    格式:变量 <= 赋值表达式

区别:非阻塞语句的赋值时并行执行的

阻塞赋值与非阻塞赋值区别如下
code1:
 r1 = 1;
 r2 = 2;
 r3 = 3;
 r2 = r1;
 r3 = r2;
 //该段程序执行结果为:r1 = 1,r2 = 1,r3 = 1

code2:
 r1 = 1;
 r2 = 2;
 r3 = 3;
 r1 <= r3
 r2 <= r1
 r3 <= r2
 //该段程序执行结果为:r1 = 3, r2 = 1 , r3 = 2

条件语句

if-else语句

Verilog HDL提供了3种形式的if语句

第一种:
if(表达式) 
	语句

第二种:
if(表达式)
	语句1
else
	语句2
	
第三种
if(表达式1)
	语句1
else if (表达式2)
	语句2
else if (表达是3)
	语句3
....
else 
	语句 n

case语句

case语句是一种多分支语句
格式:

case (控制表达式)
	分支项表达式 1:语句1
	....
	default:语句n
endcase

循环语句

Verilog HDL中有四类循环语句,分别为

  • forever循环
  • repeat循环
  • while循环
  • for循环
forever循环

forever循环语句用于连续执行过程,不能独立写在程序中,必须写在initial块中
格式:forever 语句
常用于产生周期性的波形

repeat循环

repeat循环语句是用于执行指定循环次数的过程语句
格式:repeat(表达式) 语句
repeat表达式通常为常量表达式,表示循环次数
如果循环计数表达式的值不确定,即为X或Z时,循环次数为0

while循环

循环执行直到指定条件为假,与C语言中while语句类似
格式:while 语句
**如果条件为X或Z,则按假处理

for循环

与C语言中for循环语句类似
格式:for(初值表达式; 条件; 循环变量增值) 语句

结构声明语句

Verilog HDL中任何过程模块都从属于四种结构说明语句
initial,always,task,function

initial说明语句

initial语句常用于对各变量的初始化
一个程序模块中可以有多个initial语句
所有initial语句在程序&一开始时同时执行,并且只执行一次
格式:initial 语句

always说明语句

一个程序可以有多个always语句,在程序一开始执行,当敏感事件列表有条件满足时,运行一次语句
格式:always @(敏感事件列表) 语句
敏感事件列表:作用是激活always语句,可以是电平触发,边沿触发,可以是单个事件或是多个事件

多个事件用or连接
如果敏感事件是电平信号则直接给出信号名
如果敏感事件是边沿信号,则分为上升沿和下降沿
上升沿触发的信号前加关键字posedge,下降沿触发信号前加关键字negedge

task说明语句

task说明语句定义任务,类似高级语言中的字程序,用来单独完成某项任务,并被其他模块或其他任务调用

任务定义语句:
	task 任务名
		端口声明语句
		类型声明语句
		语句
	endtask
任务调用语句:
	任务名 (端口名列表)

注意:

  • 任务的定义与调用必须在同一个模块内
  • 任务的定义不能出现在任何一个过程块内
  • 任务的调用应在always,initial块或另一个任务汇总
  • 任务定义时,task语句后没有端口名列表,一个任务也没有输入输出端口
  • 当任务被调用时,任务被激活,如果一个任务有输入输出端口,调用时需列出端口名列表,其顺序与任务定义中完全一致
  • 进行任务调用时,参数的传递是按值传递的,不能按址传递
  • 一个任务可以调用别的函数或任务或函数,可以调用的函数或任务不受限制
function说明语句

function说明语句用来定义函数。函数类似高级语言中的函数,用来单独完成某项具体的操作。
函数可以作为一个表达式中的一个操作数,也可以被模块,任务或其他函数调用
函数调用有一个返回值

函数语句定义:
function(返回值的类型或范围) 函数名
	端口声明语句;
	类型声明语句;
	语句
endfunction
//返回值的类型或范围是可选项,若缺省,则返回值为一位寄存器类型的数据

函数的调用:
	函数名(端口名列表)

函数与任务的区别:

返回值

  • 函数只能有一个返回值,任务可以有多个或没有返回值

  • 函数的返回值是通过函数名返回的,任务的返回值是通过输出端口传递的
    输入变量

  • 函数至少有一个输入变量,任务可以多个任何类型的变量或没有

仿真时间

  • 函数只能与主模块共用一个仿真时间,而任务可以定义自己的仿真时间单位

调用

  • 函数不能调用任务,而任务可以调用其他任务和函数

你可能感兴趣的:(Verilog,HDL数字系统设计)