当前位置: 首页 > news >正文

FPGA开发流程

FPGA开发流程

    • 前言
    • 需求分析
    • 模块设计
    • 工程搭建(Vivado)
    • 功能仿真(Modelsim)
    • 生成下载文件
    • 上板验证
    • Flash固化

前言

本文是以“流水灯设计”进行FPGA开发流程讲解。需求如下:

使开发板上的4个LED灯顺序点亮并熄灭,循环往复产生流水灯的效果,流水间隔时间为0.5s。

需求分析

开发板上LED灯硬件连接的示意图如下图所示,当FPGA输出低电平时,LED灯点亮;输出高电平时,LED灯熄灭。

硬件实物图如下图所示:

在这里插入图片描述

FPGA引脚分配关系如下表所示:

引脚名称IO方向(相对于FPGA)电平标准(IOSTANDARD)引脚位置(PACKAGE_PIN)备注
led[0]OutputLVCOMS33F19
led[1]OutputLVCOMS33E21
led[2]OutputLVCOMS33D20
led[3]OutputLVCOMS33C20

模块设计

该需求功能是4个 LED 灯实现流水灯的效果,因此给模块命名为 flow_led。

两个灯流水的间隔时间为 0.5s,间隔时间的控制需要通过计数器来实现,即通过计数器来实现计时的功能,因此本次实验需要用到系统时钟;

除此之外,系统复位在 FPGA 系统中也是必不可少的,当程序出现跑飞等异常情况时,可以使程序恢复至默认状态;

由以上分析可知,本次实验需要2个输入的端口,分别为系统时钟和系统复位,输出为 4位的 LED 端口,模块框图如下图所示:

在这里插入图片描述

模块端口与功能描述如下表所示:

信号名位宽方向端口说明
sys_clk1输入系统时钟,50MHz
sys_rstn1输入系统复位按键,低电平有效
led4输出LED,低电平有效

前面需求分析过硬件设计部分,当IO输出低电平0时,点亮LED灯;当IO输出高电平1时,LED灯熄灭,因此要想控制LED实现流水灯效果,第一次的时候给led端口赋值4‘b1110;等待0.5s后,给led端口赋值4’b1101;等待0.5s后,给led端口赋值4’b1011;等待0.5s后,给led端口赋值4’b0111;后面依次类推,4个LED即可实现流水的效果。


LED 灯流水的间隔为 0.5s,因此接下来还需要做一个 0.5s 的延时,延时的功能可以通过计数器实现,每当计数器计时到 0.5s 后,切换一次 LED 灯的显示状态即可。当计时完成后,开始控制 LED 灯的状态。对于流水的功能非常适合移位的操作来实现,由此得到模块内部的框图如下图所示:

在这里插入图片描述

系统时钟 sys_clk 的时钟周期为 20ns(对应开发板板载的晶振频率为 50Mhz),计数器计时 0.5s 需要0.5s/20ns=500_000_000ns/20ns = 25_000_000 个时钟周期,由于计数器是从 0 开始计数,所以计数器最大计数到25000000-1,刚好是 0.5s。


由此绘制出 flow_led 模块的波形图如下图所示:

在这里插入图片描述

由上图可知, tcnt 循环从 0 计数到 24999999,表示计时 0.5s。每当计数器计数到最大值时,此时切换LED 灯的状态。


流水灯(flow_led.v)代码编写如下:

// 流水灯模块, 流水间隔0.5smodule flow_led (// 模块时钟及复位input         sys_clk,input         sys_rstn,// LED输出output [3:0]  led
);//------------------------------------
//             Local Signal
//------------------------------------reg [24:0] tcnt = 0; // 计数器reg [3:0]  led_ff = 4'b1110; // 移位寄存器//------------------------------------
//             User Logic
//------------------------------------
// 计数器计时0.5salways @ (posedge sys_clk or negedge sys_rstn)if (!sys_rstn)tcnt <= 25'd0;else if (tcnt < 24'd24_999_999)tcnt <= tcnt + 25'd1;elsetcnt <= 25'd0; 
// led输出移位寄存器always @ (posedge sys_clk or negedge sys_rstn)if (!sys_rstn)led_ff <= 4'b1110;else if (tcnt == 24'd24_999_999)led_ff <= {led_ff[2:0],led_ff[3]};elseled_ff <= led_ff; 
//------------------------------------
//             Output Port
//------------------------------------assign led = led_ff;endmodule

流水灯(flow_led.v)的 Testbench 仿真代码编写如下:

