改进电子门锁并加入数码管

一.前言

  • 前文已经发过电子门锁初步设计,但是后来发现有缺陷:多错误几次就很容易猜到正确的密码,有损安全性,于是本文做改进设计,并补充加入数码管显示键入密码功能

二.功能描述

  • 1.按下key[0]密码+1

    2.按下key[1]密码-1

    3.按下key[2]确认该位密码并跳转到下一位密码输入

    4.输入第一位密码时,数码管显示(AA–(密码值))

    5.输入第二位密码时,数码管显示(BB–(密码值))

    6.输入第三位密码时,数码管显示(CC–(密码值))

    7.输入第四位密码时,数码管显示(DD–(密码值))

    8.密码正确时,数码管显示(111111)

    9.密码错误时,数码管显示(FFFFFF)

三.状态转移图

在这里插入图片描述

四.模块设计图

在这里插入图片描述

五.设计思路

  • 状态转移条件:重点关注按下key[2](确认按键);比较键入值和设定密码;延时10s条件。
    在这里插入图片描述

  • 设置1ms计数器,并使sel每隔1ms进行位拼接{sel[4:0],sel[5]}的操作,由于余晖效应,肉眼是无法辨别sel的变换,视觉上显示的是数码管全亮的状态。

  • 每一个状态观测sel值(case(sel)),不同的sel值让对应的数码管点亮需求的显示。

六.代码

  • key_debounce.v
