07 按键控制 LED

按键简介

按键开关是一种电子开关,属于电子元器件类。常见的按键开关有两种,第一种是轻触式按键开关(简称轻触开关),使用时以向开关的操作方向施加压力使内部电路闭合接通,当撤销压力时开关断开,其内部结构是靠金属弹片受力后发生形变来实现通断的;第二种是自锁按键,自锁按键第一次按下后保持接通,即自锁,第二次按下后,开关断开,同时开关按钮
弹出来。
在这里插入图片描述

硬件原理图

LED原理图

LED0 到 LED3 这 4 个发光二极管的阴极分别连到 S8050(NPN 三极管)的集电极上,阳极都与 3.3V 电压相连,三极管的基极分别与 FPGA 相连,这是由于 FPGA 的 IO 口的电压只有 1.5V,电压较低,所以此处连接三极管是为了起到放大电压的作用。这样就可以通过改变三极管的状态来控制 LED 的亮灭。当 FPGA 输出到为高电平时,三极管导通,LED 灯亮;当 FPGA 输出到为低电平时,三极管截止,LED 灯灭。
在这里插入图片描述
在这里插入图片描述

按键原理图

每个按键都连接了一个 1K 电阻(起到限流的作用,以防止按键被按下时电源直接接地造成电路短路),当按键未按下时,为高电平,按下后,为低电平。
在这里插入图片描述
在这里插入图片描述

程序功能

使用 4 个按键来控制 4 颗 LED 灯。没有按键被按下时,4 颗 LED 保持常灭;如果按键 KEY0 被按下, LED 灯从低位到高位流水;如果按键 KEY1 被按下,LED 灯从高位到低位流水;如果按键 KEY2 被按下,LED 灯交替闪烁;KEY3 被按下,LED 灯常亮。
在这里插入图片描述

系统框图

在这里插入图片描述

代码编写

`timescale 1ns / 1ns	//仿真单位/仿真精度

module key_led #(
	//参数列表
	parameter COUNT_WIDTH = 25,				//内部计数器宽度
	parameter COUNT_PERIOD = 25_000_000		//计数器最大周期,决定LED多久变化依次
)
(
	input sys_clk,							//时钟
	input sys_rst_n,						//复位
	input [3:0] key,						//按键
	
	output reg [3:0] led					//led
);

//周期计数器,当计数到COUNT_PERIOD-1时LED进行输出状态切换
reg [COUNT_WIDTH-1:0] count;
//LED等控制标志
//流水灯模式时记录当前点亮的是那个LED
//闪烁模式时led_flag[0]用于亮灭控制
reg [1:0] led_flag;

//周期计数器,当计数到COUNT_PERIOD-1时LED进行输出状态切换
always @(posedge sys_clk) begin
	if(!sys_rst_n)
		count <= 0;
	else if(count < (COUNT_PERIOD - 1))
		count <= count+ 1;
	else
		count <= 0;
end

//LED等控制标志
//流水灯模式时记录当前点亮的是那个LED
//闪烁模式时led_flag[0]用于亮灭控制
always @(posedge sys_clk) begin
	if(!sys_rst_n)
		led_flag <= 2'h0;
	else if(count == (COUNT_PERIOD - 1))
		led_flag <= led_flag + 2'h1;
end

//根据按键状态和流水灯控制标志控制LED输出
always @(posedge sys_clk) begin
	if(!sys_rst_n)
		led <= 4'b0000;
	else if(key == 4'b1111)				//全灭
		led <= 4'b0000;
	else if(key == 4'b1110) begin		//从led0到led3流水
		if(led_flag == 2'd0)
			led <= 4'b0001;
		else if(led_flag == 2'd1)
			led <= 4'b0010;
		else if(led_flag == 2'd2)
			led <= 4'b0100;
		else
			led <= 4'b1000;
	end
	else if(key == 4'b1101) begin		//从led3到led0流水
		if(led_flag == 2'd0)
			led <= 4'b1000;
		else if(led_flag == 2'd1)
			led <= 4'b0100;
		else if(led_flag == 2'd2)
			led <= 4'b0010;
		else
			led <= 4'b0001;
	end
	else if(key == 4'b1011) begin		//闪烁
		if(led_flag[0] == 1'b0)
			led <= 4'b1111;
		else
			led <= 4'b0000;
	end
	else if(key == 4'b0111)				//全亮
		led <= 4'b1111;
end

endmodule

仿真验证激励程序

`timescale 1ns/1ns //仿真的单位/仿真的精度

