Verilog 基本语法
分类
模块
语法
语法要点
Test bench
执行
1. 分类
- 系统级:不可综合的
- 算法级
- RTL 级:寄存器传输级(最常设计的等级)
- 门级、开关级:不常用
- 行为级:将一个模块当作黑盒子,仅描述行为不关心实现
- 可综合语法:设计结构
- 不可综合语法:功能仿真,监控调试
2. 模块
1 | //多路选择器 |
3. 语法
- Verilog HDL 区分大小写
- Verilog HDL 关键字全小写
- Verilog HDL 注释符:// xxx
3.1 常量
数字
<位宽>’<进制><数值>
位宽:对应二进制的宽度(十进制可缺省)
进制:用 bohd 或 BOHD 表示(十进制可缺省)
位宽小于实际数字的时候,相应高位被忽略.(4’d61==4’b1101)
除了十进制以外,数值可以包含 x(不定)、z(高阻).高阻态:通常指输出引脚,引脚与内部电路是断开的,不导通,呈高阻状态.
不定态:是指在引脚上所加的或输出的电压在 1V~2V 之间,这个电平是不确定的状态.引脚可以是输入脚, 也可以输出脚
语法
parameter 参数 1=表达式,参数 2=表达式,…… ;
例如: parameter code=8’ha3;
3.2 变量
网络型:nets type
寄存器型:register type
网络型
类型 | 功能 |
---|---|
wire, tri | 连线功能 |
wor,trior | 多重驱动时,具有线或功能的连线型 |
wand,triand | 多重驱动时,具有线与功能的连线型 |
tri1,tri0 | 上拉电阻/下拉电阻 |
supply1/supply0 | 电源(逻辑 1)/ 地(逻辑 0) |
wire 类型(最常用)
常用来表示用 assign 语句赋值的组合逻辑信号
取值为:0,1,x(不定值),z(高阻,不常用)
语法
wire 数据 1,数据 2,……. 数据 n;
例子:wire[20:1] addrbus; //定义了 20 位位宽 wire 型向量地址总线
寄存器型
类型 | 功能说明 | 具体硬件 |
---|---|---|
reg | 常用的寄存器型变量 | 触发器、寄存器 |
integer | 32 位带符号整数型变量 | 无 |
real | 64 位带符号整数型变量 | 无 |
time | 无符号时间变量 | 无 |
语法
reg 数据 1,数据 2,…… 数据 n;
例子:
reg[8:1] data
reg[7:0] memory[1023:0] //定义 1k 字节(8bits)的存储器
3.3 运算符
_基本同 C++_
- 缩减运算符: 自身各个 bit 从低位到高位连续运算
&
,|
,~&
,~|
,^
,~^
- 链接运算符:
{a,b,c,d,e,f,g}
{}
4. 语句
4.1 块语句
- 顺序块:begin-end
- 并行块:fork-join
并行块中的语句块并行执行,其中包含单条语句和顺序块.
4.2 过程块
always
_用于描述带有敏感信号列表的过程块,always 过程块不能嵌套使用._
always @(<敏感信号表达式>)
//posedge->上升沿触发 negedge->下降沿触发
begin
//过程赋值
//if 语句
//case 语句
//while,repeat,for 语句
//task,function 调用
end
initial
用于描述初始化过程块,initial 过程块不能嵌套使用.
主要面向功能模拟,不具有可综合性,只用于测试文件
initial //如果有多个 initial 过程块,各个模块并行执行
begin
语句 1;
语句 2;
……
end
4.3 赋值语句
4.3.1 连续赋值语句(assign)
常用于对 wire 型变量进行赋值
assign c=a&b
a,b 信号的任何变化,都随时反应到信号 c 上(组合逻辑)
4.3.2 过程语句赋值
阻塞赋值(=)
1 | always @(posedge clk) |
如上两个赋值语句同时执行,c 只会得到 b 的旧值.
阻塞赋值并行执行,一定会生成寄存器.(推荐使用)
非阻塞赋值(<=)
1 | always @(posedge clk) |
如上两个赋值语句同时执行,c 和 b 都得到 a 的值.
非阻塞赋值顺序执行.(大佬说这个 coding style 很菜哈哈哈哈)
4.4 条件语句
if-else
case 1
if (<条件表达式>) 语句或语句块;case2
if (<条件表达式>) 语句或语句块;
else 语句或语句块;case3
if (<条件表达式>) 语句或语句块;
else if (<条件表达式>) 语句或语句块;
……
else if (<条件表达式>) 语句或语句块;
else 语句或语句块;
_if-else 需要配对写齐,否则会综合出来锁存器._
case
case (<敏感表达式>)
值 1:语句与语句块;
值 2:语句与语句块;
……
值 n:语句与语句块;
default:语句或语句块;(可省略)
encase
4.5 循环语句
forever/repeat
无限循环/连续执行语句,多用于 initial 语句块中,以生成周期性波形,不可综合.
1 | repeat(size) |
while
条件循环,直到不满足条件
1 | while(i<4) |
for
条件循环,条件满足则执行
1 | for(i=0;i<6;i=i+1) |
4.6 task 和 function
4.6.1 task(不可综合)
1 | task<任务名> |
调用格式
<任务名>(端口 1,端口 2,……)
特征
支持多种目的,可计算多个结果,能够启动其他任务和函数,没有返回值.
可以定义自己的仿真单位.
4.6.2 function(可综合)
1 | function<返回值位宽或类型> <函数名> |
调用格式
<函数名> (<输入表达式 1>,<输入表达式 2>,……)
特征
通过返回一个值来响应输入信号的值,一般将函数作为表达式中的操作符.
需要至少一个输入变量,有一个返回值,只能与主模块共用一个仿真时间单位.
4.6.3 系统任务和函数
- 标准输出任务:$display 等
- 文件管理任务:$fopen 等
- 仿真控制任务:$monitor 等
- 时间函数:$timeformat 等
- 时间显示函数:$time 等
- 其他:$random 等
5. 语法要点
- always 里面赋值左边必须声明成 reg
- assign 表达式左边必须声明成 wire
- 阻塞赋值用=
- 非阻塞赋值用<=
_Coding 要点_
- 边缘触发逻辑一律用<=赋值
- 电平触发一律用=赋值
- 逻辑简单用 assign 语句,逻辑复杂用 always 语句.
- 条件分支写完整,避免出现锁存器.
6. Test bench(测试台)
包裹在可综合代码外面,用来测试的,不可综合的模块.(综合=编译)
7. 执行
不同模块,同模块中的不同逻辑部分,并行执行.
组合逻辑只要上电就可执行.
时序逻辑需要上电与时钟信号.