赞
踩
使用按键控制开发板上一个led灯的亮灭,当按键按下的时候led灯就亮,当再一次按下按键的时候led就不亮了。由于按键存在抖动,按键松开的时候led灯就不亮,所以需要一个消抖模块对按键消抖
module key_led ( input wire clk, input wire rst_n, input wire[3:0] key, output reg[3:0] led ); parameter TIME_0_2S = 10_000_000; // reg[24:0] cnt_0_2S; reg[1:0] state; //=================0.2s计时====================// always @(posedge clk or negedge rst_n) begin if(!rst_n)begin cnt_0_2S<=24'd0; end else if(cnt_0_2S == TIME_0_2S - 1)begin cnt_0_2S<=24'd0; end else begin cnt_0_2S<=cnt_0_2S+1'b1; end end //=================state=================// always @(posedge clk or negedge rst_n) begin if(!rst_n)begin state<=2'b00; end else if(cnt_0_2S == TIME_0_2S - 1) begin state<=state+1'b1; end else begin state<=state; end end //================按键控制流水灯===============// always @(posedge clk or negedge rst_n) begin if(!rst_n)begin led<=4'b0000; end else if(~key[0]) begin case (state) 2'd0:led<=4'b0001; 2'd1:led<=4'b0010; 2'd2:led<=4'b0100; 2'd3:led<=4'b1000; endcase end else if(~key[1]) begin case (state) 2'd0:led<=4'b1000; 2'd1:led<=4'b0100; 2'd2:led<=4'b0010; 2'd3:led<=4'b0001; endcase end else if(~key[2]) begin case (state) 2'd0:led<=4'b1111; 2'd1:led<=4'b0000; 2'd2:led<=4'b1111; 2'd3:led<=4'b0000; endcase end else if(~key[3]) begin case (state) 2'd0:led<=4'b1111; 2'd1:led<=4'b1111; 2'd2:led<=4'b1111; 2'd3:led<=4'b1111; endcase end else begin led<=4'b0000; end end endmodule
// ----------------------------------------------------------------------------- // Copyright (c) 2014-2023 All rights reserved // ----------------------------------------------------------------------------- // Author : 辣子鸡味的句橘子,331197689@qq.com // File : key_debounce.v // Create : 2023-07-14 10:36:44 // Revise : 2023-07-14 10:36:44 // Editor : sublime text4, tab size (4) // ----------------------------------------------------------------------------- module key_debounce( input wire clk, input wire rst_n, input wire[3:0] key_in,//四个按键信号输入 output reg[3:0] key_out//四个按键信号消抖输出 ); parameter TIME_20MS = 1000_000; reg[19:0] cnt;//20ms计数器 wire add_cnt;//计数开始 wire ent_cnt;//计数终止 wire nedge;//下降沿检测 reg[3:0] key_in_r0;//同步key_in输入信号 reg[3:0] key_in_r1;//延迟一个周期 reg[3:0] key_in_r2;//延迟两个周期 reg flag;//消抖开始标志信号 //计数器模块,当addent满足时开始计数,检测到下降沿重新计数,end_ent满足时停止计数,消抖完成 always @(posedge clk or negedge rst_n) begin if(~rst_n) begin cnt<=20'd0; end else if(add_cnt)begin if(ent_cnt)begin cnt<=20'd0; end else if(nedge)begin cnt<=20'd0; end else begin cnt<=cnt+1; end end else begin cnt<=cnt; end end assign add_cnt = flag;//计数开始条件 assign end_cnt = (cnt == TIME_20MS - 1)&&add_cnt;//终止结束条件,当满足计时到20ms,且满足计时条件时成立 //信号延时模块 always @(posedge clk or negedge rst_n) begin if(~rst_n) begin key_in_r0<=4'b1111; key_in_r1<=4'b1111; key_in_r2<=4'b1111; end else begin key_in_r0<=key_in; key_in_r1<=key_in_r0; key_in_r2<=key_in_r1; end end //检测下降沿,当任意一个按键出现下降沿都会被检测到 assign nedge = (~key_in_r1[0]&key_in_r2[0])||(~key_in_r1[1]&key_in_r2[1])||(~key_in_r1[2]&key_in_r2[2])||(~key_in_r1[3]&key_in_r2[3]); //消抖开始模块 always @(posedge clk or negedge rst_n) begin if(~rst_n) begin flag<=1'b0; end else if(nedge)begin//当出现下降沿开始消抖 flag<=1'b1; end else if(end_cnt)begin//当end_cnt满足时停止消抖 flag<=1'b0; end else begin flag<=flag; end end //输出信号赋值模块,当消抖完毕标志按键按下,出现一个脉冲信号表示按键按下 always @(posedge clk or negedge rst_n) begin if(~rst_n) begin key_out<=4'b1111;//默认为高电瓶 end else if(end_cnt)begin key_out<=key_in;//稳定信号赋值 end else begin key_out<=4'b1111;//其他信号默认为高电平 end end endmodule
module key_top( input wire clk, input wire rst_n, input wire[3:0] key, output wire[3:0] led ); wire[3:0] key_r; key_debounce inst_key_debounce ( .clk(clk), .rst_n(rst_n), .key(key), .key_r(key_r)); key_led inst_key_led ( .clk(clk), .rst_n(rst_n), .key(key_r), .led(led)); endmodule
module key_top_tb(); reg clk; reg rst_n; reg[3:0] key; wire[3:0] led; wire[3:0] key_r; parameter SYS_CLK = 20; parameter TIME = 100; always #(SYS_CLK/2) clk = ~clk; initial begin clk=1'b0; rst_n=1'b0; #(2*SYS_CLK); rst_n=1'b1; key = 4'b1111; #(2*SYS_CLK); repeat (19) begin key[0] = ~key[0]; #(2*SYS_CLK); end key[0] = 1'b0; #(400*SYS_CLK); $stop; end key_debounce #(.TIME_20MS(TIME)) inst_key_bounce ( .clk(clk), .rst_n(rst_n), .key(key), .key_r(key_r)); key_led #(.TIME_0_2S(TIME)) inst_key_led ( .clk(clk), .rstn(rstn), .key(key), .led(led)); endmodule
总的来说编写不算复杂,需要注意的是模块之间的连接和按键消抖模块
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。