module tb_key_led();

reg sys_clk;					//时钟
reg sys_rst_n;					//复位
reg [3:0] key;					//按键

wire [3:0] led;					//led

initial begin
	sys_clk = 1'b0;
	sys_rst_n = 1'b0;
	key <= 4'b1111;
	#180
	sys_rst_n = 1'b1;
	
	#2000
	key <= 4'b1110; //按下 KEY0
	#2000
	key <= 4'b1111; //释放 KEY0
	
	#2000
	key <= 4'b1101; //按下 KEY1
	#2000
	key <= 4'b1111; //释放 KEY1
	
	#2000
	key <= 4'b1011; //按下 KEY2
	#2000
	key <= 4'b1111; //释放 KEY2
	
	#2000
	key <= 4'b0111; //按下 KEY3
	#2000
	key <= 4'b1111; //释放 KEY3
end

always #10 sys_clk = ~sys_clk;

key_led #(
	//参数列表
	.COUNT_WIDTH(25),
	.COUNT_PERIOD(25)
)
tb_key_led_inst(
	.sys_clk(sys_clk),				//时钟
	.sys_rst_n(sys_rst_n),			//复位
	.key(key),						//按键
	
	.led(led)						//led
);
endmodule

时序约束

时序约束(Timing Constraints)用来描述设计人员对时序的要求,比如时钟频率,输入输出的延时等,以满足设计的时序要求。对时序约束最简单的理解就是,设计者告诉 EDA 工具设计中所使用的时钟信号的参数(如频率等),然后 EDA 工具按照所要求的时钟参数去优化布局布线,使设计能够在要求的时钟下正常工作
一般情况下对于简单的设计,即使不对工程做时序约束,也不影响最终的功能。但是当设计变得复杂起来,或者输入的时钟频率比较高的时候,如果不添加时序约束,那么就有可能导致功能异常。

添加时序约束

  1. 对时钟进行约束前,需要先对代码进行综合,即点击 Vivado 左侧“Flow Navigator”窗口下“Run Synthesis”按钮来对代码进行综合
    在这里插入图片描述
    在弹出的窗口中我们直接点击“OK”
    在这里插入图片描述

  2. 综合完成后,在弹出的“Synthesis Completed”窗口中我们直接点击“X”即可
    在这里插入图片描述

  3. 点击 Vivado 左侧“Flow Navigator”窗口下的“Edit Timing Constraints”按钮了
    在这里插入图片描述

  4. 点击“Edit Timing Constraints”按钮后,Vivado 就会打开“Timing Constraints”界面,我们点击该界面下的“+”号按键就可以添加时钟约束了
    在这里插入图片描述

  5. 点击“+”号后,弹出的“Create Clock”界面
    在这里插入图片描述
    “Create Clock”界面中各参数定义如下:
    Clock name:时钟名称,用于为所创建的时钟约束命名。为了可以一眼看出该时钟约束的约束源,通常情况下其命名与被约束的时钟信号名相同
    Source objects:源对象,用于指定被约束的时钟对象
    Waveform:波形,用于设置时钟的周期(Period),上升沿(Rise at)、下降沿(Fall at)以及勾选 Add this clock to the existing clock(是否将该时钟添加到现有时钟中)
    Command:命令,即通过我们上述的配置后,vivado 自动生成的约束命令,该命令是可以直接复制粘贴到 XDC 文件中使用的

  6. 点击“Source objects”框后的“…”指定时钟源对象
    在这里插入图片描述

  7. 点击“…”后弹出“Specify Clock Source Objects”,在“Specify Clock Source Objects”界面中“Find”之上的各个选项主要用于设置筛选条件,因为系统时钟来自于 IO 口,所以“Find names of type(寻找名称类型)”选择“I/O Port”,其余选项保持默认。
    在这里插入图片描述

  8. 在找到的信号中,我们选择需要约束的系统时钟信号(sys_clk)然后点击“→”按钮将其添加到右侧窗口。
    在这里插入图片描述

  9. 之后点击“Set”即可将该信号定义为源对象
    在这里插入图片描述

  10. 点击 “Create Clock” 的“OK”即可添加约束并关闭“Create Clock”界面
    在这里插入图片描述

  11. 此时的 “Timing Constraints”界面如下
    在这里插入图片描述

  12. 点击 Vivado 软件左上方的保存图标来将其保存到 XDC 文件中,如果弹出“Out of Date Design”则点击 “OK”
    在这里插入图片描述
    在这里插入图片描述

  13. 在弹出的“Save Constraints”界面中会默认保存到现有的 XDC 文件中,所以直接点击“OK”
    在这里插入图片描述

