注:文章内容为本人学习笔记,若有错误欢迎指正或补充。
1 运行逻辑
Verilog语言不同于c语言的运行逻辑,它的代码是并行执行的,只有在begin,end中的代码才是顺序执行。
2 数据类型与常量格式
在Verilog中最常用的两个数据类型分别是wire(网线型变量),reg(寄存器型变量)。输入信号必须为wire类型,输出信号看如何赋值选择用wire或reg。
常量格式 3'b101 三位二进制的101
3'o5 三位八进制的5
3'd5 三位十进制的5
3'h5 三位十六进制的5
3 参数定义
参数定义一共有两个函数 parameter 和 localparam ,用法类似c语言中的宏定义,parameter可以用于实例化用法如下。
module example
#(
parameter data1 = 1'b0,
parameter data2 = 1'b1
)
(...)
endmodule
//实例化格式
example
#(
.data1(data3),
.data2(data4)
)
example_int
(...)
4 赋值
Verilog有两种赋值方式,阻塞赋值 “=”,和非阻塞赋值 “<=”。在同一个语句块中阻塞赋值是一条条按照顺序赋值,非阻塞赋值是同时赋值的。(当值为x表示未知电平,z为高阻态)
例:a=1 b=2 c=3
a = b; a <= b;
b = c; b <= c;
c = a; c <= a;
得:a=2 b=3 c=2 a=2 b=3 c=1
5 赋值语句
always 过程过程赋值语句,使用它时需要用reg类型的变量,当敏感条件发生变化时执行内部代码。敏感条件有边沿触发和电平触发,边沿触发又分信号上升沿触发 (posedge) ,与信号下降沿触发(negedge),有多条赋值语句时需要用begin,end包括起来。另外if语句和case语言只能用于always语句块中。
always @(posedge in_1) //in_1信号上升沿触发
always @(negedge in_1) //in_1信号下降沿触发
always @(in_1) //in_1信号变化时沿触发
always @(*) //当有任意信号发生变化时沿触发
always #10 //每10个单位时间触发一次
assign 连续赋值语句,使用它时需要用wire类型的变量,assign 语句一般只有一行代码,当赋值的变量发生变化时执行。
initial 语句一般用于仿真实验的信号初始化,使用它时需要用reg类型的变量,initial语句块中的内容只会在仿真时钟为0时仅执行一次,若有多条则并行执行。
6 拼接运算符“ { } ”
拼接不同位数的变量,可用于等号赋值与被赋值
wire [1:0] data1;
wire data2;
wire data3;
assign data1 = {data2,data3};
assign {data2,data3} = data1;
7 一些Verilog语言的关键字(目前接触过的)
begin,end
类似c语言中的大括号。
module,endmodule
模块的开始与结束。
`timesale 1ns/1ns
设置时间基本单位和精度,前一个1ns时最小时间单位,后一个1ns时最小时间精度,时间单位不得小于精度。
$stop 暂停仿真
$finish 结束仿真
$time 获取时间
$random 随机数
打印相关函数
$write 打印,用法与c语言的打印相同
$display 打印,自动换行
$strobe 打印,自动换行,并最后执行
$monitor 变量发生变化时打印,用于变量监测
$timefoemat 改变打印时间的格式
//data1表示时间单位为10^(data)s,
//data2表示小数点后打印的位数
//data3打印的单位,应与data1的单位相同
//data4打印的最小数字字符
$timeformat(data1,data2,"data3",data4);
8 latch锁存器(组合逻辑)与Flip-flop触发器(时序逻辑)
latch对毛刺敏感,不能异步复位,还会使静态时序分析变复杂,所以在代码中尽量避免lach的产生
产生latch的方式: if,else语句中缺少else语句
case语句中缺少default或case描述未完全列举
在组合逻辑中输出变量赋值给自己
Flip-fiop一般由输入,输出,时钟和复位组成。
输入信号在时钟边沿有效,若输入信号在时钟边沿发生变化,则采集时钟沿前一时刻的信号。
复位分同步复位与异步复位,同步复位在产生复位信号后在下一个时钟沿复位,异步复位在产生复位信号后立即复位。