本文的主要内容:(1)以二选一数据选择器为例一步一步操作总结FPGA详细的开发流程
(2)总结了Verilog语法中的模块结构
(3)总结了Verilog语法中的数据类型、变量、常量
1.创建合理的工程目录
良好的文件夹设置以及工程管理是学好FPGA设计的基础,在学习之初就应建立良好的习惯。因此首先在新建的工程文件夹下面,分别建立如图下图所示的子文件夹。
文件夹 | 功能 |
---|---|
prj | 为工程文件存放目录 |
rtl | 为verilog可综合代码 |
img | 为设计相关图片存放目录(主要为了方便后期写文档) |
doc | 为设计相关文档存放目录 |
testbench | 为对应的testbench存放目录 |
prj文件夹下创建ipcore文件夹 | 存放quartus ii中生成的ip核文件 |
2.创建Quartus Prime工程
2.1 打开quartusll软件,创建工程
2.2 设置工程的路径、工程名字及顶层模块的名字
工程的路径中不可出现中文字符,工程名字也不可出现中文名字
2.3 添加文件,如果没有可以直接点Next
2.4 选择FPGA的型号
引脚个数和速度等级进而快速选择出你自己使用的FPGA具体的型号
2.5.设置使用的仿真工具和语言
2.6生成总结报告,工程创建完成
3编写HDL描述文件
(1)新建Verilog文件并在其上出描述功能的语句:
(2)编写代码
(3)将写好的文件保存在rtl文件夹中
(4)对写好的代码进行编译检查语法错误快捷键Ctrl+K 或者点击图标按钮
如果出现语法错误,需对代码进行修改并进行保存之后再进行编译。
解析在代码中部分Verilog语法
3.1 Verilog语法_模块的结构
Verilog的基本设计单元是“模块”。一个模块是由两部分组成的
。一部分描述接口,另一部分描述逻辑功能。
Verilog结构位于在module和endmodule声明语句之间,每个Verilog程序主要包括四部分:端口定义、I/O说明、内部信号定义和功能定义。
3.1.1 模块端口定义
模块的端口声明了模块的输入输出口,格式如下:
module 模块名(端口1,端口2:,…);
模块的端口表示的是模块的输入还是输出口名,也就是说它与别的模块联系端口的标识。
3.1.2 I/O说明格式
输入口
input [信号位宽-1:0] 端口名1
输出口
output [信号位宽-1:0] 端口名1
输入/输出口
inout [信号位宽-1:0] 端口名1
3.1.3 内部信号说明
在模块内用到的与端口有关的wire和reg类型变量声明
reg [width-1 : 0] R变量1,R变量2…;
wire [width-1 : 0] W变量1,W变量2…;
3.1.4 功能定义
模块中最重要的部分是逻辑功能定义部分。有3种方法可在模块中产生逻辑
**1)用"assign"**声明语句
如:assign a=b&c;
描述了一个与门
assign语句常用于描述组合逻辑电路
2)用实例元件
如: and #2 u1(q,a,b)
表示在设计中用到了一个与门,名字为u1,输入端口为a,b.输出为q.
3)用always块
如:always@(posedge sclk or necedge clr)
begin
if(clr) q<=0;
else q<=d;
end
生成了一个带有异步清零的D触发器。
always块既可以描述组合逻辑也可以描述时序逻辑。
3.1.5小结
3.2 Verilog语法_数据类型、常量、变量
Verilog HDL一共有19种数据类型,我们最常用的有四种:分别是reg型、wire型、integer型和parame型。
3.2.1 常量
在程序运行过程中,其值不能被改变的量为常量。
1.数字
(1)整数在Verilog HDL中,整数常量即整常量。
表达方式 | 含义 |
---|---|
1<位宽>’<进制><数字> | 这是最全面的描述方式 |
2.’<进制><数字> | 数字的位宽采用缺省位宽方式(此时位宽由具体的机器系统决定,至少32位) |
<数字> | 采用缺省进制(默认十进制) |
1'd1 //位宽为1的数的十进制表示
(2).x和z值
X | Z |
---|---|
X代表不定值 | Z代表高阻,Z还有一种表达方式? |
4'b10x0 位宽为4的二进制数,从低位数第二位为不定值
4'b101z 位宽为4的二进制数,从低位数为高阻值
4'b101? 位宽为4的二进制数,从低位数为高阻值
(3)负数
一个数字可以被定义为负数,只需要在位宽表达式前加一个建好,减号必须写在数字表达式的前面
-8'd5 //这个表达式代表5的补数
2.参数型(parameter)
在Verilog中用parameter来定义常量,即用parameter来定义一个标识符代表一个常量,称为符号常量。
格式如下:
parameter 参数名1=表达式,参数2=表达式…;
parameter msb=7; //定义参数msb为7
3.2.2 变量
1.wire变量
wire是最常用的线网络变量。我们可以将wire直接理解为连线。因此wire型变量不能够保存值也不能对其进行赋值。
wire主要起信号连接作用,用以构成信号的传递或者形成组合逻辑。
wire型变量的定义格式如下:
wire [n-1,0] 变量名;
wire a //定义了一个1位的wire型数据a
2.reg变量
寄存器是数据储存单元的抽象。寄存器数据类型的关键字是reg。
reg型数据常用来表示“always”模块内的指定信号,常代表触发器。通常在设计中要由“always”模块通过使用行为描述语句来表示逻辑关系。在always块内赋值的每一个信号都必须定义为reg型
reg型变量的定义格式如下:
reg [n-1,0] 变量名;
reg [3:0] regb //定义了一个4位的名为regb的reg型数据
3.memory型
Verilog HDL通过对reg型变量量建立数组来对寄存器建模,可以描述RAM型存储器、ROM存储器和reg文件。
memory型数据格式如下:
reg [n-1:0] 存储器名词 [m-1:0];
reg [n-1:0] 定义了存储器的位宽。
[m-1:0] 定义了存储器的深度。
reg [n-1:0] rega //一个n位的寄存器
reg mema [n-1:0] // 一个位宽为1,深度为n的存储器
4. 编写测试脚本并进行功能仿真(testbench)
在首次使用quartusll与modelsim进行联合仿真时,通常需要以下五部才可以实现仿真
4.1 设置quartusll与modelsim关联路径
1.Tools>>options
2. options>>EDA Tool options下找到modelsim-alter的安装路径,并选择到win32aloem文件夹。
注意:我在设置quartusll13.0时直接选择win32aloem就添加关联路径成功了。而我在设置quartusll13.1的关联路径时必须在win32aloem后面加一个斜杠\关联路径才可以设置成功。
4.2 设置仿真激励testbench
1.添加Verilog文件
2.编写testbench代码
3. 将写好的文件保存在testbench文件夹中
4.对代码进行编译检查语法错误快捷键Ctrl+K 或者点击图标按钮
如果出现语法错误,需对代码进行修改并进行保存之后再进行编译。
4.3 设置nativelink
1.assignments>>settings
按图中的顺序操作
点击new
(1).添加测试文件
(2)命名testbench的名称
(3)按下add,加测试文件加到testbench中
4.4运行仿真
按下图进行操作
得到仿真结果
5.在Quartus Prime中执行布局布线
执行下图操作
6.进行时序仿真
执行下图操作
6.1 Nativelink Error警告
在此处你可能会遇到下图的错误警告
此时需要把modelsim-alter关闭后重新启动仿真。得到时序仿真的结果
7.分配引脚并编译得到FPGA配置文件
1.执行下图操作或者使用快捷键Ctrl+Shift+N进行引脚配置
2. 根据具体设计选择各个端口对应的引脚与电平标准
3. 再对文件进行布局布线操作
8.配置FPGA并运行
1.执行下图操作
2.此处采用USB-Blaster对FPGA进行配置
2.1 执行下图操作
2.2 选择USB-Blaster
2.3 添加.sof文件.sof文件在output_files文件夹中
2.4 运行.sof文件
至此一个完整的FPGA开发流程完毕。
参考文献:1. 夏宇闻. Verilog数字系统设计教程
2.小梅哥开发板套件资料