跟着逻辑先生学习FPGA-实战篇第二课 6-2 LED灯流水灯实验

** 硬件平台:征战Pro开发板
软件平台:Vivado2018.3
仿真软件:Modelsim10.6d
文本编译器:Notepad++**

征战Pro开发板资料
链接:https://pan.baidu.com/s/1AIcnaGBpNLgFT8GG1yC-cA?pwd=x3u8
提取码:x3u8

1 知识背景

我们在《LED 灯闪烁实验》中对 LED 灯作了详细的介绍,如果大家对这部分内容不是很熟悉的话, 请参考《LED 灯闪烁实验》中的简介部分。

2 实验任务

流水灯是指同一时刻只有一个灯处于点亮状态,其余的 LED 灯处于熄灭状态,然后每隔一段时间 LED 灯从左往右依次点亮,从而形成流水灯的效果。实验我们将实现 8 个 LED 灯依次点亮,每 100ms 点亮 1 个灯。

3 硬件设计

3.1 原理图分析

八个 LED 灯均连接到了 FPGA 的 IO。当 FPGA 输出 LED0~LED7 为高电平时,发光二极管的正负极有电压差,便会产生电流流过发光二极管,从而点亮 LED 灯;当 FPGA 输出 LED0~LED7 为低电平时,发光二极管正负级没有电压差,也不会产生电流,LED 灯熄灭。
在这里插入图片描述
图6-2- 1 发光二极管原理图

3.2 管脚映射表

表6-2- 1 管脚映射表
在这里插入图片描述
在这里插入图片描述
同学们可能会好奇,为什么原理图中的网络名不和程序中的信号名一致呢?这是因为一般有两个原因:
1. 在公司里面,设计硬件的工程师和设计软件的工程师并不是同一个人,每个人的命名习惯不同,所以就会命名不一样的情况。
2. 硬件上的器件功能和软件上的功能并不一样。比如我们的按键 SW1 ,在硬件上它就是一个按键,但是在软件设计中,我们可以认为它是复位管脚,也可以认为它是控制管脚,所以原理图中的网络名和程序中的信号名没办法统一。
这种情况是很常见的,只要同学们掌握了原理,这个命名随便怎么变我们都知道如何去约束 FPGA 管脚。

3.3 编写 XDC 约束文件

在这里插入图片描述

4 程序设计

4.1 模块框图

八个灯流水的间隔时间为 100ms,间隔时间的控制需要通过计数器来实现,即通过计数器来实现计时的功能,因此本次实验需要用到系统时钟;除此之外,系统复位在 FPGA 系统中也是必不可少的,当程序出现跑飞等异常情况时,可以使程序恢复至默认状态;由以上分析可知,本次实验需要两个输入的端口,分别为系统时钟和系统复位,输出为 8 位的 LED 端口,模块框图如下图所示:
在这里插入图片描述
图6-2- 2模块框图与端口

4.2 设计思路

在硬件设计部分中我们介绍过,当 IO 输出高电平 1 时,点亮 LED 灯;当 IO 输出低电平 0 时, LED灯熄灭,因此要想控制 LED3 到 LED10 实现流水灯效果,第一次的时候给 led 端口赋值为 8’b00000001;等待 0.1s 后,给 led 端口赋值为 8’b00000010; 等待 0.1s 后,给 led 端口赋值为 8’b00000100;等待 0.1s,给 led 端口赋值为 8’b00001000;再次等待 0.1s 后,给 led 端口赋值为 8’b00010000,后面依次类推,八个 LED 即可实现流水的效果。
LED 灯流水的间隔为 0.1s,因此接下来还需要做一个 0.1s 的延时,延时的功能可以通过计数器实现,每当计数器计时到 0.1s 后,切换一次 LED 灯的显示状态即可。当计时完成后,开始控制 LED 灯的状态。
LED 共八种状态:
8’b00000001:对应 LED3 点亮,其它熄灭;
8’b00000010:对应 LED4 点亮,其它熄灭;
8’b00000100:对应 LED5 点亮,其它熄灭;
8’b00001000:对应 LED6 点亮,其它熄灭;
8’b00010000:对应 LED7 点亮,其它熄灭;
8’b00100000:对应 LED8 点亮,其它熄灭;
8’b01000000:对应 LED9 点亮,其它熄灭;
8’b10000000:对应 LED10 点亮,其它熄灭;
从上面我们得知,总共8个状态,那不用状态机来实现,岂不是对不起这 8 种状态。
由此绘制出 led_flow 模块的波形图如下图所示:

在这里插入图片描述
图6-2- 3 led_flow模块波形图

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

4.3 代码编写

限于篇幅,仅贴出部份代码(详见 Source 文件夹下led_flow.v文件)
定义模块端口,代码如下所示:

在这里插入图片描述
代码中使用了状态机,定义了九种状态,如下所示:
在这里插入图片描述
通过判断计数器cnt计数值到达最大值进行状态跳转,依次为:IDLE–>S0–>S1–>S2–>S3–>S4–>S5–>S6–>S7–>S0–>S1…,代码如下所示:
在这里插入图片描述
当状态机设计好以后,就可以根据不同状态给 led 端口赋值,代码如下所示:
在这里插入图片描述

5 仿真验证

对 RTL 代码进行仿真之前,我们首先需要编写实验对应的仿真文件(TestBench)。 TestBench 是用于验证功能模块的设计是否符合预期,其内容主要分为以下三个步骤:
1、 向被测功能模块的输入接口添加激励
2、 对被测功能模块的顶层接口进行信号例化
3、 判断被测功能模块的输出是否满足设计预期

5.1 led流水灯模块(led_flow)仿真验证

5.1.1 仿真激励代码编写

流水灯模块的输入端口为系统时钟 clk 和系统复位 rst_n,输出端口为 led。 clk 对应开发板所板载的 50MHz 的晶振,周期为 20ns,所以 TB 模块产生 clk 时,可以控制该信号每隔 10ns 翻转一次。而系统复位信号对应输入的复位按键,按键在未按下时为高电平,按下后为低电平,所以 TB 模块可以将 rst_n 初始状态赋值为 0,使程序处于复位状态,在延时一段时间后拉高 rst_n 来结束复位。在正常运行之前,先使程序处于一段时间的复位状态,是为了给流水灯模块里的相关信号赋初始值。
TB 模块产生的系统时钟和复位信号通过例化被测模块,将信号传递至被测模块中。
由于在上一章我们已经把仿真脚本写好了,这一章我们只用将 Sim 这个文件夹拷贝到我们当前课程文件夹中,文件结构如下所示:

在这里插入图片描述
图6-2- 4 工程结构

打开Sim文件夹,将“tb_led_shark.v”文件改为“tb_led_flow.v”,然后使用“Notepad++”工具打开“tb_led_flow.v”文件,就可以开始编写仿真代码了。
在这里插入图片描述

程序中第一行代码定义的仿真单位和仿真精度都是 1ns,对应程序中第 15 行代码表示延时 200ns。程序中第 20 行代码用于产生系统时钟, clk 每隔 10ns 翻转一次,一个完整的时钟周期包含一个高电平和一个低电平,因此系统时钟为 20ns,对应系统时钟频率为 50MHz。
需要注意的是,由于流水灯模块定义的流水间隔较长,为 0.1s,虽然 0.1s 从时间上来说比较短暂,但是对于仿真来说,仿真 0.1s 需要的时间较长。尤其是对于复杂的程序来说,有时候仿真几十毫秒,就需要好几个小时,因此为了降低仿真的等待时间和提升效率,一般需要对程序中延时较长的参数在仿真代码中进行重定义,如仿真代码第 23 行将led_flow 模块中的TIME_0S1进行重新定义赋值。

5.1.2 批处理仿真

仿真代码编写好,就可以使用批处理仿真了,在该章节我们可以不用再更改 modelsim.bat 文件。sim.do 文件也仅仅只用修改一处地方,如下图所示:

在这里插入图片描述
此处改为我们当前的仿真代码模块名:tb_led_flow,改好以后,保存。
双击modelsim.bat,我们就不管了,先喝茶,等软件自已跑(具体步骤参考前一章节),细心的读者会发现,modelsim界面报错了,如下图所示:
在这里插入图片描述
图6-2- 5 Modelsim报错信息

报错提示clk在wave.do不能被发现,这是因为我们的wave.do文件还是上一章节的波形,所以此处报错我们不用理会。当我们保存波形文件再运行 sim.do 文件就不会再报该错误了。

5.1.3 仿真波形分析

我们将led_flow模块的信号加入波形窗口,并将波形文件保存,运行sim.do指令(具体步骤参考《6-1 LED灯闪烁实验》),仿真出的波形如下图所示:

在这里插入图片描述
图6-2- 6 led_flow模块仿真波形
在这里插入图片描述
图6-2- 7 led_flow模块仿真波形(局部放大)

由图可知,状态机(curr_st)跳转正确,led 赋值正确;由图可知,状态机在 cnt 等于 9 时跳转,波形和预期相符。

6 综合编译

在前面我们已经将Source里面的源码(led_flow.v)和约束文件(pin.xdc)通过notepad++软件编辑好了,并且通过Modelsim进行了功能仿真,接下来我们新建Vivado工程并生成bit文件。具体步骤见《6-1 LED灯闪烁实验》章节,此处不再赘述。

7 下载验证

具体步骤见《6-1 LED灯闪烁实验》章节,此处不再赘述。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/497555.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kafka数据迁移全解析:同集群和跨集群

文章目录 一、同集群迁移二、跨集群迁移 Kafka两种迁移场景,分别是同集群数据迁移、跨集群数据迁移。 一、同集群迁移 应用场景: broker 迁移 主要使用的场景是broker 上线,下线,或者扩容等.基于同一套zookeeper的操作。 实践: 将需要新添加…

Ashy的考研游记

文章目录 摘要12.1112.2012.21 DAY1(政治/英语)政治英语 12.22 DAY2(数学/专业课)数学专业课 结束估分 摘要 在24年的12月里,Ashy完成了他的考研冲刺,顺利的结束了他本年度的考研之旅。 在十二月里&#…

【Sentinel】流控效果与热点参数限流

目录 1.流控效果 1.1.warm up 2.2.排队等待 1.3.总结 2.热点参数限流 2.1.全局参数限流 2.2.热点参数限流 2.3.案例 1.流控效果 在流控的高级选项中,还有一个流控效果选项: 流控效果是指请求达到流控阈值时应该采取的措施,包括三种&…

【Unity3D】ECS入门学习(十二)IJob、IJobFor、IJobParallelFor

IJob&#xff1a;开启单个线程进行计算&#xff0c;线程内不允许对同一个数据进行操作&#xff0c;也就是如果你想用多个IJob分别计算&#xff0c;将其结果存储到同一个NativeArray<int>数组是不允许的&#xff0c;所以不要这样做&#xff0c;如下例子就是反面教材&#…

SELECT的使用

目录 1、SQL的查询命令 1.1 SELECT语句 1.2 投影查询 1.3 选择查询 1.4 聚合函数查询 1.5 简单分组查询(GROUP BY) 1.6 内连接查询 1.7 外连接查询 1.8 子查询 1. 无关子查询 2. 相关子查询 带exists的相关子查询&#xff1a; 1.9 集合查询 1. UNION(并) 2. INT…

电池均衡系统

一、电池概况 常见的电池分类&#xff1a;铅酸电池、锂电池、钠离子电池、碱性干电池、纽扣电池等&#xff0c;其中钠离子电池暂未大规模商用。 例如&#xff1a;电动车电池电压通常48v、60v、72v等&#xff0c;汽车启动电池电压&#xff1a;12v 而构成高电压的电池&#xf…

Windows系统下载、部署Node.js与npm环境的方法

本文介绍在Windows电脑中&#xff0c;下载、安装并配置Node.js环境与npm包管理工具的方法。 Node.js是一个基于Chrome V8引擎的JavaScript运行时环境&#xff0c;其允许开发者使用JavaScript编写命令行工具和服务器端脚本。而npm&#xff08;Node Package Manager&#xff09;则…

使用arduino从零做一辆ROS2Jazzy的阿克曼小车---电机驱动篇

本项目采用 Arduino Mega2560 Pro 作为主控开发板&#xff0c;电机驱动器选用 TB6612FNG&#xff0c;并配备了 12V 电源、两个直流减速电机和一个舵机。未来计划通过嘉立创将各模块集成到一个 PCB 板上&#xff0c;提升系统的集成度和稳定性。 本文将聚焦于电机驱动部分&#x…

华为麦芒5(安卓6)termux记录 使用ddns-go,alist

下载0.119bate1 安卓5和6版本,不能换源,其他源似乎都用不了,如果root可以直接用面具模块 https://github.com/termux/termux-app/releases/download/v0.119.0-beta.1/termux-app_v0.119.0-beta.1apt-android-5-github-debug_arm64-v8a.apk 安装ssh(非必要) pkg install open…