`timescale 1ns/1nsmodule tb_flow_led;//*************************** Parameters ***************************parameter  PERIOD_CLK = 20;//***************************   Signals  ***************************// 模块时钟及复位reg        sys_clk = 0;reg        sys_rstn = 0;// LED输出wire [3:0] led;//*************************** Test Logic ***************************always # (PERIOD_CLK/2) sys_clk = ~sys_clk;initialbegin#100;sys_rstn = 1;#5000;$stop;end//***************************  Instance  ***************************flow_led u_flow_led(// 模块时钟及复位.sys_clk  (sys_clk),.sys_rstn (sys_rstn),// LED输出.led      (led));endmodule

由于流水灯模块定义的流水0.5s间隔较长,虽然 0.5s 从时间上来说比较短暂,但是对于仿真来说,仿真 0.5s 需要的时间较长。尤其是对于复杂的程序来说,有时候仿真几十毫秒,就需要好几个小时,因此为了降低仿真的等待时间和提升效率,一般需要对程序中延时较长的代码进行修改,流水灯模块修改后的代码如下(将流水时间间隔改为500ns):

// 流水灯模块, 流水间隔0.5smodule flow_led (// 模块时钟及复位input         sys_clk,input         sys_rstn,// LED输出output [3:0]  led
);//------------------------------------
//             Local Signal
//------------------------------------reg [24:0] tcnt = 0; // 计数器reg [3:0]  led_ff = 4'b1110; // 移位寄存器//------------------------------------
//             User Logic
//------------------------------------
// 计数器计时0.5salways @ (posedge sys_clk or negedge sys_rstn)if (!sys_rstn)tcnt <= 25'd0;// else if (tcnt < 24'd24_999_999)else if (tcnt < 24'd24)tcnt <= tcnt + 25'd1;elsetcnt <= 25'd0; 
// led输出移位寄存器always @ (posedge sys_clk or negedge sys_rstn)if (!sys_rstn)led_ff <= 4'b1110;// else if (tcnt == 24'd24_999_999)else if (tcnt == 24'd24)led_ff <= {led_ff[2:0],led_ff[3]};elseled_ff <= led_ff; 
//------------------------------------
//             Output Port
//------------------------------------assign led = led_ff;endmodule

工程搭建(Vivado)

  1. 双击打开 Vivado,点击”Create Project“;

    在这里插入图片描述

  2. 点击 ”Next“;

    在这里插入图片描述

  3. 工程命名;

    在这里插入图片描述

  4. 选择工程类型”RTL Project“,点击”Next“;

    在这里插入图片描述

  5. 一直点击 ”Next“;

    在这里插入图片描述

    在这里插入图片描述

  6. 选择芯片型号;

    在这里插入图片描述

    在这里插入图片描述

  7. 添加代码和仿真文件;

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

功能仿真(Modelsim)

  1. 设置选择仿真工具为 Modelsim;

    在这里插入图片描述

  2. 设置Modelsim安装路径和库路径;

    在这里插入图片描述

  3. 点击开始仿真;

    在这里插入图片描述

  4. 添加要观察的信号至波形窗口;

    在这里插入图片描述

  5. 点击“Run all”,查看仿真波形是否跟功能一致;

    在这里插入图片描述

  6. 由上图可知, led=4’b1110的持续时间为 500ns, led=4’b1101 的持续时间同样也是 500ns,即 LED 灯的流水间隔为 500ns,波形和预期相符。

    需要注意的是,在仿真结束之后,将代码中定义的 LED 流水间隔时间改回 0.5s,否则 500ns 的时间间隔太短,人的肉眼会看不到流水的效果。

生成下载文件

  1. 编写约束文件;

    ############## NET - IOSTANDARD ##################
    set_property CFGBVS VCCO [current_design]
    set_property CONFIG_VOLTAGE 3.3 [current_design]
    #############SPI Configurate Setting##################
    set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
    set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
    set_property CONFIG_MODE SPIx4 [current_design]
    set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]
    ############# clock #########################
    set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
    set_property PACKAGE_PIN Y18 [get_ports sys_clk]
    create_clock -period 20.000 [get_ports sys_clk]
    ############# reset ##########################
    set_property IOSTANDARD LVCMOS33 [get_ports sys_rstn]
    set_property PACKAGE_PIN F20 [get_ports sys_rstn]
    ########################### LED Define ###########################
    set_property PACKAGE_PIN F19 [get_ports {led[0]}]
    set_property PACKAGE_PIN E21 [get_ports {led[1]}]
    set_property PACKAGE_PIN D20 [get_ports {led[2]}]
    set_property PACKAGE_PIN C20 [get_ports {led[3]}]set_property IOSTANDARD LVCMOS33 [get_ports {led[*]}]
    
  2. 添加约束文件;

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

  3. Bitstream 设置,同时生成固化文件;

    在这里插入图片描述

  4. 点击生成 Bitstream;

    在这里插入图片描述

  5. 生成文件路径如下:

    在这里插入图片描述

上板验证

  1. 先连接硬件,把 JTAG 下载器和开发板连接,然后开发板上电,下图为开发板的硬件连接图:

在这里插入图片描述

  1. 点击 Open target 按钮->Auto Connect, 在 hardware 界面下会显示 xc7a35t_0( AX7035 开发板)或 xc7s50_0( AX7050 开发板) 的图标,说明 JTAG 连接已经建立 ;

    在这里插入图片描述

    在这里插入图片描述

  2. 右键选择 xc7a35t_0( AX7035 开发板)或 xc7s50_0( AX7050 开发板) ,在弹出的选项里选择Program Device 项 ;

    在这里插入图片描述

  3. 在弹出的 Program Device 对话框中, 选择 flow_led 项目生成的 bit 文件,点击 Program 按钮烧写 FPGA。

    在这里插入图片描述

  4. 烧写完成后 xc7a35t_0( AX7035 开发板)或 xc7s50_0( AX7050 开发板) 的状态会变成Programmed, 这时我们可以看到开发板上的四个 LED 灯已经在做流水灯动作了 。

    在这里插入图片描述

Flash固化

直接下载 Bit 文件到 FPGA 后,开发板重新上电后配置程序已经丢失,还需要JTAG 下载,只有固化到 Flash,才能实现上电不丢失。具体步骤如下:

  1. 在如下图中右键选择 xc7a35t_0( AX7035 开发板)或 xc7s50_0( AX7050 开发板) 芯片,在弹出的列表中选择 Add Configruation Memory Device… ;

    在这里插入图片描述

    注意:如果发现此项变为灰色不能选,是因为我们提供的工程中已经添加了 FLASH 配置,不能再添加 FLASH, 如下:

    在这里插入图片描述

    当然自己如果想在已有 flash 的工程中再次添加一下进行实验话,可按如下图移除 flash,然后按上面添加 flash 的步骤进行即可:

    在这里插入图片描述

  2. 在 Add configruation Memory Device 的配置界面里选择正确的 FLASH 型号,如下图所示:

    在这里插入图片描述

  3. 提示是否对 SPI FLASH 进行编程, 点击 OK;

    在这里插入图片描述

  4. 在弹出的 Program Configuration Memory Device 窗口中, Configration file 项选择 Vivado 生成的flow_led.bin 文件(此文件默认在 impl_1 目录下) 。 PRM File 项不用选。另外在这个窗口用户还可以配置 I/O 为上拉,下拉或者无上下拉。 配置操作选项保留默认就可以;

    在这里插入图片描述

  5. 点击 OK 开始编程 FLASH;

    在这里插入图片描述

  6. FLASH 编程完毕后, 会弹出如下成功的界面。
    在这里插入图片描述

  7. 至此, SPI FLASH 烧写完毕, flow_led 程序已经固化到 SPI FLASH 中了。我们来验证一下,关电重新启动开发板, 等待一会儿你就可以看到开发板上的 LED 灯已经在做跑马运动了。

http://www.dtcms.com/a/353477.html

相关文章:

  • 一键搭建开发环境:制作bash shell脚本
  • Apple Silicon Mac 上解决 Docker 平台不匹配和 QEMU 段错误问题
  • 腾讯云服务器重启卡住:原因分析与底层原理详解
  • AI-调查研究-62-机器人 机械臂五大应用场景详解:从焊接到手术,从农田到太空
  • Knife4j 文档展示异常的小坑
  • GBDT(Gradient Boosting Decision Tree,梯度提升决策树)总结梳理
  • 如何设置 Lustre 文件系统并在其上运行 PostgreSQL
  • 设计模式9-责任链模式
  • UDC否定响应码学习
  • 未成功:使用 Nginx 搭建代理服务器(正向代理 HTTPS 网站)
  • 《StarRocks、Doris、ClickHouse 深度对比:三大 OLAP 引擎的优劣与应用场景》
  • go的实现arp客户端
  • 《方法论》--笛卡尔
  • 【学习笔记】非异步安全函数(禁止在信号处理中调用)
  • 雷卯针对香橙派Orange Pi 4开发板防雷防静电方案
  • 【Golang】 项目启动方法
  • Android12 user版本默认开启adb调试
  • centos7安装java mysql redis nginx
  • docker 所有常用命令,配上思维导图,加图表显示
  • 713 乘积小于k的子数组
  • Mysql数据挂载
  • Leetcode+Java+动态规划IV
  • electron离线开发环境变量ELECTRON_OVERRIDE_DIST_PATH
  • [MT6835] MT6835开启secureboot导致写入分区提示Security deny for [customer].
  • 【图像算法 - 25】基于深度学习 YOLOv11 与 OpenCV 实现人员跌倒识别系统(人体姿态估计版本)
  • 达梦数据库配置文件-COMPATIBLE_MODE
  • LangChain4j入门一:LangChain4j简介及核心概念
  • 路由基础(一):IP地址规划
  • 基于单片机空调温度控制测温ds18b20系统Proteus仿真(含全部资料)
  • React 组件命名规范:为什么必须大写首字母蛊傲