管脚约束

管脚约束方法1:
直接在约束文件中增加如下内容,用于约束IO引脚

#IO 引脚约束
#------------------------------系统时钟和复位-----------------------------------
set_property -dict {PACKAGE_PIN R4 IOSTANDARD LVCMOS15} [get_ports sys_clk]
set_property -dict {PACKAGE_PIN U7 IOSTANDARD LVCMOS15} [get_ports sys_rst_n]
#----------------------------------按键-----------------------------------------
set_property -dict {PACKAGE_PIN T4 IOSTANDARD LVCMOS15} [get_ports {key[0]}]
set_property -dict {PACKAGE_PIN T3 IOSTANDARD LVCMOS15} [get_ports {key[1]}]
set_property -dict {PACKAGE_PIN R6 IOSTANDARD LVCMOS15} [get_ports {key[2]}]
set_property -dict {PACKAGE_PIN T6 IOSTANDARD LVCMOS15} [get_ports {key[3]}]
#-----------------------------------LED-----------------------------------------
set_property -dict {PACKAGE_PIN V9 IOSTANDARD LVCMOS15} [get_ports {led[0]}]
set_property -dict {PACKAGE_PIN Y8 IOSTANDARD LVCMOS15} [get_ports {led[1]}]
set_property -dict {PACKAGE_PIN Y7 IOSTANDARD LVCMOS15} [get_ports {led[2]}]
set_property -dict {PACKAGE_PIN W7 IOSTANDARD LVCMOS15} [get_ports {led[3]}]

管脚约束方法2:

  1. 需要先对代码进行综合,即点击 Vivado 左侧“Flow Navigator”窗口下“Run Synthesis”按钮来对代码进行综合
    在这里插入图片描述
  2. 综合完成后选择 Vivado 左侧“Flow Navigator”窗口下“SYNTHESIS“
    在这里插入图片描述
  3. 在右上角的窗口布局中选择”I/O Planning“
    在这里插入图片描述
  4. 选中下面的”I/O Ports“页面
    在这里插入图片描述
    Name:工程中顶层端口的名称。
    Direction:说明管脚是输入还是输出。
    Neg Diff Pair:负差分对,差分信号在 I/O Ports 窗口中只显示在一行里(只会显示 P 端信号,N 端信号显示在 Neg Diff Pair 属性栏中)。
    Package Pin:配置管脚封装。
    Fixed:每一个端口都有 Fixed 属性,表明该逻辑端口是由用户赋值的。端口必须保持锁定状态,才能避免生成比特流时不会发生错误。
    Bank:显示管脚所在的 Bank。
    I/O Std:配置管脚的电平标准,常用电平标准有 LVTTL 和 LVCMOS、SSTL、LVDS 与 HSTL 等。
    Vcco:选择的管脚的电压值。
    Vref:在我们的设计中,硬件上 VREF 引脚悬空。
    Drive Strength:驱动强度,默认 12mA。
    Slew Type:指上升下降沿的快慢,设置快功耗会高一点,默认设置慢(slow)。
    Pull Type:管脚上下拉设置,有上拉、下拉、保持与不设置。
    Off-Chip Termination:终端阻抗,默认 50Ω。
    IN-TERM:是用于 input 的串联电阻。
    提示
    如果页面被不小心关掉了可以选择右上角的”Reset Layout“
    在这里插入图片描述
  5. 在I/O Ports中根据原理图完成引脚约束
  6. 点击 Vivado 软件左上方的保存图标来将其保存到 XDC 文件中,如果弹出“Out of Date Design”则点击 “OK”
    在这里插入图片描述
    在这里插入图片描述
  7. 在弹出的“Save Constraints”界面中会默认保存到现有的 XDC 文件中,所以直接点击“OK”
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