图片转成oled使用的字模数据

目录 oled尺寸 如何生成用到的图片 图片转字模 1.首先用Img2Lcd转成bmp单色图片 2.然后用PCtoLCD2002把单色图片转字模 oled尺寸 我使用0.96寸oled模块&#xff0c;对应着的分辨率是128*64&#xff0c;对应着宽高像素比128*64。所以不是随意一张图片就能用的&#xff0c;…

【通信网络】二层基础:03 二层转发基础

1. 二层转发概述 数据链路层&#xff0c;位于OSI模型中的第二层&#xff0c;所以称之为二层。本文我们讨论的转发过程&#xff0c;就是在数据链路层上的转发过程&#xff0c;即二层转发。 1.1 MAC地址 为了唯一的表示一台网络设备&#xff0c;网络设备都有自己的MAC地址。IE…

从0到100:基于Java的大学选修课选课小程序开发笔记(上)

背景 为学生提供便捷的课程选择方式&#xff0c;并帮助学校进行课程管理和资源调配&#xff1b;主要功能包括&#xff1a;课程展示&#xff0c;自主选课&#xff0c;取消选课&#xff0c;后台录入课程&#xff0c;统计每门课程报名情况&#xff0c;导出数据&#xff0c;用户管…

基于Springboot + vue实现的火锅店管理系统

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

基于Svelte 5的体检查询系统前端设计与实现探究

一、引言 1.1 研究背景与意义 在当今数字化时代&#xff0c;医疗信息化已成为医疗行业发展的重要趋势。随着人们对健康的重视程度不断提高&#xff0c;体检作为预防疾病、保障健康的重要手段&#xff0c;其相关信息的管理和查询需求也日益增长。传统的体检查询系统前端往往存…

科大讯飞在线语音合成(流式版)python版

1、进入自己的项目 复制APPID、APISecret、APIKey 2、添加好听发音人 复制vcn参数 3、需要替换代码部分&#xff1a; 换自己喜欢的发声人的参数 换上自己的APPID、APISecret、APIKey 4、完整代码&#xff1a; # -*- coding:utf-8 -*- import _thread as thread import base…

TCP 为什么采用三次握手和四次挥手以及 TCP 和 UDP 的区别

1. TCP 为什么采用三次握手和四次挥手 采用三次握手的原因&#xff1a; 确认双方的收发能力。第一次握手&#xff0c;客户端发送 SYN 报文&#xff0c;告诉服务器自身具备发送数据的能力&#xff0c;第二次握手&#xff0c;服务器回应 SYN ACK 报文&#xff0c;表名自己既能…

python-Flask:SQLite数据库路径不正确但是成功访问到了数据库,并对表进行了操作

出现了这个问题&#xff0c;就好像是我要去找在南方的人&#xff0c;然后我刚好不分南北&#xff0c;我认为的方向错了&#xff0c;实则方向对了。 在我针对复盘解决&#xff1a;sqlite3.OperationalError: unrecognized token: “{“-CSDN博客这个内容的时候&#xff0c;又出现…

2024-12-29-sklearn学习(25)无监督学习-神经网络模型(无监督) 烟笼寒水月笼沙,夜泊秦淮近酒家。

文章目录 sklearn学习(25) 无监督学习-神经网络模型&#xff08;无监督&#xff09;25.1 限制波尔兹曼机25.1.1 图形模型和参数化25.1.2 伯努利限制玻尔兹曼机25.1.3 随机最大似然学习 sklearn学习(25) 无监督学习-神经网络模型&#xff08;无监督&#xff09; 文章参考网站&a…

Spring ----深入理解AOP(面向切面编程)

给程序做增强 事务是最小的执行单元&#xff0c;转账&#xff0c;同时成功、同时失败 TxUtils类式事务管理类&#xff0c;有6个静态方法&#xff0c;可以直接通过类名来调用&#xff0c;threadlocal线程池&#xff0c;还有一个静态代码块&#xff0c;来加载链接 从数据源中获取…

vue源码分析(十)—— 生命周期

文章目录 前言一、关键方法 callHook二、详细的钩子函数说明1.beforeCreate和create2.beforeMount & mounted注意点组件&#xff08;非根组件&#xff09;的渲染节点&#xff08;1&#xff09;invokeInsertHook函数&#xff08;2&#xff09;insert方法&#xff08;3&#…