Verilog语法
连续赋值语句, 阻塞赋值语句, 非阻塞赋值语句
数据流的描述是采用连续赋值语句(assign )语句来实现的。语法如下:
assign net_type = 表达式;
连续赋值语句用于组合逻辑的建模
等式左边是wire 类型的变量
等式右边可以是常量. 由运算符如逻辑运算符. 算术运算符参与的表达。
如下几个实例:
1 | wire [3:0] Z, Preset, Clear; //线网说明 |
- 连续赋值语句的执行是:
只要右边表达式任一个变量有变化,表达式立即被计算,
计算的结果立即赋给左边信号。 - 连续赋值语句之间是并行语句,因此与位置顺序无关
(“=”用于阻塞的赋值, 凡是在组合逻辑(如在assign 语句中)赋值请用阻塞赋值)
行为建模方式
一般是指用过程赋值语句
(initial 语句和always 语句)
- 顺序语句块(begin . . . end):
语句块中的语句按给定次序顺序执行;
1 | begin |
- 两种过程赋值语句 initial 和 always 语句:
这两种语句之间的执行是并行的,即语句的执行与位置顺序无关
这两种语句通常与语句块(begin ….end)相结合,则语句块中的执行是按顺序执行
initial 语句只执行一次;
always 语句与initial 语句相反, 是被重复执行, 执行机制是通过对一个称为敏感变量表的事件驱动来实现的:
1 | initial |
对于always:
- 对组合逻辑器件的赋值采用阻塞赋值 “=”
- 时序逻辑器件的赋值语句采用非阻塞赋值 “<=”,如上的 Q 〈= D;)
结构建模
实例化语句:
1 | module_name instance_name(port_associations); |
信号端口可以通过位置或名称关联;但是关联方式不能够混合使用
端口关联形式如下:
1 | port_expr //通过位置。 |
port_expr 可以是以下的任何类型:
- 标识符
(reg 或net )
如:.C(T3),T3
为wire型标识符 - 位选择 ,如
.C(D[0])
,C端口接到D信号的第0bit 位 - 部分选择 ,如
.Bus (Din[5:4])
- 上述类型的合并,如
.Addr({ A1,A2[1:0]})
- 表达式(只适用于输入端口),如
.A (wire Zire = 0 )
- 对输入管脚悬空的,则该管脚输入为高阻 Z,输出管脚被悬空的,该输出管脚废弃不用
1 | module and (C,A,B); |
书写建议
- 条件表达式需用括号括起来
- 若为if - if 语句,请使用块语句 begin —- end:
1 | if (Clk) |
以上两点建议是为了使代码更加清晰,防止出错。
- 对if 语句,除非在时序逻辑中,if 语句需要有else 语句
若没有缺省语句, 设计将产生一个锁存器, 锁存器在ASIC设计中有诸多的弊端(可看同步设计技术所介绍)。
如下一例:
1 | if (T) |
注意语法
算术表达式结果的长度由最长的操作数决定
1 | assign Dbus [7:4] = {Dbus [0], Dbus [1], Dbus[2], Dbus[3] } ; |
reg 是最常用的寄存器类型, 寄存器类型通常用于对存储单元的描述
如在always 语句中进行描述的必须用reg 类型的变量
- reg 类型定义语法如下:
reg [msb: lsb] reg1, reg2, . . . reg N;
msb 和lsb 定义了范围,并且均为常数值表达式。 - 寄存器类型的值可取负数,但若该变量用于表达式的运算中,则按无符号类型处理
- 对数组类型,请按降序方式,如
[7:0];