unity学习(22)——客户端与服务器合力完成注册功能(4)数据库化

单纯的账号密码这种非频繁读写&#xff0c;实现起来很简单的&#xff0c;游戏的属性信息到时候也许会比较麻烦。 思路&#xff1a;每次加入有新键值TryAdd&#xff0c;如果加入成功&#xff0c;直接重写账号密码文件即可。 C#JsonConvert.DeserializeObject反序列化与JsonCon…

15-55V输入自动升降压 光伏MPPT自动跟踪充电方案 大功率300瓦

1.MPPT原理--简介 MPPT&#xff0c;全称为Maximum Power Point Tracking&#xff0c;即最大功点跟踪&#xff0c;它是一种通过调节电气模块的工作状态&#xff0c;使光伏板能够输出更多电能的电气系统能够将太阳能电池板发出的直流电有效地贮存在蓄电池中&#xff0c;可有效地…

0205-2-数据链路层

第 3 章 数据链路层 使用点对点信道的数据链路层 数据链路和帧 数据链路层使用的信道主要有以下两种类型&#xff1a; 点对点信道。这种信道使用一对一的点对点通信方式。广播信道。这种信道使用一对多的广播通信方式&#xff0c;因此过程比较复杂。广播信道上连接的主机很多…

程序员金三银四跳槽指南:时间线经典面试16问

祝大家成功上岸&#xff0c;升职加薪&#xff0c;冲鸭 &#x1f389; 金三银四 今天复工&#xff0c;就要开始准备啦&#x1f4bc;✨ 把握好打工人跳槽的金三银四&#xff0c;获得满意的新工作 &#x1f389; 时间线 年后跳槽时间线&#xff0c;过完年刚好开始准备&#xf…

COMSOL Multiphysics在超材料与超表面仿真中的应用

随着科技的飞速发展&#xff0c;超材料和超表面作为新兴研究领域&#xff0c;吸引了广泛关注。它们通过人工设计的结构&#xff0c;能够在特定条件下表现出特殊的物理性质&#xff0c;为光电子领域带来革命性的变革。COMSOL Multiphysics作为一款强大的多物理场仿真软件&#x…

vue 实现docx文件在线预览

预览请求步骤&#xff1a; 准备一个需要预览的文件地址【如:https://usdoc.cn/vw/文件模板.docx】GET 参数到请求地址将拼接好的地址放在浏览器中&#xff0c;开始预览 请求地址&#xff1a;https://vw.usdoc.cn/ 请求方式&#xff1a;GET 请求参数: 字段名称字段类型必填参数…

WordPress主题YIA在广告位添加图片广告时下方有空白怎么办?

YIA主题设置中默认有4个广告位&#xff0c;而侧边栏的广告位由站长自行添加。boke112百科在这些广告位添加图片广告后发现图片下方有空白&#xff0c;导致下方的两个角没有变圆角&#xff0c;看起来也有点不好看。具体如下图所示&#xff1a; 其实&#xff0c;这个问题就是典型…

Spring Security基础学习

一、SpringSecurity框架简介 二、SpringSecurity入门案例 三、SpringSecurity Web权限方案 四、SpringSecurity微服务权限方案 五、SpringSecurity原理总结

Model / View结构

红色部分是可以直接使用的。 QFileSystemModel; QFileSystemModel的使用&#xff1a; 头文件&#xff1a; QFileSystemModel* model nullptr; cpp文件&#xff1a; model new QFileSystemModel; model->setRootPath(QDir::currentPath()); ui->listView->setModel…

