FPGA/verilog 学习笔记(2)—— Verilog基础语法
文章目录
Verilog基础语法
一、基础知识
1. 逻辑值
逻辑值 | 代表 | 对应电路 |
---|---|---|
0 | 低电平 | GND |
1 | 高电平 | VCC |
X | 未知(高电平或低电平) | 可能是VCC或GND |
Z | 高阻态 | 悬空状态,外部没有激励信号 |
2. 数字进制格式
-
Verilog数字进制格式包括二进制、八进制、十进制、十六进制
-
进制示例
进制 写法 代表 二进制 4'b0101
4位二进制数0101(B) 十进制 4'd2
4位十进制数2(D),二进制0010(B) 十六进制 4'ha
4位十六进制数a(H),二进制1010(B) -
缺省是32位十进制表示:直接写
100
,Verilog理解为32'd100
-
二进制数每4位数可以加下划线增加可读性:
16'b1001_1010_1010_1001 = 16'h9AA9
3. 标识符
-
用于定义模块名、端口名、信号名
-
标识的第一位必须是字母或下划线
-
大小写敏感
-
可是任意一组以下符号的组合
- 数字(不能做第一位)
- 字母
-
$
符号(不能做第一位) -
_
下划线
-
良好的命名规范
- 不要大小写混用
- 普通内部信号最好全部小写
- 信号名应当简洁、清晰、易懂
-
示例:
-
用有意义的词:
sum
、cpu_addr
等 -
用下线区分词:
cpu_addr
-
采用一些前缀后缀:
clk_50
、clk_cpu
-
二、数据类型
-
三种基本数据类型
-
变量数据类型(共5种):reg、integer、time、real、realtime…
-
线网数据类型(共11种):wire、tiror、trireg、tri、wand、tril、wor…
-
参数数据类型:parameter…
-
-
Verilog允许定义各个类型的数组
-
真正在数字电路中起作用的是寄存器类型和线网类型(可以映射到实际的数字电路)
1. reg和wire类型
(1)reg寄存器类型
-
寄存器表示一个抽象的数据存储单元,通过赋值语句可以改变寄存器存储的值
-
关键字:
reg
reg[31:0] delay_cnt; //delay_cnt是一个位宽32位的寄存器,注意高位写前面
reg key_reg; //key_reg是一个位宽为1的寄存器
-
默认初始值:
X
-
reg类型的数据只能在
always
和initial
块中被赋值 -
reg类型的物理意义:
- 如果此过程语句描述的是时序逻辑,即
always
语句带时钟信号,则此寄存器对应触发器 - 如果此过程语句描述的是组合逻辑,即
always
语句不带时钟信号,则此寄存器对应硬件连线
- 如果此过程语句描述的是时序逻辑,即
(2)wire线网类型
-
线网数据表示结构实体(如门)之间的物理连线
-
关键字:
wire
、tri
,常用wire
型
wire key_flag; //1位位宽
wire [1:0]my_flag; //2位位宽
-
线网的数据不能存储值,它的值是由驱动它的元件决定的;如果没有驱动原件连接到线网类型变量上,则此变量是高阻的,即值为:
z
-
可以驱动线网类型变量的元件
- 门
- 连续的赋值语句
- assign语句
(3)reg和wire的区别
- 类型区别
- reg是一种变量类型(和integer、time类型并列)
- wire是一种线网类型(和wand、tir类型并列)
- 赋值
- reg只能在initial和always块中赋值
- wire只能通过连续赋值语句assign或通过模块输入输出端口赋值
- 初始值
- reg初始值为
x
(未知) - wire初始值为
z
(高阻)
- reg初始值为
- 强度值
- reg不能被赋予强度值
- wire可以被赋予强度值
2. integer类型
-
整形变量包含一个整数值,可以作为普通变量使用,通常用于高层次行为建模
-
支持有符号数,算数运算结果以2的补码表示
-
integer数至少有32位,具体实现时可以提供更多位
-
定义
-
格式
integer a1,a2,a3..,an[msb:lsb]
-
示例
integer a,b,c; //3个整型变量 integer d[3:6]; //1个整型变量数组
-
直接定义的
interger a
,a也可以当作数组访问。如a[6]
之类的访问是合法的
-
-
整型和位向量的转换
//整型->位向量
reg [31:0] sel_reg;
integer sel_int;
sel_reg = sel_int;
//位向量->整型
integer j;
reg[3:0] bcq;
j = 6; //j = 32'b0000...0110
bcq = j; //bcq的值为4'b0110
bcq = 4‘0101;
j = bcq; //j = 32'b0000...0101
j = -6; //j = 32'b1111...11010
bcq = j; //bcq = 4'b1010
- 转换赋值总是从最右边的位开始,到最左边的位结束,多余的位被截断
3. parameter类型
-
参数其实就是一个常量
-
关键字:
parameter
-
可以一次定义多个参数,之间用
,
分隔 -
每个参数定义的右边必须是一个常量表达式
-
常见用途
- 定义状态机的状态
- 定义数据位宽(比如
wire [len:0] flag;
这里的len
就可以定义位成参数变量,方便修改) - 定义延时的大小
-
采用标识符来代表一个常量可以提升程序的可维护性和可读性
-
在模块调用时,可以用参数传递来改变被调用模块中已定义的参数
三、运算符
1. 运算符优先级
2. 算术运算符
- 注意
a/b
会截断舍去小数
3. 关系运算符
4. 逻辑运算符
5. 条件运算符
result = (a>=b)?a:b;
6. 位运算符
- 如果位宽不一致,会先给短的数据高位补零,使二者位宽一致后再运算
7. 移位运算符
-
都是用0补移出来的空位
-
左移时,位宽增加;右移时,位宽不变
-
4'b1001 << 2 == 6'b100100
为真4'b1001 >> 1 == 4'b0100
为真
8. 位拼接运算符
c = {a,b[3:0]}; //拼接a和b的低四位作为c信号,a的部分在高位,b的部分在低位
上一篇: sqlserver表结构查询语句