-- filename ﹕ sw_debounce.vhd
-- author ﹕ wuhouhang
-- description ﹕ 三个独立按键控制四个led流水灯工作/停止或者左移/右移
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity johnson is
port(
clk: in std_logic; --50mhz输入时钟
rst_n: in std_logic; --低电平复位信号
key_in: in std_logic_vector (2 downto 0); --三个独立按键,低表示按下
--key_in(2): 控制流水灯工作/停止
--key_in(1): 控制流水灯右移
--key_in(0): 控制流水灯左移
led_out: buffer std_logic_vector (3 downto 0) --发光二极管,分别由按键控制
);
end entity johnson;
--20ms按键消抖处理
--消抖后按键下降沿检测
--按键控制led控制位状态
--led显示控制
architecture key_control_of_led of johnson is
signal key_inr0: std_logic_vector (2 downto 0); --第一拍按键锁存寄存器
signal key_inr1: std_logic_vector (2 downto 0); --第二拍按键锁存寄存器
signal key_posedge: std_logic_vector (2 downto 0); --按键上升沿标志位,高电平有效一个时钟周期
signal key_negedge: std_logic_vector (2 downto 0); --按键下降沿标志位,高电平有效一个时钟周期
signal cnt20ms: std_logic_vector (19 downto 0); --20ms计数寄存器
signal key_value: std_logic_vector (2 downto 0); --消抖后的键值锁存寄存器
signal key_valuer0: std_logic_vector (2 downto 0); --消抖后第一拍按键锁存寄存器
signal key_valuer1: std_logic_vector (2 downto 0); --消抖后第二拍按键锁存寄存器
signal key_valueneg: std_logic_vector (2 downto 0); --消抖后按键下降沿标志位,高电平有效一个时钟周期
signal led_display: std_logic; --led流水灯工作,1--开启,0--停止
signal led_direction: std_logic; --led流水灯方向,1--右移,0--左移
signal cnt320ms: std_logic_vector (23 downto 0); --320ms计数寄存器
begin
--第一拍按键锁存
process(clk,rst_n)
begin
if (rst_n = '0') then --异步复位
key_inr0 <= 111;
elsif (clk'event and clk = '1') then --时钟上升沿
key_inr0 <= key_in; --锁存上一拍键值
end if;
end process;
--第二拍按键锁存
process(clk,rst_n)
begin
if (rst_n = '0') then --异步复位
key_inr1 <= 111;
elsif (clk'event and clk = '1') then --时钟上升沿
key_inr1 <= key_inr0; --锁存上一拍键值
end if;
end process;
--按键边沿检测
key_posedge <= (not key_inr1) and key_inr0; --按键上升沿标志位,高电平有效一个时钟周期
key_negedge <= key_inr1 and (not key_inr0); --按键下降沿标志位,高电平有效一个时钟周期
--20ms计数
process(clk,rst_n)
begin
if (rst_n = '0') then --异步复位
cnt20ms <= x00000;
elsif (clk'event and clk = '1') then --时钟上升沿
if ((key_posedge /= 000) or (key_negedge /= 000)) then --键值边沿标志位复位计数器,此处理目的为消除抖动
cnt20ms <= x00000;
elsif (cnt20ms < 10#1000000#) then --20ms计数
cnt20ms <= cnt20ms+1;
else
cnt20ms <= x00000;
end if;
end if;
end process;
--消抖后键值锁存
process(clk,rst_n)
begin
if (rst_n = '0') then --异步复位
key_value <= 111;
elsif (clk'event and clk = '1') then --时钟上升沿
if (cnt20ms = 10#1000000#) then --计数值到20ms
key_value <= key_inr1; --锁存键值
end if;
end if;
end process;
--消抖后第一拍按键锁存
process(clk,rst_n)
begin
if (rst_n = '0') then --异步复位
key_valuer0 <= 111;
elsif (clk'event and clk = '1') then --时钟上升沿
key_valuer0 <= key_value; --锁存上一拍键值
end if;
end process;
--消抖后第二拍按键锁存
process(clk,rst_n)
begin
if (rst_n = '0') then --异步复位
key_valuer1 <= 111;
elsif (clk'event and clk = '1') then --时钟上升沿
key_valuer1 <= key_valuer0; --锁存上一拍键值
end if;
end process;
--消抖后按键下降沿检测
key_valueneg <= key_valuer1 and (not key_valuer0); --消抖后按键下降沿标志位,高电平有效一个时钟周期
--按键控制led控制位状态(流水灯工作/停止)
process(clk,rst_n)
begin
if (rst_n = '0') then --异步复位
led_display <= '0';
elsif (clk'event and clk = '1') then --时钟上升沿
if (key_valueneg(2) = '1') then --控制流水灯工作/停止
led_display <= not led_display; --锁存键值
end if;
end if;
end process;
--按键控制led控制位状态(流水灯左移/右移)
process(clk,rst_n)
begin
if (rst_n = '0') then --异步复位
led_direction <= '0';
elsif (clk'event and clk = '1') then --时钟上升沿
if (key_valueneg(1) = '1') then --控制流水灯工作/停止
led_direction <= '1'; --锁存键值
elsif (key_valueneg(0) = '1') then --控制流水灯工作/停止
led_direction <= '0'; --锁存键值
end if;
end if;
end process;
--320ms计数
process(clk,rst_n)
begin
if (rst_n = '0') then --异步复位
cnt320ms <= x000000;
elsif (clk'event and clk = '1') then --时钟上升沿
if (cnt320ms < 10#16000000#) then --320ms计数
cnt320ms <= cnt320ms+1;
else
cnt320ms <= x000000;
end if;
end if;
end process;
--led显示控制
process(clk,rst_n)
begin
if (rst_n = '0') then --异步复位
led_out <= 0001;
elsif (clk'event and clk = '1') then --时钟上升沿
if (cnt320ms = 10#16000000# and led_display = '1') then --每320ms做一次led移位判断
if (led_direction = '1') then --右移
led_out <= led_out(0) & led_out(3) & led_out(2) & led_out(1);
--led_out <= led_out sla 1;
else --左移
led_out <= led_out(2) & led_out(1) & led_out(0) & led_out(3);
--led_out <= led_out sra 1;
end if;
end if;
end if;
end process;
end architecture key_control_of_led;
为什么要推广智慧路灯
MEMS器件发展势不可挡:未来MEMS市场将持续增长
小米 Poco F2预热:搭载高通骁龙 732G SoC、神似 Redmi K30 4G
3D打印核心部件努力实现国产化,大族激光谈SLM增材制造技术
英特尔联合Verizon 展示行业领先 vRAN 解决方案
BJ-EPM CPLD开发板:VHDL入门例程3
GPS接收机高频通道的系统设计及仿真研究
分辨PCB板层数技巧
PC行业衰退长达五年 联想老大的位置拱手相让
Garmin在全球智能手表出货收入中的份额增加到9.4%
政策引领新能源汽车走高能量密度、高续航里程的技术发展路线
CAN总线精品文章合集
华为首次曝光AI战略!
MicroGen振动能量收集器实现了Linear无线传感器网络
苹果正在研制的Micro LED显示屏到底是什么?
区块链技术被认为是下一代颠覆性的核心技术
艾迈斯半导体推出基于四段3.5mm音频接口的降噪耳机技术
高精度定位研究:城市NOA驱动下的高精度定位发展趋势
基于腔模理论的双频圆极化GNSS天线设计
移动机器人正式加入泰达汽车制造