微信小程序:实现微信小程序应用首页开发 (本地生活首页)

文章目录 小程序应用页面开发1、创建项目并配置项目目录结构配置导航栏效果三、配置 tabBar 效果四、轮播图实现4.1 创建轮播图数据容器4.2 定义一个请求轮播图数据的接口4.3 页面加载调用 数据请求接口 五、九宫格实现5.1 获取九宫格数据5.2 结构和样式的完善六、图片布局实现…

普中51单片机学习(九)

蜂鸣器 蜂鸣器简介 在单片机应用的设计上&#xff0c;很多方案都会用到蜂鸣器&#xff0c;大部分都是使用蜂鸣器来做提示或报警&#xff0c;比如按键按下、开始工作、工作结束或是故障等等。改变单片机引脚输出波形的频率&#xff0c;就可以调整控制蜂鸣器音调&#xff0c;产…

Qt的基本操作

文章目录 1. Qt Hello World 程序1.1 通过图形化界面的方式1.2 通过代码的方式实现 2. Qt 的编码问题3. 使用输入框实现hello world4. 使用按钮实现hello world5. Qt 编程注意事项6. 查询文档的方式7. 认识Qt坐标系 1. Qt Hello World 程序 1.1 通过图形化界面的方式 我们先讲…

Autosar --- CAN Driver标准解读

前言 本文是对Autosar文档的翻译与解读&#xff0c;通过对规范的理解&#xff0c;加上实际的应用来一一对应&#xff0c;方便大家更好的理解。 注意&#xff1a;本文并非完全的按照【AUTOSAR_SWS_CANDriver.pdf】来进行翻译的。文章内容的标题与【AUTOSAR_SWS_CANDriver.pdf】保…

记录setData报错TypeError: [object Array] is not a function

小程序调用setData控制台显示报错.但是功能正常 同样的各个地方调setData都报错,经过一轮排除法后发现是自定义组件写法有问题 修改正确之后就没问题了

精品jsp+ssm健身器材管理系统-教练开发与设计

《[含文档PPT源码等]精品jspssm健身管理系统开发与设计[包运行成功]》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 使用技术&#xff1a; 开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&…

VUE3 中导入VISO 图形

微软的VISO是一个功能强大的图形设计工具&#xff0c;它能够绘制流程图&#xff0c;P&ID&#xff0c;UML 类图等工程设计中常用的图形。它要比其它图形设计软件要简单许多。以后我的博文中将更多地使用VISO 来绘制图形。之前我一直使用的是corelDraw。 VISO 已经在工程设计…

AbstractQueuedSynchronizer

重要类 Node Node中的属性&#xff1a;prev next 重要方法 这个方法主要有两种实现 一个是公平 一个是非公平 公平&#xff1a; /*** Fair version of tryAcquire. Dont grant access unless* recursive call or no waiters or is first.*/protected final boolean tryAcq…

IOC理解总结

IOC 控制反转&#xff08;Inversion of Control&#xff0c;缩写为IoC&#xff09;&#xff0c;是面向对象编程中的一种设计原则&#xff0c;可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入&#xff08;Dependency Injection&#xff0c;简称DI&#xff09…

[深度学习] 卷积神经网络“卷“在哪里?

​ &#x1f308; 博客个人主页&#xff1a;Chris在Coding &#x1f3a5; 本文所属专栏&#xff1a;[深度学习] ❤️ 热门学习专栏&#xff1a;[Linux学习] ⏰ 我们仍在旅途 目录 1.卷积的定义 2.卷积的"卷"在哪里 3.什么又是卷积神…

⭐北邮复试刷题589. N 叉树的前序遍历__DFS (力扣每日一题)

589. N 叉树的前序遍历 给定一个 n 叉树的根节点 root &#xff0c;返回 其节点值的 前序遍历 。 n 叉树 在输入中按层序遍历进行序列化表示&#xff0c;每组子节点由空值 null 分隔&#xff08;请参见示例&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [1,null,…