目录
前言
一、Verilog HDL 初始化
二、Verilog 操作符号
1、Verilog 赋值运算符
1、连续赋值符号
2、阻塞赋值符
3、非阻塞赋值符
4、映射赋值符
5、位置赋值
2、Verilog 按位运算符
3、归约运算符
4、算数运算符
5、Verilog 关系运算符
6、Verilog 逻辑运算符
7、Verilog 迭代连接运算符
8、Verilog 移位运算符
9、Verilog 条件运算符
10、Verilog 运算符优先级
参考声明
本文承接前文:Verilog HDL 语法整理 (一)。本文主要介绍 Verilog 的运算符和表达式。
FPGA 内主要对记忆器件(寄存器、BRAM、ROM等)进行初始化,无记忆性的单元(wire 型连线)不用初始化。
1、分布式赋初值
在声明变量时,直接对变量赋值。例 :
reg [15:0] I_DATA=16'ff ;
2、集中式赋初值
使用 initial 块赋初值。initial 块语法:
initial
begin
<代码块>;
end
initial 语句块 仅执行一次,不涉及内部电路功能。故 赋值时使用 阻塞赋值和非阻塞赋值均可。例:
reg [7:0] I_REAL;
reg [7:0] I_IMAG;
integer K ;
initial
begin
for(K=0 ;K<=99 ;K=K+1)
begin
I_REAL <= K;
I_IMAG = K+1;
end
end
仅能用于 线网型(wire)型变量赋值。语法格式:
assign <线网型变量> = <表达式> ;
主要用于组合逻辑,只能对 寄存器型 变量赋值。赋值符 “ = ” 。此符号一般都出现表达组合逻辑的 always 语句块中。always 语句块中的语句顺序执行,阻塞赋值的含义:保证上一条语句执行、赋值完成后才开始下一条语句。例:
always @ (c)
begin
b=c;
a=b;
end
主要用于组合逻辑,只能对 寄存器型 变量赋值。赋值符 “ <= ” 。此符号一般都出现表达时序逻辑的 always 语句块中。always 语句块中的语句顺序执行,非阻塞赋值的含义:上一条语句已经执行但未完成赋值时就开始下一条语句的执行。例:
always @ (posedge I_CLK)
begin
b <= c;
a <= b;
end
映射赋值符号 “ . ” 。此运算符常用于 模块例化时,输入输出端口的连接赋值。例:
ASYNC_FIFO_ENCAP inst_ASYNC_FIFO_ENCAP
(
.I_Rst_n (I_Rst_n),
.I_WR_CLK (I_WR_CLK),
.I_RD_CLK (I_RD_CLK),
.I_DATA (I_DATA),
.I_VAL (I_VAL),
.O_DATA (O_DATA),
.O_VAL (O_VAL),
.O_FULL (O_FULL)
);
功能与映射赋值相同。一般用的很少,上例可以写为:
ASYNC_FIFO_ENCAP inst_ASYNC_FIFO_ENCAP
(
I_Rst_n,
I_WR_CLK,
I_RD_CLK,
I_DATA,
I_VAL,
O_DATA,
O_VAL,
O_FULL
);
【注】位置赋值 和 映射赋值 不可混合使用。
1、~
按位取反运算,单目运算符。对操作数的每一位进行取反。例:
wire [7:0] A,B;
assign A = 8'b0000_1111;
assign B = ~A; //B: 1111_0000
2、&
按位 与 运算,双目运算符。对参与运算的两个操作数,按位 与 运算。例:
wire [7:0] A,B,C;
assign A = 8'b0000_1111;
assign B = ~A; //B: 1111_0000
assign C = A & B; //C: 0000_0000
3、|
按位 或 运算,双目运算符。对参与运算的两个操作数,按位 或 运算。例:
wire [7:0] A,B,C;
assign A = 8'b0000_1111;
assign B = ~A; //B: 1111_0000
assign C = A | B; //C: 1111_1111
4、^
按位 异或 运算,双目运算符。对参与运算的两个操作数,按位 异或 运算。例:
wire [7:0] A,B,C;
assign A = 8'b0000_1111;
assign B = ~A; //B: 1111_0000
assign C = A ^ B; //C: 1111_1111
5、^~
按位 异或非(同或) 运算,双目运算符。对参与运算的两个操作数,按位 异或非(同或) 运算。例:
wire [7:0] A,B,C;
assign A = 8'b0000_1111;
assign B = ~A; //B: 1111_0000
assign C = A ^~ B; //C: 0000_0000
规约运算符 都是单目运算符。操作数有一定位宽。运算结果均为1bit。
1、&
规约 与 运算符。对操作数的 所有 bit 作逻辑与操作。例:
wire [7:0] A;
assign A = 8'b0000_1111;
assign B = &A; //B: 0
2、~&
规约 与非 运算符。对操作数的 所有 bit 先作 规约与 操作,然后对结果取反。例:
wire [7:0] A;
assign A = 8'b0000_1111;
assign B = ~&A; //B: 1
3、|
规约 或 运算符。对操作数的 所有 bit 作逻辑或操作。例:
wire [7:0] A;
assign A = 8'b0000_1111;
assign B = |A; //B: 1
4、~|
规约 或非 运算符。对操作数的 所有 bit 先作 规约或 操作,然后对结果取反。例:
wire [7:0] A;
assign A = 8'b0000_1111;
assign B = ~|A; //B: 0
5、^
规约 异或 运算符。对操作数的 所有 bit 作逻辑异或操作。例:
wire [7:0] A;
assign A = 8'b0000_1111;
assign B = ^A; //B: 0
6、~^
规约 异或非 运算符。对操作数的 所有 bit 作逻辑异或非操作 (注:只有操作数位宽为 偶数时,异或非 运算和 同或 运算等价)。对操作数的 所有 bit 先作 规约异或 操作,然后对结果取反。例:
wire [7:0] A;
wire [2:0] C;
assign A = 8'b0000_1111;
assign C = 3'b000;
assign B = ~^A; //B: 1
assign D = ~^C; //D: 1
1、+
加法运算符,双目运算符。例:
wire [2:0] A = 3'b011;
wire [2:0] B = 3'b011;
wire [2:0] C = 3'b111;
assign D = A + B ;// D:6
assign E = A + C ;// E:2 溢出
2、-
减法运算符,双目运算符。例:
wire [2:0] A = 3'b011;
wire [2:0] B = 3'b011;
wire [2:0] C = 3'b111;
assign D = A - B ;// D:0
assign E = A - C ;// E:4 溢出
3、*
乘法运算符,双目运算符。例:
wire [2:0] A = 3'b001;
wire [2:0] B = 3'b011;
wire [2:0] C = 3'b111;
assign D = A * B ;// D:3
assign E = B * C ;// E:5 溢出
4、/
除法运算符,双目运算符。例:
wire [2:0] A = 3'b001;
wire [2:0] B = 3'b011;
wire [2:0] C = 3'b111;
assign D = B / A ;// D:3
5、%
求余运算符,双目运算符。例:
wire [2:0] A = 3'b001;
wire [2:0] B = 3'b011;
wire [2:0] C = 3'b111;
assign D = B % A ;// D:0
6、**
乘方运算符,双目运算符。例:
wire [2:0] A = 3'b001;
wire [2:0] B = 3'b011;
wire [2:0] C = 3'b111;
assign D = B ** A ;// D:3
【注】,不建议直接用 乘方运算符号 实现乘方运算,可用相关 IP核。
主要用作 条件判断 通用语法格式:
<表达式 1> <关系运算符> <表达式 2>
主要的 关系运算符:
== //判断表达式相等
=== //判断表达式全等(包含 X、Z 状态,仅用于 仿真)
!= //判断表达式不等
!== //判断表达式不全等(包含 X、Z 状态,仅用于 仿真)
< //左表达式 小于 右表达式
> //左表达式 大于 右表达式
<= //左表达式 小于等于 右表达式
>= //左表达式 大于等于 右表达式
主要用于 多个关系表达式的连接。可实现较复杂的判断条件。语法格式:
<逻辑运算符> <关系表达式>
或
<关系表达式> <逻辑运算符> <关系表达式>
主要有以下几种 逻辑运算符:
! //单目运算符,对右边表达式 取反
&& //左右表达式的结果 作 逻辑与运算
|| //左右表达式的结果 作 逻辑或运算
运算符:“{}”
1、连接功能
wire [2:0] A = 3'b001;
wire [2:0] B = 3'b011;
wire [2:0] C = 3'b111;
assign D = {A,B,C};//D:001_011_111
2、迭代功能
wire [2:0] A = 3'b001;
wire [2:0] B = 3'b011;
wire [2:0] C = 3'b111;
assign D = {2{C}};//D:111_111
3、混合功能
wire [2:0] A = 3'b001;
wire [2:0] B = 3'b011;
wire [2:0] C = 3'b111;
assign D = { {2{C}} , A , B };//D:111_111_001_011
assign E = { {2{ A ,B }} , C};//E:001_011_001_011_111
运算符:
<< //(无符号)左移运算
>> //(无符号)右移运算
<<< //(有符号)左移运算
>>> //(有符号)右移运算
【注】无符号移位:移位时 空缺的位 用 1'b0 补上。
有符号左移与无符号左移相同,右边空缺位用 1'b0 补上。有符号右移,左边空缺位用 符号位 补上。
移位算法:
<变量名> <移位运算符> <移位个数>
例:
wire [2:0] A = 3'b001; wire [2:0] B = 3'b011; wire signed [2:0] C = 3'b111; assign D = A >> 1;//D:000 assign E = C >> 1;//E:011 assign F = C >>> 1;//F:111 assign G = C <<< 1;//G:110
移位运算 可用 连接运算符 实现。
基本语法:
assign <变量名> = <表达式> ? <表达式为真选择此式> :<表达式为假选择此式>
多用 小括号。不要依赖运算本身的优先级。下表操作的优先级,由高到低。
! ~ + - (负号) |
* / % |
+ -(减号) |
<< >> |
< <= > >= |
== != === !== |
& ~& |
^ ^~ |
| ~| |
&& |
|| |
? : |
【1】夏宇闻. Verilog 数字系统设计教程 第二版.
【2】狄超. FPGA之道.
【3】IEEE Standard for Verilog Hardware Description Language 1364-2005.
掌握了基本的Verilog语法,不去实战练习的话很难有大的突破。牛客网可以为大家提供一个免费的刷题练习的平台。非常推荐大家使用。
链接如下:牛客网-Verilog专项https://www.nowcoder.com/link/pc_csdncpt_zls_verilog这个里面有很多代码题目练习,对于新手来说可以快速掌握Verilog编程的基本语法,对于老手来说也可以巩固自己的编程能力。不用付费免费试用哦。基本是每个即将找工作的人必备的刷题网站。快行动起来吧!