目录
3.2、Verilog允许设计者使用一下三种方式来描述逻辑电路
1、verilog语法与要素
1.1、Verilog结构
-
定义模块:moudle endmoudle
-
输入端口input output inout
-
注释// /..../
-
信号类型声明 reg[3:0] out; 小端
-
逻辑功能定义:
-
assign持续赋值语句
-
always过程块定义
-
调用元件
-
1.2、Verilog语言要素
-
空白符
-
注释 // /* */
-
标识符
1.3、常量
-
整数
-
格式: +/- <size>'<进制><数字> eg:-6‘hFFF
-
-
可以使用_隔开数字,方便阅读
-
?是高阻态z
-
sh代表有符号整数
1.4、字符串
1.5、数据类型
-
逻辑值
-
0、1、x、z
-
-
net型
-
wire
-
tri
-
supply1,supply0:supply1是电源(逻辑1)、supply0是地(逻辑0)
-
-
variable型(register型)
-
reg:寄存器
-
integer:32位整数
-
real
-
time
-
1.6、参数
-
parameter
-
声明格式:parameter 参数名1=表达式1,参数2=表达式2
-
采用:#(参数声明1,参数声明2,...)的形式进行定义参数
-
-
参数的传递
-
用# 隐式的重载:重载的顺序与参数必须在原定义模块中声明的顺序相同,并且不能跳过参数
-
在线显式重载:允许在线参数按照任意顺序排列
-
使用defparam 语句显式重载
-
-
localparam 定义的参数仅仅作用于本模块,不可用于参数传递,也就是说在实例化的时候不能通过层次引用进行重定义
1.7、向量
-
宽度为1位的变量称为标量,线宽大于1位的变量称为向量
-
向量可以分为两种:标量类向量,向量类向量,标量类向量支持位选择和域选择,在定义时用关键字scalared说明,向量类向量不支持位选择,只能作为一个统一 的整体操作,使用vectored说明
-
存储器:二维数组 reg[3:0] mema[63:0]
字长 容量
1.8、运算符
-
^~ 按位同或
-
~^ 按位异或
2、Verilog语句语法
2.1、过程语句
-
initial:initial只执行一次
-
用于赋初值
-
-
always:always不断重复执行
-
敏感列表@(a or b)信号之间用or连接(Verilog-2001中新规定也可使用,分割)
-
posedge negedeg关键字 上升沿触发 下降沿触发
-
*代表块内全部信号
-
2.2、块语句
-
bigin-end语句 串行块
-
fork -join 语句 并行块
2.3、赋值语句
-
assign 为持续赋值语句 主要用于对wire型变量的赋值
-
过程赋值语句
-
非阻塞赋值 <=
-
阻塞赋值 =
-
在always块中,阻塞赋值是顺序执行的、非阻塞赋值是并发执行的
-
2.4、条件语句
-
if-else语句
-
case语句:case(敏感表达式)值1:语句1 ......default:语句
2.5、循环语句
2.6、编译指示语句
-
宏替换 ‘define 宏名 字符串 eg.'define sum ina+inb 调用:out=’sum+inc
-
文件包含‘include eg:’include “文件名”
-
‘条件编译 ‘ifdef ’else ‘endif
2.7、任务与函数
-
任务:task:
-
定义 task<任务名>; 端口以及数据类型声明语句
-
调用 <任务名>(端口1,端口2)
-
-
任务的注意事项
-
任务的定义与调用必须在一个moudle中
-
定于任务时,没有端口名列表,但需要紧接着进行输入/输出端口和数据类型的说明
-
当任务被调用时,任务被激活。任务的调用通过任务名调用实现,调用时需列出端口名列表,排序与定义时一致
-
一个任务可以调用其他任务与函数
-
-
函数:function:
-
定义:function<返回值位宽或类型说明> 函数名;
-
调用:<函数名> (<表达式1>,<表达式2>)
-
-
函数的注意事项
-
函数的定义与调用必须在一个moudle 中
-
函数要求至少有一个输入变量
-
输出变量由函数名本身担任
-
定于任务时,没有端口名列表,但需要紧接着进行输入/输出端口和数据类型的说明,与任务一致
-
函数可以出现在持续赋值assign的右端表达式中
-
函数不能调用任务
-
2.8、执行与并发执行
-
always过程块、assign过程块、实例元件的调用等操作都是同时执行的
-
always内部对于非阻塞赋值语句是并发的,对于阻塞语句是顺序执行的
2.9、Verilog—2001语言标准
-
ANSI C风格的模块声明:允许将端口声明和数据类型声明放在同一条语句
-
可以使用逗号分割铭感信号列表
-
在组合逻辑铭感信号列表中使用通配符“*”,表示对过程块中出现的信号均敏感
-
generate语句:通过generate语句循环可以产生一个对象(moudle、primitive(原语)或者variable、net、task、function、assign、initial、always)
generate语句一般与循环语句,条件语句,一起使用,新增四个关键字(来表示新的数据类型)
-
generate
-
endgenerate
-
genvar:在generate循环中的标尺变量必须定义为genvar型数据,for循环中的内容必须在begin and块语句中 并且要命名
-
localparam:局部变量
-
-
有符号的算数扩展
-
wire与reg可以声明为有符号变量:eg:wire signed[3:0] a
-
整数与参数 12’sh54f
-
函数返回值
-
-
增加了算数移位操作符
-
系统函数$signed与$unsigned
-
指数运算符**
-
常数函数:与普通函数的区别在于其赋值是在编译或详细描述(elboration?)时被确定的
-
定义:function integer 函数名
-
注意:常数函数只能调用常数函数,不能调用系统函数
-
-
向量的位选与域选:
-
[base_expr +: width_expr] 正偏移
-
[base_expr -: width_expr]负偏移
-
-
多维数组
-
矩阵的位选择与部分选择
-
模块实例化时的参数重载:当模块实例化时,其内部定义的参数(parameter)值是可以变化的,有两种方法可以改变参数值:
-
defparam:显式重载
-
模块化时使用#隐式重载
-
重载的顺序必须与定于顺序相同
-
新增第三种在线显式重载参数的方式:.SIZE(1023)
-
-
可重入任务与递归函数:新增automatic关键字,可以实现:
-
可重入任务
-
递归函数
-
3、Verilog进阶
3.1、设计的层次
-
系统级
-
算法级
-
寄存器传输级(RTL)
-
门级
-
开关级
3.2、Verilog允许设计者使用一下三种方式来描述逻辑电路
-
结构描述
-
行为描述
-
数据流描述
3.3、结构描述
所谓结构描述方式,就是在设计中,通过调用库中的元件或已设计好的模块来完成设计实体的功能的描述
-
调用Verilog内置门元件(门级结构描述)
-
调用开关级元件(晶体管结构描述)
-
用户自定义元件UDP(门级)
3.3.1、门元件
-
基本门
-
多输入门:and、nand、or、xor、xnor
-
多输出门:buf、not
-
-
三态门:允许定义驱动强度:buf0,buf1,notif0,notif1
-
MOS开关:无驱动强度:noms、pmos、cmos
-
双向开关
-
上拉、下拉电阻:pullup,pulldown
3.3.2、真值表
若输入有x,则真值为x
3.3.3、三态门
三态门有使能端
-
当使能端为0时候,输出为z
-
为x、z,输入为0,1时,输出为L、H
3.3.4、门元件的调用
门元件名字 <例化的门名字>(<端口列表>)
端口列表:(输出,输入,使能控制端)
3.4、行为描述
行为描述,就是对设计实体的数学模型的描述,抽象程度远高于结构描述,无需指导电路结构,只需要清楚输入与输出信号的行为即可。
通常使用always语句赋值
3. 5、数据流描述
数据流描述方式主要使用持续赋值语句,多用于描述组合逻辑电路
assign LHS_net=RHS_expression;
4、有限状态机
4.1、两类状态机
-
摩尔型:输出只是当前状态的函数
-
米勒型:输出是当前状态与当前输入的函数
4.2、有限状态机的Verilog描述
-
当前状态,现态 CS
-
下一个状态,此态 NS
-
输出逻辑 OL
4.3、描述方式
-
三段式描述:CS、NS、OL各用一个always过程描述
4.4、状态编码
-
顺序编码
-
格雷码
-
约翰逊编码
-
独热码
5、testbench
5.1、系统任务与系统函数
-
系统任务:
-
$display : 显示模拟结果 ,在输出结束后能够自动换行 使用
-
使用格式:$display(“格式控制符”,输出变量名列表);
-
格式控制符:%V:显示net型数据的驱动强度,%M:显示层次名
-
-
$write:显示模拟结果 ,在输出结束后不能够自动换行
-
使用格式与display相同
-
-
$monitor:输出控制类的系统任务,每当列表中的信号变化,输出。可以看做是监控器
-
调用格式与上述相同
-
-
$strobe:当模拟时间发生改变,并且所有事都已经处理完毕才输出结果,相当于选通监控器 更多的用来显示用非阻塞方式赋值的变量
-
$time:64位整数模拟时间
-
$realtime:实整数型数据的形式返回模拟时间(小数)
-
$finish:对于仿真过程进行控制,表示结束仿真
-
调用格式 $finish(n)
-
n=0:不输出任何信息
-
n=1:给出仿真时间和位置
-
n=2:给出仿真时间和位置,运行统计数据
-
-
$stop:对于仿真过程进行控制,表示中断仿真
-
$random:随机数
-
5. 2、用户自定义元件(UDP)
-
输出端口只能有一个,位于端口列表第一个,只用输出端口可以定义为reg型
-
驶入端口可有多个,时序电路最多9个输入端口,组合电路最多10个
-
所有端口变量必须是1位标量
-
在table中只能出现0,1,x三种状态,不能出翔z状态
-
定义UDP语法
-
primitive 元件名(输出端口,输入端口1,输入端口2)
out 输出端口;
input 输入端口;
reg 输出端口
initial beign
输出端口或内部寄存器赋初值
end
table
//输入1 输入2 :输出
真值列表
endtable
endprimitive
-
-
UDP中的缩记符,
-
x 不定态
-
? 与x相同,只能表示输入
-
b 0/1
-
— 不变
-
(vy) v=y={0,1,x} 表示变化
-
* 表示输入端有任何变化
-
R/r 表示上升沿
-
F/f 下降沿
-
P/p 包含不定态的上升沿跳变
-
N/n 包含不定态的下降沿跳变
-
5.3、延时模型的表示
-
时间标尺定义 ‘timescale <time_unit>/<time_precision>
-
延时 #10 表示延时10个单位时间