From c8e0f43589ca98bccbb261980b345f701486e593 Mon Sep 17 00:00:00 2001 From: lincaigui <18166451309@163.com> Date: Tue, 23 Apr 2024 13:32:34 +0800 Subject: [PATCH] finish --- readme.md | 3 ++ rtl/key_filter.v | 131 +++++++++++++++++++++++++++++++++++++++++++++++ rtl/top.v | 41 +++++++++++++++ tcl/C4_pin.tcl | 114 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 289 insertions(+) create mode 100644 readme.md create mode 100644 rtl/key_filter.v create mode 100644 rtl/top.v create mode 100644 tcl/C4_pin.tcl diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..f211389 --- /dev/null +++ b/readme.md @@ -0,0 +1,3 @@ +## FPGA有限状态机按键消抖 +### 1.有限状态机 +### 2.按键消抖 \ No newline at end of file diff --git a/rtl/key_filter.v b/rtl/key_filter.v new file mode 100644 index 0000000..7cd0dc9 --- /dev/null +++ b/rtl/key_filter.v @@ -0,0 +1,131 @@ +//状态机消抖模块 +module key_filter #(parameter KEY_W = 4,DELAY = 1000_000)(//20ms + input sys_clk , + input sys_rst_n , + input [KEY_W-1:0] key_in , + output reg [KEY_W-1:0] key_out +); + //状态机参数定义 + localparam IDLE = 4'b0001,//初始状态 + DOWN = 4'b0010,//滤除下降沿抖动 + HOLD = 4'b0100,//保持稳定状态 + UP = 4'b1000;//滤除上升沿抖动 + + //中间信号定义 + reg [19:0] cnt ;//计数20ms + wire add_cnt ; + wire end_cnt ; + + reg [3:0] state_c ;//现态 + reg [3:0] state_n ;//次态 + + reg [KEY_W-1:0] key_r0 ;//同步打拍寄存器 + reg [KEY_W-1:0] key_r1 ; + reg [KEY_W-1:0] key_r2 ; + + wire [KEY_W-1:0] nedge ;//下降沿检测 + wire [KEY_W-1:0] pedge ;//上升沿检测 + + wire idle2down;//状态机跳转条件 + wire down2idle; + wire down2hold; + wire hold2up ; + wire up2idle ; + + //状态机 + always @(posedge sys_clk or negedge sys_rst_n)begin + if(!sys_rst_n)begin + state_c <= IDLE; + end + else begin + state_c <= state_n; + end + end + + always @(*)begin + case (state_c) + IDLE :begin + if(idle2down) + state_n = DOWN; + else + state_n = state_c; + end + DOWN :begin + if(down2idle) + state_n = IDLE; + else if(down2hold) + state_n = HOLD; + else + state_n = state_c; + end + HOLD :begin + if(hold2up) + state_n = UP; + else + state_n = state_c; + end + UP :begin + if(up2idle) + state_n = IDLE; + else + state_n = state_c; + end + default:state_n = IDLE; + endcase + end + + assign idle2down = state_c == IDLE && (nedge );//(nedge != 0) + assign down2idle = state_c == DOWN && (pedge );//(pedge != 0) + assign down2hold = state_c == DOWN && (end_cnt);// && pedge == 0; + assign hold2up = state_c == HOLD && (pedge );//(pedge != 0) + assign up2idle = state_c == UP && (end_cnt); + + //计数器 + always @(posedge sys_clk or negedge sys_rst_n)begin + if(!sys_rst_n)begin + cnt <= 0; + end + else if(add_cnt)begin + if(end_cnt)begin + cnt <= 0; + end + else begin + cnt <= cnt + 1; + end + end + end + assign add_cnt = (state_c == DOWN) || (state_c == UP); + assign end_cnt = add_cnt && (cnt == DELAY-1 || down2idle); + + //同步 打拍 + always @(posedge sys_clk or negedge sys_rst_n)begin + if(!sys_rst_n)begin + key_r0 <= {KEY_W{1'b1}}; + key_r1 <= {KEY_W{1'b1}}; + key_r2 <= {KEY_W{1'b1}}; + end + else begin + key_r0 <= key_in; //同步按键输入信号 + key_r1 <= key_r0; //打拍 + key_r2 <= key_r1; + end + end + //r1当前状态,r2上一个状态 + assign nedge = ~key_r1 & key_r2;/*(~key_r1[0] & key_r2[0]) || (~key_r1[1] & key_r2[1]);*///两种写法都行 + assign pedge = key_r1 & ~key_r2;/*(key_r1[0] & ~key_r2[0]) || (key_r1[1] & ~key_r2[1]);*/ + + //key_down + always @(posedge sys_clk or negedge sys_rst_n)begin + if(!sys_rst_n)begin + key_out <= 0; + end + else if(down2hold)begin + key_out <= ~key_r1; //~key_r2 + //key_down <= down2hold?~key_r1:0; + end + else begin + key_out <= 0; + end + end + +endmodule diff --git a/rtl/top.v b/rtl/top.v new file mode 100644 index 0000000..284ebee --- /dev/null +++ b/rtl/top.v @@ -0,0 +1,41 @@ +module top( + input wire sys_clk , + input wire sys_rst_n , + input wire key_in , + + output reg led +); +wire key_out; + +//异步复位,复位作用是对D触发器数据清零 +always @(posedge sys_clk or negedge sys_rst_n)begin + if(!sys_rst_n)begin + led <= 1'b0; + end + else if(key_out)begin + led <= ~led; + end + else begin + led <= led; + end +end + +//同步复位,复位作用是对D触发器数据清零 +// always @(posedge sys_clk) begin + // if(!sys_rst_n)begin + // led <= 1'b0; + // end + // else if(key_out)begin + // led <= ~led; + // end + // else begin + // led <= led; + // end +// end +key_filter #(.KEY_W(1), .DELAY(1000_000)) key_filter_inst(// +.sys_clk (sys_clk), +.sys_rst_n (sys_rst_n), +.key_in (key_in), +.key_out (key_out) +); +endmodule \ No newline at end of file diff --git a/tcl/C4_pin.tcl b/tcl/C4_pin.tcl new file mode 100644 index 0000000..4fa00ee --- /dev/null +++ b/tcl/C4_pin.tcl @@ -0,0 +1,114 @@ +#引脚参数导入脚本 +#时钟、复位 +set_location_assignment PIN_E1 -to sys_clk +set_location_assignment PIN_E15 -to sys_rst_n + +#UART +#set_location_assignment PIN_M2 -to uart_rx +#set_location_assignment PIN_G1 -to uart_tx + +#LED +#set_location_assignment PIN_D16 -to led[3] +#set_location_assignment PIN_F15 -to led[2] +# set_location_assignment PIN_F16 -to led[1] +set_location_assignment PIN_G15 -to led + +#独立按键 +# set_location_assignment PIN_M16 -to key_in[2] +# set_location_assignment PIN_M15 -to key_in[1] +set_location_assignment PIN_E16 -to key_in + +#数码管选段 +# set_location_assignment PIN_B7 -to seg_led[0] +# set_location_assignment PIN_A8 -to seg_led[1] +# set_location_assignment PIN_A6 -to seg_led[2] +# set_location_assignment PIN_B5 -to seg_led[3] +# set_location_assignment PIN_B6 -to seg_led[4] +# set_location_assignment PIN_A7 -to seg_led[5] +# set_location_assignment PIN_B8 -to seg_led[6] +# set_location_assignment PIN_A5 -to seg_led[7] + +#数码管片选w· +# set_location_assignment PIN_A4 -to sel_led[0] +# set_location_assignment PIN_B4 -to sel_led[1] +# set_location_assignment PIN_A3 -to sel_led[2] +# set_location_assignment PIN_B3 -to sel_led[3] +# set_location_assignment PIN_A2 -to sel_led[4] +# set_location_assignment PIN_B1 -to sel_led[5] + +#ds18b20 +# set_location_assignment PIN_E6 -to dq + +#蜂鸣器 +#set_location_assignment PIN_J1 -to buzzer + +#SDRAM + #地址 +#set_location_assignment PIN_T8 -to addr[0] +#set_location_assignment PIN_P9 -to addr[1] +#set_location_assignment PIN_T9 -to addr[2] +#set_location_assignment PIN_R9 -to addr[3] +#set_location_assignment PIN_L16 -to addr[4] +#set_location_assignment PIN_L15 -to addr[5] +#set_location_assignment PIN_N16 -to addr[6] +#set_location_assignment PIN_N15 -to addr[7] +#set_location_assignment PIN_P16 -to addr[8] +#set_location_assignment PIN_P15 -to addr[9] +#set_location_assignment PIN_R8 -to addr[10] +#set_location_assignment PIN_R16 -to addr[11] +#set_location_assignment PIN_T15 -to addr[12] + + #数据 +#set_location_assignment PIN_R5 -to dq[0] +#set_location_assignment PIN_T4 -to dq[1] +#set_location_assignment PIN_T3 -to dq[2] +#set_location_assignment PIN_R3 -to dq[3] +#set_location_assignment PIN_T2 -to dq[4] +#set_location_assignment PIN_R1 -to dq[5] +#set_location_assignment PIN_P2 -to dq[6] +#set_location_assignment PIN_P1 -to dq[7] +#set_location_assignment PIN_R13 -to dq[8] +#set_location_assignment PIN_T13 -to dq[9] +#set_location_assignment PIN_R12 -to dq[10] +#set_location_assignment PIN_T12 -to dq[11] +#set_location_assignment PIN_T10 -to dq[12] +#set_location_assignment PIN_R10 -to dq[13] +#set_location_assignment PIN_T11 -to dq[14] +#set_location_assignment PIN_R11 -to dq[15] + + #bank +#set_location_assignment PIN_R7 -to bank[0] +#set_location_assignment PIN_T7 -to bank[1] + + #dqm +#set_location_assignment PIN_N2 -to dqm[0] +#set_location_assignment PIN_T14 -to dqm[1] + + #时钟 +#set_location_assignment PIN_R4 -to sdram_clk + + #控制信号 +#set_location_assignment PIN_R14 -to cke +#set_location_assignment PIN_T6 -to cs_n +#set_location_assignment PIN_R6 -to ras_n +#set_location_assignment PIN_T5 -to cas_n +#set_location_assignment PIN_N1 -to we_n + + +#flash +#set_location_assignment PIN_H2 -to miso +#set_location_assignment PIN_C1 -to mosi +#set_location_assignment PIN_H1 -to sclk +#set_location_assignment PIN_D2 -to cs_n + +#EEPROM +#set_location_assignment PIN_L2 -to sda +#set_location_assignment PIN_L1 -to sclk + +#VGA + +#摄像头 + + + +