资讯动态

状态机实现电子门锁

发布时间:2026/8/4 13:40:58 来源:尧图企业网站定制
文章目录一.功能描述二.模块图三.状态转移图四.设计思路五.代码六.引脚配置一.功能描述设计密码为1234的电子门锁4个按键分别对应密码的四个位例如key[0]表示密码第一位每按下一次该位加一。按错需要蜂鸣器响并回到初态。输入对密码led灯0.3s闪烁。二.模块图三.状态转移图四.设计思路状态空间设置初始状态IDLE对了一位的状态RIGHT_1,对了两位的状态RIGHT_2,对了三位的状态RIGHT_3,对了四位的状态RIGHT_4和错误状态。动作空间IDLE状态灯全灭RIGHT_1状态灯亮1个RIGHT_2状态灯亮2个RIGHT_3状态灯亮3个RIGHT_4状态灯0.3s从1111-0000闪烁WRONG状态蜂鸣器响。设置计数器分别计算按键按下的次数。状态转移条件IDLE_RIGHT_1按键key[0]按下1次RIGHT_1_RIGHT_2按键key[1]按下2次RIGHT_2_RIGHT_3按键key[2]按下3次RIGHT_3_RIGHT_4按键key[3]按下4次。RIGHT_4_IDLE这里我设置按下key[1]返回IDLE。IDLE_WRONG,RIGHT_1_WRONG,RIGHT_2_WRONG,RIGHT_3_WRONG分别是该状态下出错的情况。WRONG_IDLE为计满0.5s。0.5s计数器从WRONG状态开始计数当回到IDLE态停止计数。0.3s计数器从RIGHT_4状态开始计数五.代码key_debounce/**************************************功能介绍*********************************** Date : 2023年7月28日14:30:48 Author : Alegg xy. Version : 1.0 Description: 四位按键消抖模块 *********************************************************************************/ //---------模块及端口声名------------------------------------------------------ module key_debounce #(parameter WIDTH 4, parameter DELAY_20MS 1000_000 )( input clk , input rst_n , input [WIDTH-1:0] key_in , output [WIDTH-1:0] key_out ); //---------参数定义--------------------------------------------------------- reg [WIDTH-1:0] key_out_r; //状态机参数定义 localparam IDLE 4b0001,//空闲状态 FILETER_DOWN 4b0010,//按键按下抖动状态 HOLD_DOWN 4b0100,//按下稳定按下状态 FILTER_UP 4b1000;//按键释放抖动状态 //---------内部信号定义----------------------------------------------------- reg [3:0] cstate ;//现态 reg [3:0] nstate ;//次态 reg [WIDTH-1:0] key_r0 ;//同步打拍 reg [WIDTH-1:0] key_r1 ; reg [WIDTH-1:0] key_r2 ; wire [WIDTH-1:0] n_edge ;//下降沿 wire [WIDTH-1:0] p_edge ;//上升沿 reg [19:0] cnt_20ms ;//20ms计数器 wire add_cnt_20ms; wire end_cnt_20ms; //状态转移条件定义 wire idle2filter_down ; wire fiter_down2hold_down ; wire hold_down2filter_up ; wire filter_up2idle ; //**************************************************************** //--cstate //**************************************************************** //第一段时序逻辑描述状态转移 always (posedge clk or negedge rst_n)begin if(!rst_n)begin cstate IDLE;//复位的初始状态 end else begin cstate nstate; end end //第二段组合逻辑描述状态转移规律和状态转移条件 always (*) begin case(cstate) IDLE : begin if(idle2filter_down)begin nstate FILETER_DOWN; end else begin nstate cstate; // state_n IDLE; end end FILETER_DOWN : begin if(fiter_down2hold_down)begin nstate HOLD_DOWN; end else begin nstate cstate; end end HOLD_DOWN : begin if(hold_down2filter_up)begin nstate FILTER_UP; end else begin nstate cstate; end end FILTER_UP : begin if(filter_up2idle)begin nstate IDLE; end else begin nstate cstate; end end default : nstate IDLE; endcase end assign idle2filter_down cstate IDLE n_edge; assign fiter_down2hold_down cstate FILETER_DOWN end_cnt_20ms; assign hold_down2filter_up cstate HOLD_DOWN p_edge; assign filter_up2idle cstate FILTER_UP end_cnt_20ms; //**************************************************************** //--n_edge、p_edge //**************************************************************** always (posedge clk or negedge rst_n)begin if(!rst_n)begin key_r0 {WIDTH{1b1}}; key_r1 {WIDTH{1b1}}; key_r2 {WIDTH{1b1}}; end else begin key_r0 key_in; key_r1 key_r0; key_r2 key_r1; end end assign n_edge ~key_r1 key_r2; assign p_edge ~key_r2 key_r1; //**************************************************************** //--cnt_20ms //**************************************************************** always (posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_20ms d0; end else if(add_cnt_20ms)begin if(end_cnt_20ms)begin cnt_20ms d0; end else begin cnt_20ms cnt_20ms 1b1; end end end assign add_cnt_20ms cstate FILETER_DOWN || cstate FILTER_UP; assign end_cnt_20ms add_cnt_20ms cnt_20ms DELAY_20MS - 1; //**************************************************************** //--key_out //**************************************************************** always (posedge clk or negedge rst_n)begin if(!rst_n)begin key_out_r d0; end else if(hold_down2filter_up)begin key_out_r ~key_r2; end else begin key_out_r d0; end end assign key_out key_out_r; endmodulelock_ctrl/**************************************功能介绍*********************************** Date : 2023年7月28日14:30:56 Author : Alegg xy. Version : 1.0 Description: 控制密码锁 *********************************************************************************/ //---------模块及端口声名------------------------------------------------------ module lock_ctrl( input clk , input rst_n , input [3:0] key , output beep , output [3:0] led ); //---------参数定义--------------------------------------------------------- parameter MAX_300ms 24d15_000_000;//0.3s parameter MAX 26d25_000_000;//0.5s parameter MAX_TIME 4d9; //---------内部信号定义----------------------------------------------------- reg [3:0] led_r; reg [3:0] beep_r; //状态空间 localparam IDLE 3d1,//初始状态 RIGHT_1 3d2,//对了一位状态 RIGHT_2 3d3,//对了两位状态 RIGHT_3 3d4,//对了三位状态 RIGHT_4 3d5,//全对状态 WRONG 3d6;//出错状态 reg [2:0] cstate ;//现态 reg [2:0] nstate ;//次态 //0.5s计数器 reg [25:0] cnt ; wire add_cnt ; wire end_cnt ; always (posedge clk or negedge rst_n)begin if(!rst_n)begin cnt 26d0; end else if(add_cnt)begin if(end_cnt)begin cnt 26d0; end else begin cnt cnt 1b1; end end end assign add_cnt cstate WRONG; assign end_cnt add_cnt cnt MAX - 1d1; //0.3s计数器 reg [26:0] cnt_300ms ; wire add_cnt_300ms ; wire end_cnt_300ms ; always (posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_300ms d0; end else if(add_cnt_300ms)begin if(end_cnt_300ms)begin cnt_300ms 26d0; end else begin cnt_300ms cnt_300ms 1b1; end end end assign add_cnt_300ms cstate RIGHT_4; assign end_cnt_300ms add_cnt_300ms cnt_300ms MAX_300ms - 1d1; //状态转移条件 //成功 wire IDLE_RIGHT_1 ; wire RIGHT_1_RIGHT_2; wire RIGHT_2_RIGHT_3; wire RIGHT_3_RIGHT_4; wire RIGHT_4_IDLE ; //失败回到WRONG wire IDLE_WRONG ; wire RIGHT_1_WRONG ; wire RIGHT_2_WRONG ; wire RIGHT_3_WRONG ; wire WRONG_IDLE ; //key_in[0]计数器 reg [3:0] cnt_key0; always (posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_key0 d0; end else if(key[0] cnt_key0 MAX_TIME)begin cnt_key0 cnt_key0 1d1; end else if(cstate IDLE)begin cnt_key0 1d0; end else begin cnt_key0 cnt_key0; end end //key_in[1]计数器 reg [3:0] cnt_key1; always (posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_key1 d0; end else if(key[1] cnt_key1 MAX_TIME)begin cnt_key1 cnt_key1 1d1; end else if(cstate IDLE)begin cnt_key1 1d0; end else begin cnt_key1 cnt_key1; end end //key_in[2]计数器 reg [3:0] cnt_key2; always (posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_key2 d0; end else if(key[2] cnt_key2 MAX_TIME)begin cnt_key2 cnt_key2 1d1; end else if(cstate IDLE)begin cnt_key2 1d0; end else begin cnt_key2 cnt_key2; end end //key_in[3]计数器 reg [3:0] cnt_key3; always (posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_key3 d0; end else if(key[3] cnt_key3 MAX_TIME)begin cnt_key3 cnt_key3 1d1; end else if(cstate IDLE)begin cnt_key3 1d0; end else begin cnt_key3 cnt_key3; end end assign IDLE_RIGHT_1 cstate IDLE cnt_key0 1 ; assign RIGHT_1_RIGHT_2 cstate RIGHT_1 cnt_key1 2; assign RIGHT_2_RIGHT_3 cstate RIGHT_2 cnt_key2 3; assign RIGHT_3_RIGHT_4 cstate RIGHT_3 cnt_key3 4; assign RIGHT_4_IDLE cstate RIGHT_4 key[1] ; assign IDLE_WRONG (cstate IDLE ) (key[1] || key[2] || key[3]); assign RIGHT_1_WRONG (cstate RIGHT_1) (cnt_key1 2) (key[0] || key[2] || key[3]); assign RIGHT_2_WRONG (cstate RIGHT_2) (cnt_key2 3) (key[0] || key[1] || key[3]); assign RIGHT_3_WRONG (cstate RIGHT_3) (cnt_key3 4) (key[0] || key[1] || key[2]); assign WRONG_IDLE end_cnt; //第一段时序逻辑描述状态转移 always (posedge clk or negedge rst_n)begin if(!rst_n)begin cstate IDLE; end else begin cstate nstate; end end //第二段组合逻辑描述状态转移规律和状态转移条件 always (*) begin case(cstate) IDLE :begin if (IDLE_RIGHT_1) begin nstate RIGHT_1; end else if(IDLE_WRONG) begin nstate WRONG; end else begin nstate cstate; end end RIGHT_1 :begin if (RIGHT_1_RIGHT_2) begin nstate RIGHT_2; end else if(RIGHT_1_WRONG) begin nstate WRONG; end else begin nstate cstate; end end RIGHT_2 :begin if (RIGHT_2_RIGHT_3) begin nstate RIGHT_3; end else if(RIGHT_2_WRONG) begin nstate WRONG; end else begin nstate cstate; end end RIGHT_3 :begin if (RIGHT_3_RIGHT_4) begin nstate RIGHT_4; end else if(RIGHT_3_WRONG) begin nstate WRONG; end else begin nstate cstate; end end RIGHT_4 :begin if (RIGHT_4_IDLE) begin nstate IDLE; end else begin nstate RIGHT_4; end end WRONG :begin if (WRONG_IDLE) begin nstate IDLE; end else begin nstate WRONG; end end default : nstate IDLE; endcase end reg [3:0] led_r0; //每0.3s从1111-0000闪烁的灯 always (posedge clk or negedge rst_n) begin if (!rst_n) begin led_r0 4b1111; end else if (end_cnt_300ms) begin led_r0 ~led_r0; end else begin led_r0 led_r0; end end //控制beep always (posedge clk or negedge rst_n) begin if (!rst_n) begin beep_r 1b1; end else if(cstate WRONG) begin beep_r 1b0; end else begin beep_r 1b1; end end //第三段描述输出时序逻辑或组合逻辑皆可 always (posedge clk or negedge rst_n)begin if(!rst_n)begin led_r 4d0000; end else begin case (cstate) IDLE :led_r 4b0000; RIGHT_1 :led_r 4b0001; RIGHT_2 :led_r 4b0011; RIGHT_3 :led_r 4b0111; RIGHT_4 :led_r led_r0; default: led_r 4b0000; endcase end end assign led led_r; assign beep beep_r; endmoduletop_fsm_lock/**************************************功能介绍*********************************** Date : 2023年7月28日15:14:23 Author : Alegg xy. Version : 1.0 Description: 顶层模块 *********************************************************************************/ //---------模块及端口声名------------------------------------------------------ module top_fsm_lock( input clk , input rst_n , input [3:0] key_in , output beep , output [3:0] led ); //---------参数定义--------------------------------------------------------- wire [3:0] key_link; key_debounce u_key_debounce( .clk (clk), .rst_n (rst_n), .key_in (key_in), .key_out (key_link) ); lock_ctrl u_lock_ctrl( .clk (clk), .rst_n (rst_n), .key (key_link), .beep (beep), .led (led) ); endmodule六.引脚配置

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价