项目需要做什么,了解系统的功能,如果是大型的项目还会划分模块
通过使用verilog、VHDL、成熟的IP核或者通过画原理图的方式进行逻辑输入设计
当逻辑输入设计完成后需要对其进行验证,该部分由软件部分进行验证,如果逻辑输入有问题需要检查语法错误或则重新设计设计输入
当分析和综合通过后应该进行功能性验证,针对项目设计定义的功能使用设计的逻辑输入验证其功能能否实现,一般的做法都是通过功能仿真的方式进行验证,比如软件逻辑分析仪,modelsim、vivado等软件自带的仿真工具进行仿真验证
功能仿真也称为行为仿真,主旨在于验证电路的功能是否符合设计要求,其特点是不考虑电路门延迟与线延迟,主要是验证电路与理想情况是否一致。也可以叫做RTL仿真(test bench)
当我们的IO可以开始分配了我们首先需要分配IO,如果当前还没到IO分配的时候我们可以将IO分配放在最后,当IO分配完成后我们就可以通过软件进行布局布线,在芯片内部生成芯片电路
时序仿真也称为布局布线后仿真,是指电路已经映射到特定的工艺环境以后,综合考虑电路的路径延迟与门延迟的影响,验证电路能否在一定时序条件下满足设计构想的过程,能较好地反映芯片的实际工作情况,当时序仿真不通过的时候可能还会设计到时序约束的一个过程(在比较复杂的设计中也需要用到);
如果在布局布线时未进行IO分配在该步骤进行IO分配并生成BIT流文件
时序通过了后需要通过硬件进行验证也就是最后一步的实物验证
当系统出现问题运行不正常我们可以通过外部硬件示波器或者逻辑分析仪进行实际引脚信号抓取分析
二选一多路器,两个输入IO(a,b)可以是高电平可以是低电平,一个sel选择信号
当sel为0时候输出按键1的状态
当sel为1时候输出按键2的状态
选择自己使用的芯片(我这里采用的是小梅哥的高云FPGA开发板)
新建一个verilog文件
module mux_2_1(
input wire in1, // 输入端口1
input wire in2, // 输入端口2
input wire sel, // 输入通道的选择
output wire led // 输出led
);
// assign led = (sel == 1'b0) ? in1 : in2; // 第一种方式直接使用三目运算符
// 第二种方式是使用always的*触发方法ifelse判断
reg out;
always @(*) begin
if(sel)
out <= in2;
else
out <= in1;
end
assign led = out;
endmodule
这里代码我已经验证了所以没有语法错误,直接进行综合
当没有语法错误时表示代码正常然后我们可以运行工具中的RTL Desgin Viewer查看原理图网表;
这里我们需要将我们的源代码设置为顶层文件(这里引用一下小梅哥的图),然后我们可以看到该源码所占用的资源情况
然后我们创建一个test beach测试文件
代码如下
`timescale 1ns/1ps
module mux_2_1_tb();
reg In1;
reg In2;
reg Sel;
wire Led;
// 创建模块实例并赋值参数
mux_2_1 Mux_2_1(
.in1(In1),
.in2(In2),
.sel(Sel),
.led(Led)
);
// 初始化运行 测试每个真值表上对应的参数设定
initial begin
In1 = 0;In2 = 0;Sel = 0;
#100;
In1 = 0;In2 = 0;Sel = 1;
#100;
In1 = 0;In2 = 1;Sel = 0;
#100;
In1 = 0;In2 = 1;Sel = 1;
#100;
In1 = 1;In2 = 0;Sel = 0;
#100;
In1 = 1;In2 = 0;Sel = 1;
#100;
In1 = 1;In2 = 1;Sel = 0;
#100;
In1 = 1;In2 = 1;Sel = 1;
#100;
end
endmodule
点击综合和布线,验证有无逻辑错误
然后我们打开modsim软件创建工程
添加我们的两个源码文件并编译
进入 Add Simulation Configuration 页面,我们在 Design 标签页面中选择work 库中的“ mux_2_1_tb”模块作为设计顶层,点击复制模块名作为仿真配置“ Simulation Configuration Name”的命名,确保命名保持一致。在复杂的工程设计中,我们可以设计多个不同的仿真配置顶层对工程进行仿真测试。
点击“ Optimization Options…”, 在“ Optimization Options…” 设置栏中选择“ Apply full visibility to all modules(full debug module)”,点击“ OK”
配置元件库(这一步的操作需要在modsim中已经添加了高云fpga的仿真库后操),点击“ libraries” 设置栏, 在“ Search libraries(-L)” 一栏中点击“ Add…”添加我们新建的高云的库文件“ gw5a”,在“ Search Libraries First(-Lf)”同样选择库文件“ gw5a”,最后点击“ Save”保存设置;
然后双击我们的仿真文件进入仿真界面
然后我们选中模块右击后点击Add Wave放到显示波形中
添加好波形后回到“ Library”栏,右键单击“ work”点击 Update 将
“ mux_2_1_tb”文件更新在“ work”栏,如下所示
然后我们点击状态栏中的运行即可捕捉到波形,然后右击Zoom Full可以快速查看波形,在这一步我们可以验证我们的波形是否是我们需要的效果;
下一步我们可以将modsim的工程和波形文件保存到项目project路径下;
然后点击波形界面一下再点击这个按钮选择保存波形路径
下次还需打开工程只需要点击该目录下的.mpf文件即可
到这里功能仿真也就是RTL仿真就结束了,下一步我们需要分配我们程序中引脚并完成布局布线;
首先我们需要确认我们输入和输出接的引脚,这里小梅哥的板子提供了excel表格,下面是我使用到的资源;
然后我们回到软件中进行引脚约束
保存后进行点击布线查看是否存在错误
最终生成文件
//Copyright (C)2014-2023 Gowin Semiconductor Corporation.
//All rights reserved.
//File Title: Physical Constraints file
//Tool Version: V1.9.9 (64-bit)
//Part Number: GW5A-LV25UG324C2/I1
//Device: GW5A-25
//Device Version: A
//Created Time: Mon 12 25 15:47:02 2023
IO_LOC "led" D14; // 指定“led”io位置为D14
IO_PORT "led" PULL_MODE=NONE DRIVE=8 BANK_VCCIO=3.3; // 无上拉 驱动等级8 io电压3.3v
IO_LOC "sel" C15;
IO_PORT "sel" PULL_MODE=NONE BANK_VCCIO=3.3;
IO_LOC "in2" A15;
IO_PORT "in2" PULL_MODE=NONE BANK_VCCIO=3.3;
IO_LOC "in1" B16;
IO_PORT "in1" PULL_MODE=NONE BANK_VCCIO=3.3;
在仿真章节的代码中其实有涉及到时序相关的代码,在那一章节就可以观察时序相关的需求,例如本设计的需求有三个输入,分别是key1、key2以及sel,我们要实现的功能便是根据这三个信号的输入状态来输出led,那当我们三个输入信号发生后多久led会产生变化,这就是时序,当我们的需求是要在10ms内反应操作,那我们就需要观察输入信号发生变化时输入信号离输出信号产生的间隙是多长如下图,这里的设计没有复杂的运算以及复杂的判断电路类似直接导通所以没有延时产生(实际不会如此,很难有绝对)
如果仿真产生的延时达不到我们的需求我们就需要进行调整修改,而且实际的IO输出和仿真的效果往往也会有不同,例如这里的输入是按键,那按键抖动时波形的状态我们就可以通过示波器或则硬件逻辑分析仪进行时序分析这样会更加准确一些;
需要注意在烧录验证之前,我们需要在高云软件中配置硬件默认状态,高云编译器默认IO上拉我们需要手动更改为接地
默认烧录是烧录到sram也就是掉电后程序就不在了,如果重启后直接开始运行需要设置未固化到flash中如下图2设置
然后我们就可以在板子上验证我们设计的功能了;