1.1一个基本的Verilog代码构成
1 | module 模块名 ([端口列表]); |
如
1 | module full_adder (A,B,CIN,S,COUT); |
1.2语法
(1)逻辑运算关系
算术型
***** | 乘法 |
---|---|
/ | 除法 |
+ | 加法 |
- | 减法 |
% | 求余 |
****** | 求幂 |
其中运算规则为
- 加减乘除、求幂的操作数可以是实数也可以是整数,求余运算的操作数只能是整数
- 求余运算结果取第一个操作数的符号
逻辑型
! | 逻辑非 |
---|---|
&& | 逻辑与 |
|| | 逻辑或 |
其中运算规则为
- 逻辑型运算的结果可能是1(逻辑真)、0(逻辑假)、x(不确定)
- 逻辑运算的操作数可以是任意表达式,表达式的结果被当做逻辑值处理,只有1、0、x三种情况,非0、x即1
关系运算符
> | 大于 |
---|---|
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
等价运算符
== | 等于 |
---|---|
! = | 不等于 |
=== | **case ** 等于 |
! == | case 不等 |
其中运算规则为
- 等于和不等于运算的结果可能是1(逻辑真)、0(逻辑假)、x(不确定);对于x或a,认为是不确定的值,比较结果为x
- case等和case不等的结果只能是1或0,对于x、z认为是确定的值,参加比较
按位运算符
用于二进制数如1001与1111按照一位一位相比较
~ | 按位非 |
---|---|
& | 按位与 |
| | 按位或 |
^ | 按位异或 |
~^ ^~ | 按位同或 |
其中运算规则为
- 其它按位运算的操作数有2个或多个,将两个操作数对应的位两两运算
- 如果操作数位宽不同,位宽小的会自动左添0补齐
缩减运算符
缩减运算的操作数只有一个,将该数的各位自左至右进行逻辑运算,结果只有一位
& | 缩减与 |
---|---|
~& | 缩减与非 |
| | 缩减或 |
~| | 缩减或非 |
^ | 缩减异或 |
~^ ^~ | 缩减同或 |
1 | 例: |
移位运算符
将一位或者多位向左或向右移n位
>> | 右移 |
---|---|
<< | 左移 |
>>> | 算术右移 |
<<< | 算术左移 |
1 | 例: |
拼接复制运算符
可以将两个四位二进制数链接起来
{} | 拼接 | {操作数1, 操作数2, …} |
---|---|---|
{ {} } | 复制拼接 | {n{ 操作数 1, 操作数2, …}} |
1 | 例: |
条件运算符
跟C语言中一样,可以对未知数进行条件赋值
表达式1 ? 表达式2 : 表达式3 | 用于条件赋值 |
---|---|
表达式1=1 | 结果等于表达式2 |
表达式1=0 | 结果等于表达式3 |
表达式1=x | 结果为x |
(2)assign语句
- assign语句称作连续赋值语句,相当于数电中的电平触发,其总是处于激活状态,只要表达式中的操作数有变化,立即进行计算和赋值(与连续赋值语句对应的另一种语句称为过程赋值语句)
- 赋值目标必须是wire型的,wire表示电路间的连线
这里给出一个assign语法的例子
1 | assign y=a; |
(3)always语句
- always语句本身不是单一的有意义的一条语句,而是和下面的语句一起构成一个语句块,称之为过程块;过程块中的赋值语句称过程赋值语句
- 该语句块不是总处于激活状态,当满足激活条件时才能被执行,否则被挂起,挂起时即使操作数有变化,也不执行赋值,赋值目标值保持不变
- 赋值目标必须是reg型的
always语法的基本格式和例子
1 | always @(敏感信号条件表) |
敏感条件即上面的@(敏感信号条件表)
有两种,一种是边沿敏感,一种是电平敏感
边沿敏感
(posedge 信号名) | 信号上升沿到来 | 例:(posedge clk) |
---|---|---|
(negedge 信号名) | 信号下降沿到来 | 例:(negedge clk) |
1 | 例: |
电平敏感
(信号名列表) | 信号列表中任一信号有变化 |
---|---|
例:(a,b,c) | 的a,b,c中有一个信号发生改变,always下的过程块被触发 |
其中逗号也可以换成or就变成(a or b or c)
1 | 例: |
在always语法中插入if和case等语句
1 | 例: |
begin end之间的赋值语句有阻塞赋值和非阻塞赋值之分
阻塞赋值
语句顺序执行,前面的执行完才能执行后面,赋值符号:=
,右边表达式的计算和对左边寄存器变量的赋值是一个统一的原子操作中的两个动作,这两个动作之间不能再插入其他任何动作
1 | 赋值目标1=表达式1; |
非阻塞赋值
所有语句并行执行,赋值符号:<=
,首先按顺序计算右边表达式的值,但是并不马上赋值,而是要等到过程结束时再按顺序赋值。
1 | 赋值目标1<=表达式1; |
底层模块和门语言调用
底层模块调用
为了实现多个门电路组合使用,我们先设计一个底层的基础的D触发器模块
其用代码表示为
1 | module DFF(CLK,D,Q) |
这时我们再将两个模块组合起来,加入两个内部变量d1和q1调用底层模块,在调用底层模块的时候要遵顼这两个格式
端口名关联法(命名法)
因为有名字对应,不必按底层模块的端口信号列表顺序1
2(.底层端口名1(外接信号名1),.底层端口名2(外接信号名2),…)
DFF dff1(.CLK(clk),.D(d1),.Q(q1));位置关联法(顺序法)
必须严格按照底层模块的端口信号列表顺序书写1
2(外接信号名1,外接信号名2,…)
DFF dff2(q1,d,q);
1 | module examp (clk,d,a,q) |
门原语调用
Verilog语言提供已经设计好的门,称为门原语(primitive,共12个),这些门可直接调用,不用再对其进行功能描述
门原语调用格式:门原语名 实例名 (端口连接)
其中实例名可省略(和模块调用不同),端口连接只能采用顺序法,输出在前,输入在后。
于是实际情况:例:and (out, in1, in2);
端口连接中第一个是输出,其余是输入,输入个数不限
下面给出6个与门相关的门原语
and (与) | or(或) | xor(异或) |
---|---|---|
nand(与非) | nor(或非) | xnor(同或) |
- 特殊门
not (非门) | not (OUT1, IN); |
---|---|
buf(缓冲器) | buf b1_2out(OUT1, OUT2, IN); |
三态门
bufif1(控制端1有效缓冲器) | bufif1 b1 (out, in, ctrl); |
---|---|
bufif0(控制端0有效缓冲器) | 如上修改名称 |
notif1(控制端1有效非门) | notif1 n1 (out, in, ctrl); |
notif0(控制端0有效非门) | 如上修改名称 |
端口列表中前面是输出,中间是输入,最后是使能端,输出个数不限。
数字表示格式
无符号数的表示方法:<位宽>’ <进制><数字>