/**************************************功能介绍***********************************
Date	: 2023年8月1日16:55:52
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         = 4'b0001,//空闲状态
                FILETER_DOWN = 4'b0010,//按键按下抖动状态
                HOLD_DOWN    = 4'b0100,//按下稳定按下状态
                FILTER_UP    = 4'b1000;//按键释放抖动状态
    
//---------<内部信号定义>-----------------------------------------------------
    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{1'b1}};
            key_r1 <= {WIDTH{1'b1}};
            key_r2 <= {WIDTH{1'b1}};
        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 + 1'b1;
            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;
endmodule
  • fsm_lock.v
/**************************************功能介绍***********************************
Date	:2023年8月1日17:01:23 
Author	: Alegg xy.
Version	: 1.0
Description: 
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module fsm_lock( 
    input				clk		,
    input				rst_n	,
    input		[3:0]	key		,
    output	reg [5:0]	sel	    ,
    output	reg [7:0]	seg	    ,
    output  reg [3:0]   led     
);								 
//---------<参数定义>--------------------------------------------------------- 
    //状态机参数定义
    localparam  IDLE   = 7'b000_0001,//空闲状态
                RIGHT_1= 7'b000_0010,//键入第1位密码值状态
                RIGHT_2= 7'b000_0100,//键入第2位密码值状态
                RIGHT_3= 7'b000_1000,//键入第3位密码值状态
                RIGHT_4= 7'b001_0000,//键入第4位密码值状态
                SUCESS = 7'b010_0000,//键入密码正确状态
                FAILED = 7'b100_0000;//键入密码错误状态

    //密码参数定义
    localparam  PASSWORD = 16'h1234;

    //时间参数定义
    parameter   TIME_10S = 500_000_000;//10s
    parameter   TIME_300MS = 15_000_000;//30Oms
    parameter MAX_1ms = 16'd50000;//1ms
//---------<内部信号定义>-----------------------------------------------------
    reg 	[6:0]	cstate     ;//现态
    reg	    [6:0]	nstate     ;//次态

    reg     [3:0]   value_1     ;//键入第1位的数值
    reg     [3:0]   value_2     ;//键入第2位的数值
    reg     [3:0]   value_3     ;//键入第3位的数值
    reg     [3:0]   value_4     ;//键入第4位的数值
    wire    [15:0]  key_value   ;//键入的4位密码值

    reg		[31:0]	cnt_10s	   	;
    wire			add_cnt_10s	;
    wire			end_cnt_10s	;
    reg		[25:0]	cnt_300ms	   	;
    wire			add_cnt_300ms	;
    wire			end_cnt_300ms	;
    

    reg     [3:0]   led_flow    ;//流水灯
    reg     [3:0]   led_light   ;//闪烁

    reg [3:0]   data;//存取该位数值

    //1ms计数器
    reg			[15:0]	cnt_1ms	   	;
    wire				add_cnt_1ms	;
    wire				end_cnt_1ms	;
    
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_1ms <= 16'd0;
        end 
        else if(add_cnt_1ms)begin 
            if(end_cnt_1ms)begin 
                cnt_1ms <= 16'd0;
            end
            else begin 
                cnt_1ms <= cnt_1ms + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_1ms = 1'b1;
    assign end_cnt_1ms = add_cnt_1ms && cnt_1ms == MAX_1ms - 1'd1;
    
    //数码管位选
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            sel <= 6'b111_110;//循环移位实现时,需要给位选赋初值
        end 
        else if(end_cnt_1ms)begin 
            sel <= {sel[4:0],sel[5]};//循环左移
        end 
    end
    
    
    
    //状态转移条件参数定义
    wire            IDLE_RIGHT_1            ;
    wire            RIGHT_1_RIGHT_2         ;
    wire            RIGHT_2_RIGHT_3         ;
    wire            RIGHT_3_RIGHT_4         ;
    wire            RIGHT_4_SUCCESS         ;
    wire            RIGHT_4_FAILED          ;
    wire            SUCCESS_IDLE            ;
    wire            FAILED_IDLE             ;
    
//****************************************************************
//--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(IDLE_RIGHT_1)begin
                    nstate = RIGHT_1;
                end
                else begin
                    nstate = cstate;
                end
            end
            RIGHT_1: begin
                if(RIGHT_1_RIGHT_2)begin
                    nstate = RIGHT_2;
                end
                else begin
                    nstate = cstate;
                end
            end
            RIGHT_2: begin
                if(RIGHT_2_RIGHT_3)begin
                    nstate = RIGHT_3;
                end
                else begin
                    nstate = cstate;
                end
            end
            RIGHT_3: begin
                if(RIGHT_3_RIGHT_4)begin
                    nstate = RIGHT_4;
                end
                else begin
                    nstate = cstate;
                end
            end
            RIGHT_4: begin
                if(RIGHT_4_SUCCESS)begin
                    nstate = SUCESS;
                end
                else if(RIGHT_4_FAILED)begin
                    nstate = FAILED;
                end
                else begin
                    nstate = cstate;
                end
            end
            SUCESS : begin
                if(SUCCESS_IDLE)begin
                    nstate = IDLE;
                end
                else begin
                    nstate = cstate;
                end
            end
            FAILED : begin
                if(FAILED_IDLE)begin
                    nstate = IDLE;
                end
                else begin
                    nstate = cstate;
                end
            end
            default : nstate = IDLE;
        endcase
    end

    assign IDLE_RIGHT_1    = (cstate == IDLE   ) && 1'b1;
    assign RIGHT_1_RIGHT_2 = (cstate == RIGHT_1) && key[2];
    assign RIGHT_2_RIGHT_3 = (cstate == RIGHT_2) && key[2];
    assign RIGHT_3_RIGHT_4 = (cstate == RIGHT_3) && key[2];
    assign RIGHT_4_SUCCESS = (cstate == RIGHT_4) && key[2] && key_value == PASSWORD;
    assign RIGHT_4_FAILED  = (cstate == RIGHT_4) && key[2] && key_value != PASSWORD;
    assign SUCCESS_IDLE    = (cstate == SUCESS ) && end_cnt_10s;
    assign FAILED_IDLE     = (cstate == FAILED ) && end_cnt_10s;

//****************************************************************
//--value1~value4
//****************************************************************
    //value1
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            value_1 <= 'd0;
        end 
        else if(value_1 > 9)begin 
            value_1 <= 'd0;
        end 
        else if(cstate == RIGHT_1 && key[0])begin
            value_1 <= value_1 + 1'b1;
        end
        else if(cstate == RIGHT_1 && key[1])begin
            value_1 <= value_1 - 1'b1;
        end
    end

    //value2
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            value_2 <= 'd0;
        end 
        else if(value_2 > 9)begin 
            value_2 <= 'd0;
        end 
        else if(cstate == RIGHT_2 && key[0])begin
            value_2 <= value_2 + 1'b1;
        end
        else if(cstate == RIGHT_2 && key[1])begin
            value_2 <= value_2 - 1'b1;
        end
    end
    
    //value3
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            value_3 <= 'd0;
        end 
        else if(value_3 > 9)begin 
            value_3 <= 'd0;
        end 
        else if(cstate == RIGHT_3 && key[0])begin
            value_3 <= value_3 + 1'b1;
        end
        else if(cstate == RIGHT_3 && key[1])begin
            value_3 <= value_3 - 1'b1;
        end
    end

    //value_4
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            value_4 <= 'd0;
        end 
        else if(value_4 > 9)begin 
            value_4 <= 'd0;
        end 
        else if(cstate == RIGHT_4 && key[0])begin
            value_4 <= value_4 + 1'b1;
        end
        else if(cstate == RIGHT_4 && key[1])begin
            value_4 <= value_4 - 1'b1;
        end
    end

    assign key_value = {value_1,value_2,value_3,value_4};
    
//****************************************************************
//--cnt_10s
//****************************************************************   
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_10s <= 'd0;
        end 
        else if(add_cnt_10s)begin 
            if(end_cnt_10s)begin 
                cnt_10s <= 'd0;
            end
            else begin 
                cnt_10s <= cnt_10s + 1'b1;
            end 
        end
    end 
    
    assign add_cnt_10s = cstate == SUCESS | cstate == FAILED;
    assign end_cnt_10s = add_cnt_10s && cnt_10s == TIME_10S - 1;
    
//****************************************************************
//--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 <= 'd0;
            end
            else begin 
                cnt_300ms <= cnt_300ms + 1'b1;
            end 
        end
    end 
    
    assign add_cnt_300ms = cstate == SUCESS | cstate == FAILED;
    assign end_cnt_300ms = add_cnt_300ms && cnt_300ms == TIME_300MS - 1;
    
//****************************************************************
//--led成功全亮,失败流水
//****************************************************************
    //led_light
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            led_light <= 4'd0;
        end 
        else if(cstate == SUCESS && end_cnt_300ms)begin 
            led_light <= ~led_light;
        end 
    end

    //led_flow
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            led_flow <= 4'b0001;
        end 
        else if(cstate == FAILED && end_cnt_300ms)begin 
            led_flow <= {led_flow[2:0],led_flow[3]};
        end 
    end
    
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            led <= 4'b1111;
        end 
        else begin 
            case (cstate)
                IDLE   : led <= 4'b0000;
                RIGHT_1: begin
                    led <= 4'b0001;
                    case (sel)
                        6'b111_110 :data = 4'hA;
                        6'b111_101 :data = 4'hA;
                        6'b111_011 :data = 4'hE;
                        6'b110_111 :data = 4'hE;
                        6'b101_111 :data = 4'h0;
                        6'b011_111 :data = value_1;
                        default: data = 0;
                    endcase
                end
                RIGHT_2: begin
                    led <= 4'b0001;
                    case (sel)
                        6'b111_110 :data = 4'hB;
                        6'b111_101 :data = 4'hB;
                        6'b111_011 :data = 4'hE;
                        6'b110_111 :data = 4'hE;
                        6'b101_111 :data = 4'h0;
                        6'b011_111 :data = value_2;
                        default: data = 0;
                    endcase                    
                end
                RIGHT_3: begin
                    led <= 4'b0111;
                    case (sel)
                        6'b111_110 :data = 4'hC;
                        6'b111_101 :data = 4'hC;
                        6'b111_011 :data = 4'hE;
                        6'b110_111 :data = 4'hE;
                        6'b101_111 :data = 4'h0;
                        6'b011_111 :data = value_3;
                        default: data = 0;
                    endcase
                end
                RIGHT_4: begin
                    led <= 4'b1111;
                    case (sel)
                        6'b111_110 :data = 4'hD;
                        6'b111_101 :data = 4'hD;
                        6'b111_011 :data = 4'hE;
                        6'b110_111 :data = 4'hE;
                        6'b101_111 :data = 4'h0;
                        6'b011_111 :data = value_4;
                        default: data = 0;
                    endcase
                end
                SUCESS : begin
                    led <= led_light;
                    case (sel)
                        6'b111_110 :data = 4'd1;
                        6'b111_101 :data = 4'd1;
                        6'b111_011 :data = 4'd1;
                        6'b110_111 :data = 4'd1;
                        6'b101_111 :data = 4'd1;
                        6'b011_111 :data = 4'd1;
                        default: data = 0;
                    endcase
                end
                FAILED : begin
                    led <= led_flow;
                    case (sel)
                        6'b111_110 :data = 4'hF;
                        6'b111_101 :data = 4'hF;
                        6'b111_011 :data = 4'hF;
                        6'b110_111 :data = 4'hF;
                        6'b101_111 :data = 4'hF;
                        6'b011_111 :data = 4'hF;
                        default: data = 0;
                    endcase
                end
                default: led <= 4'b0000;
            endcase
        end 
    end    
    
    always @(*)begin 
            case (data)
                4'h0:seg <= 8'b1100_0000;
                4'h1:seg <= 8'b1111_1001;
                4'h2:seg <= 8'b1010_0100;
                4'h3:seg <= 8'b1011_0000;
                4'h4:seg <= 8'b1001_1001;
                4'h5:seg <= 8'b1001_0010;
                4'h6:seg <= 8'b1000_0010;
                4'h7:seg <= 8'b1111_1000;
                4'h8:seg <= 8'b1000_0000;
                4'h9:seg <= 8'b1001_0000;
                4'hA:seg <= 8'b1000_1000; 
                4'hB:seg <= 8'b1000_0011;
                4'hC:seg <= 8'b1100_0110;
                4'hD:seg <= 8'b1010_0001;
                4'hE:seg <= 8'b1011_1111;
                4'hF:seg <= 8'b1000_1110;
                default: seg <= 8'b1100_0000;
            endcase
    end
    
    
endmodule
  • top_fsm_lock.v
/**************************************功能介绍***********************************
Date	: 2023年8月1日18:47:49
Author	: Alegg xy.
Version	: 1.0
Description: 
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module top_fsm_lock( 
    input				clk		,
    input				rst_n	,
    input		[3:0]	key		,
    output		[5:0]	sel		,
    output		[7:0]	seg	    ,
    output		[3:0]	led	
);								 
//---------<参数定义>--------------------------------------------------------- 
    wire [3:0] key_link;
//---------<内部信号定义>-----------------------------------------------------
    key_debounce u_key_debounce(
        .clk		(clk),
        .rst_n	    (rst_n),
        .key_in	    (key),
        .key_out    (key_link)  
    );
    fsm_lock u_fsm_lock(
        .clk		(clk),
        .rst_n	    (rst_n),
        .key		(key_link),
        .sel	    (sel),
        .seg	    (seg),
        .led        (led)
    );
    
    
    
    
endmodule

七.仿真

  • tb_fsm_lock.v
`timescale 1ns/1ns
    
module tb_fsm_lock();

//激励信号定义 
    reg				tb_clk  	;
    reg				tb_rst_n	;
    reg		[3:0]	tb_key		;

//输出信号定义	 
    wire	[5:0]		tb_sel	    ;
    wire	[7:0]		tb_seg      ;
    wire    [3:0]       tb_led      ;

//时钟周期参数定义	
    parameter		CLOCK_CYCLE = 20;   
    defparam u_top_fsm_lock.u_key_debounce.DELAY_20MS = 100;
    defparam u_top_fsm_lock.u_fsm_lock.TIME_10S = 500;
    defparam u_top_fsm_lock.u_fsm_lock.TIME_300MS = 15;
//模块例化
    top_fsm_lock u_top_fsm_lock(	
    .clk		(tb_clk			),
    .rst_n		(tb_rst_n		),
    .key		(tb_key 		),
    .sel		(tb_sel 		),
    .seg		(tb_seg 		),
    .led		(tb_led 		) 
    );

//产生时钟
    initial 		tb_clk = 1'b0;
    always #(CLOCK_CYCLE/2) tb_clk = ~tb_clk;

    integer i;
//产生激励
    initial  begin 
        tb_rst_n = 1'b1;
        tb_key = 4'b1111;
        #(CLOCK_CYCLE*2);
        tb_rst_n = 1'b0;
        #(CLOCK_CYCLE*20);
        tb_rst_n = 1'b1;

        #2;
        //S1状态
            //按下1次按键key[0]
            tb_key[0] = 0;//按键按下,第一次检测到下降沿d
            wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILETER_DOWN);//按键按下抖动状态,延时20ms结束
            #(CLOCK_CYCLE*30);//按键稳定按下持续时间
            tb_key[0] = 1;//按键释放
            wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILTER_UP);//按键释放延时20ms结束

            //在s1状态下,按下确认按键key[2]
            tb_key[2] = 0;//按键按下,第一次检测到下降沿d
            wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILETER_DOWN);//按键按下抖动状态,延时20ms结束
            #(CLOCK_CYCLE*30);//按键稳定按下持续时间
            tb_key[2] = 1;//按键释放
            wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILTER_UP);//按键释放延时20ms结束

        //S2 状态
            //在S2状态下连续按5次key[0],每次按一次key[0],加1;此时value_2值为5
            for (i=0;i<5;i=i+1) begin
                tb_key[0] = 0;//按键按下,第一次检测到下降沿d
                wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILETER_DOWN);//按键按下抖动状态,延时20ms结束
                #(CLOCK_CYCLE*30);//按键稳定按下持续时间
                tb_key[0] = 1;//按键释放
                wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILTER_UP);//按键释放延时20ms结束
            end

            //在S2状态下连续按3次key[1],每次按一次key[1],减1;此时value_2值为2
            for (i=0;i<3;i=i+1) begin
                tb_key[1] = 0;//按键按下,第一次检测到下降沿d
                wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILETER_DOWN);//按键按下抖动状态,延时20ms结束
                #(CLOCK_CYCLE*30);//按键稳定按下持续时间
                tb_key[1] = 1;//按键释放
                wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILTER_UP);//按键释放延时20ms结束
            end

            //在S2状态下,按下确认按键key[2]
            tb_key[2] = 0;//按键按下,第一次检测到下降沿d
            wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILETER_DOWN);//按键按下抖动状态,延时20ms结束
            #(CLOCK_CYCLE*30);//按键稳定按下持续时间
            tb_key[2] = 1;//按键释放
            wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILTER_UP);//按键释放延时20ms结束

        //S3状态下
            //在S3状态下连续按3次key[0],每次按一次key[0],加1;此时value_3值为3
            for (i=0;i<3;i=i+1) begin
                tb_key[0] = 0;//按键按下,第一次检测到下降沿d
                wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILETER_DOWN);//按键按下抖动状态,延时20ms结束
                #(CLOCK_CYCLE*30);//按键稳定按下持续时间
                tb_key[0] = 1;//按键释放
                wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILTER_UP);//按键释放延时20ms结束
            end

            //在S3状态下,按下确认按键key[2]
            tb_key[2] = 0;//按键按下,第一次检测到下降沿d
            wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILETER_DOWN);//按键按下抖动状态,延时20ms结束
            #(CLOCK_CYCLE*30);//按键稳定按下持续时间
            tb_key[2] = 1;//按键释放
            wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILTER_UP);//按键释放延时20ms结束

        //S4状态下
            //在S4状态下连续按4次key[0],每次按一次key[0],加1;此时value_4值为4
            for (i=0;i<4;i=i+1) begin
                tb_key[0] = 0;//按键按下,第一次检测到下降沿d
                wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILETER_DOWN);//按键按下抖动状态,延时20ms结束
                #(CLOCK_CYCLE*30);//按键稳定按下持续时间
                tb_key[0] = 1;//按键释放
                wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILTER_UP);//按键释放延时20ms结束
            end

            //在S4状态下,按下确认按键key[2]
            tb_key[2] = 0;//按键按下,第一次检测到下降沿d
            wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILETER_DOWN);//按键按下抖动状态,延时20ms结束
            #(CLOCK_CYCLE*30);//按键稳定按下持续时间
            tb_key[2] = 1;//按键释放
            wait(u_top_fsm_lock.u_key_debounce.end_cnt_20ms && u_top_fsm_lock.u_key_debounce.cstate == u_top_fsm_lock.u_key_debounce.FILTER_UP);//按键释放延时20ms结束
    
        //等待SUCESS与FAILED结束
        wait(u_top_fsm_lock.u_fsm_lock.end_cnt_10s);
        #10000;
        $stop;

    end

endmodule 

八.仿真效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值