前言
我们都知道 FPGA 是一种高度可编程的集成电路,适用于实现各种数字逻辑功能,而 Verilog HDL是一种广泛使用的硬件描述语言(Hardware Description Language, HDL),主要用于数字电子系统的描述、仿真和综合,以及其他数字系统的逻辑设计。通过使用 Verilog,工程师可以高效地设计和验证 FPGA 电路,从而实现所需的数字系统功能。
这里的 Verilog HDL 和 Verilog 实际上指的是同一种硬件描述语言(Hardware Description Language),即 Verilog。Verilog HDL 是 Verilog 的完整名称,“HDL”代表“Hardware Description Language”,表示这是一种用于描述硬件系统(特别是数字逻辑电路)的语言。
Verilog 语言最初由 Gateway Design Automation 开发,后来被 Cadence Design Systems 收购,并最终成为了一个开放的标准,Verilog 已经被 IEEE 标准化为 IEEE 1364。它是一种更接近编程语言的 HDL,HDL 是硬件描述语言的总称,包括 Verilog 和 VHDL。
一. Verilog 介绍
Verilog HDL是一种硬件描述语言,以文本形式来描述数字系统硬件的结构和行为的语言,用它可以表示逻辑电路图、逻辑表达式,还可以表示数字逻辑系统所完成的逻辑功能。
二. Verilog 优势与特点
1. Verilog 优势
- 语法自由、易学易用
- 适合算法级、门级设计
- 代码简洁
- 发展较快
- Verilog 的语法风格在一定程度上类似于 C 语言,这使得熟悉 C 语言的开发者能够更快地上手 Verilog。
2. Verilog 特点
硬件描述:Verilog 提供了一种描述数字电路的方式,包括电路的结构、行为和数据流。
可综合性:Verilog 代码可以被综合工具转换为实际的硬件电路,如现场可编程门阵列(FPGA)或专用集成电路(ASIC)。
仿真:Verilog 代码可以被仿真工具用来验证电路的功能正确性。
模块化设计:Verilog 支持模块化的设计方法,允许将大型设计分解为较小的、可重用的模块。
并行性:Verilog 语言支持并发执行的概念,使得描述复杂的数字系统变得容易。
混合语言支持:Verilog 可以与另一种流行的 HDL 语言 VHDL 以及其他语言混合使用。
三. Verilog 组成部分
- 模块:Verilog 设计的基本单元是一个模块,每个模块描述了一个独立的功能块。
- 端口:模块之间的连接通过端口来实现,端口可以定义为输入、输出或双向。
- 数据类型:Verilog 支持多种数据类型,包括位向量、整数、实时和位向量数组。
- 连续赋值语句:用于描述组合逻辑电路。
- 过程块:用于描述时序逻辑和控制逻辑,可以包含条件语句、循环等结构。
- 任务和函数:用于封装常用的操作或计算,提高代码的复用性。
四. Verilog 应用场景
- IC 设计:Verilog 用于描述和验证 IC 的功能。
- FPGA 开发:Verilog 用于 FPGA 的设计和配置。
- 嵌入式系统:Verilog 用于嵌入式系统的硬件部分描述。
- 系统级仿真:Verilog 可以用于系统级的仿真,包括软硬件协同仿真。
五. Verilog 具体使用
First. Verilog 编辑器
1. Verilog硬件语言,支持的文本编辑器,请看
- Notepad++ - 一个免费且强大的文本编辑器,支持语法高亮显示。
- VS Code (Visual Studio Code) - 支持多种语言,包括Verilog,并且可以通过扩展增强功能。
- Sublime Text - 提供了高度可定制化的环境,有丰富的插件支持。
- Atom - 一个开源编辑器,有大量的社区插件可供安装。
- Vim 或 Emacs - 对于熟悉命令行界面的用户来说非常强大。
2. 文本编辑器与集成开发环境的区别
(1). 文本编辑器
文本编辑器是用于编写和编辑代码的工具,通常提供基本的文本处理功能。常见的文本编辑器包括:
- Notepad++、
- Visual Studio Code、
- Sublime Text、
等等。
(2). 集成开发环境(IDE)
集成开发环境 (IDE) 是一种集成了多个开发工具的综合性开发平台,专门用于设计FPGA开发的IDE通常包括代码编辑、综合(synthesis)、仿真(simulation)、实现(implementation)、调试(debugging)等功能。常见的 FPGA IDE 包括:
- Intel Quartus Prime、
- Xilinx Vivado、
- Lattice Diamond
等等。
容易搞混乱,别搞混了。
Second. Verilog 文件
1. VS Code
- 这里以VS Code文本编辑器为例,进行开发;
- 打开VS Code,在插件商店搜索 Verilog-HDL/SystemVerilog/Bluespec SystemVerilog 并下载,这样VsCode就可以识别到 Verilog 代码。
2. 新建文件
- 打开所选的文本编辑器后;
- 新建一个空白文件,注意区别文件/文件夹。
3. 保存文件
- 将文件后缀名改为 .v,例如 my_module.v(Verilog文件的后缀为 .v)。
- 确保选择合适的文件夹,保存文件。
4. 编写代码
- 在 Verilog 文件中(后缀名为.v的文件中)输入代码,进行开发。
Third. Verilog 数据类型
Verilog HDL(Hardware Description Language)支持多种数据类型,这些数据类型可以大致分为两大类:物理数据类型和抽象数据类型。这里是一些常见的Verilog数据类型:
1. 物理数据类型
- Wire (
wire
):表示硬件单元之间的物理连线,它不具备存储功能。- Tri (
tri
,tri0
,tri1
,triand
,trior
,trireg
):表示三态逻辑门的输出。- Reg (
reg
):表示寄存器或存储单元,可以存储数据。- Memory (
reg
array):使用寄存器数组来模拟存储器。这些类型主要用于直接映射到硬件电路中的实际组件上。
2. 抽象数据类型
这些类型用于辅助设计和验证过程,通常不直接映射到具体的硬件组件上
- Integer (
integer
):用于表示整数。- Time (
time
):用于表示时间值,如仿真时间。- Real (
real
):用于表示实数。- Parameter (
parameter
):用于定义符号常量。- Event (
event
):用于表示事件。- String (
string
):用于表示字符串。除了上述类型之外,Verilog还支持一些其他的类型,例如:
- Genvar (
genvar
):用于生成循环中的索引。- Enum (
enum
):用于定义枚举类型。- Struct (
struct
):用于定义结构体。- Union (
union
):用于定义联合体。
3. 常用的数据类型
根据资料显示,Verilog HDL共有19种数据类型,其中包括最基本的4种数据类型:
integer
、parameter
、reg
、wire
。除此之外,还有其他如large
、medium
、scalared
、small
、vectored
等类型,但这些并不是经常使用的类型。因此,如果只考虑最基本和常用的数据类型,我们可以总结出以下几种:
- 连线型 (
wire
)- 寄存器型 (
reg
)- 整型 (
integer
)- 时间型 (
time
)- 实型 (
real
)- 参数型 (
parameter
)- 三态逻辑 (
tri
,tri0
,tri1
,triand
,trior
,trireg
)- 数组类型 (
reg
,integer
,time
,real
,realtime
的数组)- 事件 (
event
)- 字符串 (
string
)- 枚举 (
enum
)- 结构体 (
struct
)- 联合 (
union
)- 生成变量 (
genvar
)这里需要注意的是,某些类型如
tri
系列的类型可能不会在所有的Verilog实现中都可用,具体支持哪些类型取决于Verilog的标准版本以及使用的综合工具或仿真器的支持情况。
4. 经常使用的数据类型
(1). wire:用于表示组合逻辑电路中的连线。它没有存储能力,只反映当前时刻的值。
wire out;
assign out = A & B; // 组合逻辑赋值
(2). reg:用于表示寄存器或存储单元。它可以存储值,并且可以在时序逻辑中使用。
reg out;
always @(posedge clk) begin
if (reset)
out <= 0;
else
out <= A & B;
end
(3) integer:用于表示整数变量,可以存储较大的整数值。
integer i;
(4) time:用于表示时间值,例如在仿真中表示延迟。
time delay_time;
(5) real:用于表示实数变量。
real voltage;
(6) genvar:用于循环生成模块时作为索引。
genvar i;
generate for(i=0; i<4; i=i+1) begin : inst
// 生成模块实例
end
endgenerate
Fourth. Verilog 逻辑值
1. 二进制逻辑值
- 1:表示逻辑高电平。
- 0:表示逻辑低电平。
2. 未知值
- x 或 X:表示未知的逻辑值,常用于不确定的状态或未初始化的变量。
- z 或 Z:表示高阻态,通常用于三态门输出或总线的状态。
3. 其它特殊值
- -:有时也用于表示未知值。
- ?:表示未知或未指定的值。
4. 常用整合
- 0逻辑低电平,条件为假
- 1逻辑高电平,条件为真
- z:高阻态,无驱动
- x:未知逻辑电平
5. 使用示例
假设我们想要定义一个简单的组合逻辑电路,该电路接收两个输入信号A
和B
,并输出一个与门的结果out
。
module and_gate(input A, input B, output out);
assign out = A & B; // 使用二进制逻辑值
endmodule
如果我们要处理不确定的状态,我们可以使用x
或X
来表示未知值。
module unknown_logic(input A, input B, output out);
assign out = (A & B) | (A & X) | (X & B); // 使用未知值
endmodule
6. 注意事项
- 在时序逻辑设计中,尽量避免使用
wire
类型的变量来表示需要存储的值。- 当涉及到复杂的逻辑表达式时,合理使用
wire
和reg
可以帮助优化设计。- 对于未知值和高阻态的处理要特别小心,因为它们可能会导致意想不到的行为。
Fifth. Verilog 算数运算符
在Verilog HDL中,算术运算符用于执行基本的数学操作,如加法、减法、乘法和除法。这些运算符对于实现数字电路中的算术功能非常重要。这里是Verilog中的一些常见算术运算符及其使用方法:
1. 加法 (+):用于两个数值的加法操作。
reg [3:0] a = 4'b0011;
reg [3:0] b = 4'b0001;
reg [4:0] sum;
assign sum = a + b; // sum 将等于 4'b0100
2. 减法 (-):用于两个数值的减法操作。
reg [3:0] a = 4'b0011;
reg [3:0] b = 4'b0001;
reg [4:0] diff;
assign diff = a - b; // diff 将等于 4'b0010
3. 乘法 (*):用于两个数值的乘法操作。
reg [3:0] a = 4'b0011;
reg [3:0] b = 4'b0001;
reg [7:0] product;
assign product = a * b; // product 将等于 8'b00000011
4. 除法 (/):用于两个数值的除法操作。注意,整数除法会丢弃小数部分。
reg [3:0] a = 4'b0100;
reg [3:0] b = 4'b0010;
reg [3:0] quotient;
assign quotient = a / b; // quotient 将等于 4'b0010
5. 取模 (%):用于求余数。
reg [3:0] a = 4'b0101;
reg [3:0] b = 4'b0011;
reg [3:0] remainder;
assign remainder = a % b; // remainder 将等于 4'b0000
6. 代码示例
这里使用Verilog算术运算符实现一个简单的例子,展示如何实现一个基本的加法器模块:
module adder_module(input [3:0] a, input [3:0] b, output [4:0] sum);
assign sum = a + b; // 计算 a 和 b 的和
endmodule
Verilog中的算术运算符提供了基本的数学操作,这对于实现数字电路中的算术功能非常重要。在使用这些运算符时,需要注意位宽和溢出等问题。
7. 注意事项
- 位宽:在进行算术运算时,要注意操作数的位宽。如果位宽不匹配,可能需要使用位拼接 (
{}
) 或位扩展 ($signed
或$unsigned
) 来调整位宽。- 溢出:加法和乘法可能导致溢出,特别是在位宽有限的情况下。Verilog 不会自动处理溢出,因此需要程序员自己处理。
- 无符号和有符号运算:Verilog 默认使用无符号运算。如果需要有符号运算,可以使用
$signed
函数来明确指定。- 类型转换:在不同类型的变量之间进行运算时,可能需要显式转换类型。
Verilog中的算术运算符提供了基本的数学操作,这对于实现数字电路中的算术功能非常重要。在使用这些运算符时,需要注意位宽和溢出等问题。