文章目录
Verilog HDL设计方法
行为级:直接赋值;
RTL级:定义寄存器;
门电路级:定义模块,使用模块。
模块分为两种:定义的电路和测试。
Verilog常用语法
模块的结构
引入
- 端口定义,module-end module及其括号中的内容,对于测试文件来说,不存在括号;
- IO说明,对端口中的变量指定input、output以及位宽,其实也可以在端口定义中写这些内容;
- 内部信号声明,在这里可定义一些常量和变量;
- 功能定义。
端口定义
端口的连接方式有两种:
- blk(.a(q),.b(w),.sel(e),.out(t)):这样就不用在乎顺序了;
- blk(q,w,e,t):务必对应输入。
IO格式说明与内部信号声明
IO格式说明的格式为input/output [位宽-1:0] 端口名
内部信号声明常见的有reg和wire,格式为reg/wire[位宽-1:0] 变量名
关于对于端口而言,类型和输入输出可以一起写。
功能定义
- 实例元件;
- 连续赋值语句assign;
- 行为描述语句always。
数据类型及常量和变量
Verilog中的数制
通常默认为无符号数,在计算减法运算时,将减数视为负数,转换为补码,因为没有符号位,所以全部都是构成补码的。被减数相当于正数,所以说补码原码都一样。
有符号数进行运算时,除了一位符号位,其余都是补码。
如果只有数字的话,也就是十进制,默认为有符号数;integer也默认为有符号数。
常量
整数
- 二进制整数:b/B;
- 十进制整数:d/D;
- 十六进整数:h/H;
- 八进制整数:o/O。
常见的书写方式有:
<位宽><进制><数字>
:8b10101111
;
<进制><数字>
:o5270
;默认为32位,此时位数不能超过32位;
<数字>
:32
;默认为32位十进制,此时位数不能超过32位且必须得是十进制数字。
其中,位宽指的是数字转化为二进制之后占用的位的大小。
x和z
逻辑值的取值可以是:
- 0:逻辑0或者假状态;
- 1:逻辑1或者真状态;
- x:未知状态或者不关心状态;
- z/?:高阻态。
x和z可以用来定义
- 十六进制数的4位二进制状态;
- 八进制的3位二进制数状态;
- 二进制数的1位状态。
x不能表示十进制数字。
单独一个x配上啥进制都是合理的,但是和别的数字搭配的话,对于十进制来说就是非法的。
负数
只需要在位款表达式最前面加负号。
实数
可以有十进制和科学记数法两种格式。如果采用十进制的话,小数点两边都必须有数字。
下划线
主要是用于分割数字提高可读性的,只能用于数字之间。
参数
parameter 参数名=表达式
赋值语句中的表达式只能包含常量,即数字或者parameter。
注意区别于宏定义。
字符串
双引号表示,每个被机器理解为8位ASCII值。
变量
类型 | 符号 |
---|---|
网格型 | wire、tri |
寄存器型 | reg,integer |
存储器型 | memery(reg的数组) |
wire
- wire类型并不存储数据,需要与驱动器相连接;
- 驱动器有:门或者assign;
- 如果没有与驱动器连接,那么该变量就成了高阻态。
- wire和tri具有相同的语法格式和功能,在使用习惯上,wire用于assign或单个门,tri用于多驱动器;
- 模块的输入输出默认为wire;
- assign和输出必须是wire。
对于多驱动源,驱动一致,就是该输出;驱动不一致的话,处了高阻态于0、1,保持0、1,其余都是x。
reg
- reg可以存储数据;
- reg通过赋值语句来改变存储的值;
- 默认为x;
- always和initial的赋值对象必须为reg。
memory
定义格式为;reg [n-1:0] mem_name [m-1:0]
[n-1:0]
定义了每个存储单元的大小;[m-1:0]
定义了存储器中有多少寄存器。
定义了一个名为mem_name
的存储器,其中有m
个n
位的存储器单元,其地址范围是0~m-1。
需要注意的是
- 对存储器进行地址索引时,必须是常数表达式。
- 它是由n个1位reg构成的,而不是一个n位。
- 对其赋值时,需要进行地址索引。
Verilog HDL运算符
运算符类型 | 符号 |
---|---|
算术运算符 | + - * / % |
赋值运算符 | = <= |
关系运算符 | > < <= >= |
相等运算符 | == != ===(全等) !== |
逻辑运算符 | && || ! |
条件运算符 | ?: |
位运算符 | &,|,~,^(异或),^~或~^(同或) |
移位运算符 | << >> <<< >>> |
拼接运算符 | {} |
规约运算符 | & ~& | ~| ^ ~^ |
算术运算符
- 如果两个操作数有一个含x,那么结果未知;
- 如果两个数运算之后,超过了该有的位宽,会从低位开始进行截断;
- 操作数为reg或wire则是无符号数。
位运算
&与、|或、~非、^异或、~^同或
- 长度不同的操作数做位运算,系统会向右看齐,并给位数少的高位补0。
- 不要将位运算符和逻辑运算符混淆。
- ~是单目运算符。
- 异或运算符的话,有x就是x。
逻辑运算符
&&与、||或、!非。
逻辑运算符是对整体看的,就是说只要不是零,那么在逻辑运算符看来就是1。
如果x参与其中,还得看看1和0是否是绝对的。
关系运算符
如果关系成立,输出1,如果含x,那么输出x。
相等运算符
- ==和!=就是普通的相等和不等,如果操作数含x或z,那么结果就是x,z的话也是x。
- ===和!==则把x和z看成逻辑状态,必须完全一致才是1,否则是0。
逻辑移位运算符
a<<n
或a>>n
,a是操作数,n是移动的位数,0会填补这些空白。
4位全是x,但移位的时候还是给到了0.
算术移位运算符
连接与复制操作
- 将多个表达式拼接成一个大的表达式;
- 表达式中不允许存在未指明位数的信号,因为拼接的时候必须知道;
- 有
{3{a,b}}={a,b,a, b,a,b}
;
归约/缩减运算符
&规约与,|规约或,^规约异或,以及他们的非运算。
对单个操作数进行操作,从第1位一直到最后一位,最后结果为1位。
条件运算符
x?1001:1010 -> 10xx