0%

FPGA-verilog语法

硬件描述语言(Hardware Description Languages,HDL)

基本设计单元:模块

image-20240314204738613

1.数值表示

1
2
3
4
5
6
7
8
9
10
11
//数值信号
0;//低电平
1;//高电平
x;//未定电平
z;//高阻抗
//数值表示
//位宽'进制数字(未指定位宽默认系统位宽(32bit,64bit),未指定进制默认十进制)
8'b11001010; //8bit二进制
5'd23; //5bit十进制
'o7460; //默认bit八进制
16'hf68a; //16bit16进制

2.数据(变量)类型

(1)线网型

1
2
3
4
5
//注:矢量表示即[range]默认[MSB:LSB]即[高位:低位]

//线网型
wire wire1;//总线型(默认线网类型),默认1bit
wire [7:0]wire2;//8未矢量线网变量

(2)寄存器型

1
2
3
4
5
6
7
8
9
10
11
12
13
//寄存器型
//无符号整数变量,可以选择不同的位宽(标量或矢量)
reg reg1;//默认1bit寄存器
reg [7:0]reg2,reg3;//两个8位寄存器
reg [7:0]reg_array[4:0]//深度为5的8位寄存器
//无符号整数变量,64位宽(Verilog-XL仿真工具用)
time time1;
//有符号整数变量,32位宽,2的补码的算术运算。
integer integer1;
//双精度有符号的浮点数,用法与integer相同。
real real1;
//与real内容一致,可用作实数仿真时间的保存与处理
realtime realtime1;

3.操作符

(1)单目操作

单目操作符对数字的二进制形式进行逐位操作得到单比特结果

image-20240315160838546

(2)算术操作

  1. 将负数赋值给 reg 或其他无符号变量使用二进制补码;
  2. 如果操作数的某一位是x或z ,则结果为x;
  3. 在整数除法中,余数舍弃;
  4. 模运算中使用第一个操作数的符号。

(3)逻辑操作

  • 逻辑与&&
  • 逻辑或||
  • 逻辑非!

其得到的结果为逻辑数值0,1,x。分别表示假,真,未定。对于非零操作数,等同于逻辑真,为零的操作数,等同于逻辑假。操作数中任意一位为x,z,其等同于逻辑不确定x。

image-20240315161335540

(4)关系操作

image-20240315161750991

(5)等价操作

(6)移位操作

(7)条件操作

< condition >?< true >:< false >;

(8)拼接操作

1
2
3
4
5
6
7
reg a,b;
reg [6:0]out1,out2;
a = 1;
b = 0;
//拼接操作符{}
out1 = {b,{3{a,b}}};//0101010
out2 = {b,a,b,a,b,a,b};//0101010

注:操作符优先级

image-20240315161633471

4.赋值方式

(1)连续赋值

1
2
3
4
5
6
//显式连续赋值:
net_type [size] net_name;
assign (drive strength) #(delay) net_name = expression;
//其中(驱动强度) #[延迟] 赋值目标 = 赋值表达式;
//隐式连续赋值:
net_type (drive strength) [size] #(delay) net_name = expression;
  • 连续赋值通过关键字”assign”声明,其中,net_name必须是一个标量或线网型向量,不可为寄存器型
  • assign赋值可以视为电路中左侧赋值目标与右侧赋值表达式直接相连,左侧赋值目标实时随右侧赋值表达式变化而变化(即连续赋值语句总处于激活状态)。故一个被连续赋值后的赋值目标不可被再次连续赋值。(如果同一赋值目标被两次连续赋值,可以认为两个赋值表达式在电路中直接相连,可能会引发无法预料的错误)

(2)过程赋值

  • 过程赋值语句的左值可以是以下类型之一:

    • ​ reg、整形数、实型数、时间寄存器变量或存储器单元
    • 上述各种类型的位选(例如:addr[3])
    • 上述各种类型的域选(例如:addr[31:16])
    • 上面三种类型的拼接
  • 过程赋值语句只能在initial或always语句内进行赋值,只能对变量数据类型赋值,同时initial和always中只能使用过程赋值语句。

  • 阻塞赋值 =

阻塞赋值语句顺序执行,变量赋值在语句执行后实现改变,语句执行一次后不会持续执行,直到下一次进行改变。

1
2
3
4
5
6
7
8
9
10
11
12
//begin...end为一个块语句
//阻塞赋值
reg [3:0]a,b,c;

initial begin
a = 4'd1;
b = 4'd2;
c = 4'd4;
//阻塞赋值语句
b = a;//4'd1
c = b;//4'd1
end
  • 非阻塞赋值 <=

同一块语句中,非阻塞赋值语句在块结束时并行执行,同时进行赋值。

1
2
3
4
5
6
7
8
9
10
11
//非阻塞赋值
reg [3:0]a,b,c;

initial begin
a = 4'd1;
b = 4'd2;
c = 4'd4;
//非阻塞赋值语句
b <= a;//4'd1
c <= b;//4'd2
end

所以非阻塞赋值可以实现如下操作:

1
2
3
4
5
6
7
always @(posedge clk) begin
    a <= b ;
end
 
always @(posedge clk) begin
    b <= a;
end

2 个 always 块中语句并行执行,赋值操作右端操作数使用的是上一个时钟周期的旧值,达到交换寄存器值的目的。