分类
模块
语法
语法要点
Test bench
执行

1. 分类

  • 系统级:不可综合的
  • 算法级
  • RTL 级:寄存器传输级(最常设计的等级)
  • 门级、开关级:不常用
  • 行为级:将一个模块当作黑盒子,仅描述行为不关心实现
  • 可综合语法:设计结构
  • 不可综合语法:功能仿真,监控调试

2. 模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//多路选择器
//模块类似于函数
module mux(out,in0,in1,sel); //接口端
parameter N=8; //定义参数
output[N:1] out; //定义端口类型
input[N:1] in0,in1; //[最高位:最低位]
input sel; //默认1bit
assign out=sel?in1:in0; //问号表达式
endmodule;

//加法计数器
module counter(q,cout,reset,cin,clk);
parameter N=4; //参数定义
output [N:1]q; //输出端口定义
output cout;
input reset,cin,clk; //输入端口定义
reg [N:1]q //数据类型定义:寄存器型(有保持功能)
// 缺省:导线型(wire)

always @(posedge clk) /时钟上升沿执行下面语句块:描述时序 (negedge:下降沿)
begin //语句块开始
if(reset) q<=0; //清零(非阻塞赋值)
else
q<=q+cin; //计数或者保持
end //语句块结束
assign cout=&q&&cin; //描述组合电路
endmodule




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
2
3
4
5
always @(posedge clk)
begin
b<=a;
c<=b;
end

如上两个赋值语句同时执行,c 只会得到 b 的旧值.

阻塞赋值并行执行,一定会生成寄存器.(推荐使用)

非阻塞赋值(<=)
1
2
3
4
5
always @(posedge clk)
begin
b=a;
c=b;
end

如上两个赋值语句同时执行,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
2
3
4
5
6
7
8
9
10
11
12
repeat(size)
begin
if(temp_b[1]) outcome=outcome+temp_a;
temp_a=temp_a<<1;
end
end

forever
begin
tempa=tempa<<4;
end
end

while

条件循环,直到不满足条件

1
2
while(i<4)
i=i+1;

for

条件循环,条件满足则执行

1
2
for(i=0;i<6;i=i+1)
if(vote[i]) sum=sum+1;

4.6 task 和 function

4.6.1 task(不可综合)

1
2
3
4
5
task<任务名>
端口与类型说明;
局部变量说明;
语句或语句块;
endtask

调用格式

<任务名>(端口 1,端口 2,……)

特征

支持多种目的,可计算多个结果,能够启动其他任务和函数,没有返回值.
可以定义自己的仿真单位.

4.6.2 function(可综合)

1
2
3
4
5
function<返回值位宽或类型> <函数名>
输入端口与类型说明;
局部变量说明;
语句或语句块;
endfunction

调用格式

<函数名> (<输入表达式 1>,<输入表达式 2>,……)

特征

通过返回一个值来响应输入信号的值,一般将函数作为表达式中的操作符.
需要至少一个输入变量,有一个返回值,只能与主模块共用一个仿真时间单位.

4.6.3 系统任务和函数

  • 标准输出任务:$display 等
  • 文件管理任务:$fopen 等
  • 仿真控制任务:$monitor 等
  • 时间函数:$timeformat 等
  • 时间显示函数:$time 等
  • 其他:$random 等

5. 语法要点

  • always 里面赋值左边必须声明成 reg
  • assign 表达式左边必须声明成 wire
  • 阻塞赋值用=
  • 非阻塞赋值用<=

_Coding 要点_

  • 边缘触发逻辑一律用<=赋值
  • 电平触发一律用=赋值
  • 逻辑简单用 assign 语句,逻辑复杂用 always 语句.
  • 条件分支写完整,避免出现锁存器.

6. Test bench(测试台)

包裹在可综合代码外面,用来测试的,不可综合的模块.(综合=编译)

7. 执行

不同模块,同模块中的不同逻辑部分,并行执行.

组合逻辑只要上电就可执行.

时序逻辑需要上电与时钟信号.