至简设计系列_电子密码锁

--作者:肖肖肖

--案例作者:WB_Yih

本文为明德扬原创及录用文章,转载请注明出处!

1.1 总体设计1.1.1 概述

随着生活质量的不断提高,加强家庭防盗安全变得非常重要,但传统机械锁的构造过于简单,很容易被打开,从而降低了安全性。数字密码锁因为它的保密性很高,安全系数也非常高,再加上其不需要携带避免了丢失的可能,省去了因钥匙丢失而需要换锁的麻烦,受到了越来越多的人的欢迎。随看人们对高科技产品也越来越推崇,在当今社会科技的高度集中和创新,人们对日常生活中保护自身及财产安全的物品非常追捧,对其安全性的要求也非常的高。为了达到人们对锁具安全性的高要求,加强锁具的安全保密性,用密码锁来取代传统机械锁的锁具是必然趋势。数字密码锁比传统机械锁具更加的安全。在本案例的设计过程中,应用了至简设计法、状态机模板应用等,在经过逐步改进、调试等一系列工作之后,最终达到了设计目标。

基于明德扬至简设计法和明德扬设计规范,设计一个基于FPGA的密码锁、并将数值显示在数码管上,然后根据输入的键值判断密码是否正确。

1.1.2 设计目标

实现电子密码锁的功能,具体功能要求如下:

1. 密码4位,初始密码2345。

2. 密码锁状态:LOCKED和OPEN,初始状态为LOCKED。

1) 当在LOCKED状态时,连续两次输入正确密码,状态变为OPEN状态。当输入错误密码时(包括第一次就输入错误;或者第一次输入正确,第二次输入错误的情况),数码管显示ERROR 2秒后重新显示原来的状态(LOCKED)。

2) 当在OPEN状态时,一次输入错误密码,状态变为LOCKED状态。当输入正确密码时,数码管无显示,10秒后重新显示原来的状态(OPEN)。

3) 不管在何状态,当输入4位密码或者某几位密码,但未按下确认键,并超过10S时,返回原来的状态。(即输入密码超时,返回原状态)

对于点拨开发板,使用矩阵按键输入(本文以点拨603开发板为例)。

对于Mp801开发板,密码显示及确认:无论在OPEN,还是LOCKED状态下,均可以通过拨码开关输入密码。当有拨码开关拨动时,数码管当前显示的OPEN或LOCKED消失,并显示当前输入的密码,暂未输入的密码位不显示。4位密码输入完毕后,再拨动拨码开关时视为无效输入,当前显示的密码不改变。4位密码输入完毕后,按下确认键后,系统判断密码是否正确。

拨码开关及按键:初始状态下,拨码开关全部往下拨。当拨码开关向上拨后,再向下拨(回到初始状态),表示一个数字的有效输入。按键每按下一次(会自动弹起),为一次有效输入(复位/确认)。

1.1.3 系统结构框图

系统结构框图如下图一所示:

图一

1.1.4模块功能按键检测模块实现功能

1、 检测按键的数值

控制模块实现功能

1、 对接收到的按键数值进行判断和控制对应的密码锁状态,实现对输入密码的正误判断和对密码锁的开启和闭合控制。

数码管显示模块实现功能

1、 显示输入的密码数值;

2、 显示当前密码锁的状态(开启状态或者闭锁状态);

3、 提示密码输入错误的状态。

1.1.5顶层信号

1.1.6参考代码

下面是使用工程的顶层代码:

module top_mdyPwdlock_keyscan(    clk             ,       rst_n           ,       key_col         ,    key_row         ,    seg_sel         ,      segment                    );    input               clk                 ;    input               rst_n               ;    input [3:0]         key_col             ;    output[5:0]         seg_sel             ;    output[7:0]         segment             ;    output[3:0]         key_row             ;    wire  [5:0]         seg_sel             ;    wire  [7:0]         segment             ;    wire  [3:0]         key_row             ;    wire  [3:0]         key_out             ;    wire                key_vld             ;    wire  [6*5-1:0]     seg_dout            ;    wire  [5:0]         seg_dout_vld        ;           key_scan u_key_scan(        .clk                (clk           ),                .rst_n              (rst_n         ),             .key_col            (key_col       ),        .key_row            (key_row       ),        .key_out            (key_out       ),        .key_vld            (key_vld       )    );    control u_ctrl(        .clk                (clk            ),               .rst_n              (rst_n          ),                                                     .key_num            (key_out        ),               .key_vld            (key_vld        ),                                                     .seg_dout           (seg_dout       ),               .seg_dout_vld       (seg_dout_vld   )            );    seg_display u_segment(        .clk                (clk            ),               .rst_n              (rst_n          ),               .din                (seg_dout       ),               .din_vld            (seg_dout_vld   ),              .segment            (segment        ),               .seg_sel            (seg_sel        )            );    endmodule

1.2 按键检测模块设计

1.2.1接口信号

1.2.2 设计思路

在前面的案例中已经有矩阵按键检测模块的介绍,所以这里不在过多介绍,详细介绍请看下方链接:

http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=310&highlight=%BE%D8%D5%F3

其中,按键的功能面板如下图所示:

1.2.3参考代码

module  key_scan(                 clk    ,                 rst_n  ,                 key_col,                 key_row,                 key_out,                 key_vld                  );    parameter      KEY_W  =         4 ;    parameter      CHK_COL  =   0 ;    parameter      CHK_ROW  =   1 ;    parameter      DELAY    =   2 ;    parameter      WAIT_END =   3 ;    parameter      COL_CNT  =   16;    parameter      TIME_20MS=   1000000;    input               clk    ;    input               rst_n  ;    input  [3:0]        key_col;    output              key_vld;    output[3:0]         key_out;    output[KEY_W-1:0]   key_row;    reg   [3:0]         key_out;    reg   [KEY_W-1:0]   key_row;    reg                 key_vld;    reg [3:0]           key_col_ff0;    reg [3:0]           key_col_ff1;    reg [1:0]           key_col_get;    wire                shake_flag ;    reg                 shake_flag_ff0;    reg[3:0]            state_c;    reg [19:0]          shake_cnt;    reg[3:0]            state_n;    reg [1:0]           row_index;    reg[15:0]           row_cnt;    wire                chk_col2chk_row ;     wire                chk_row2delay   ;    wire                delay2wait_end  ;    wire                wait_end2chk_col;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        key_col_ff0 <= 4'b1111;        key_col_ff1 <= 4'b1111;    end    else begin        key_col_ff0 <= key_col    ;        key_col_ff1 <= key_col_ff0;    endendwire        add_shake_cnt ;always @(posedge clk or negedge rst_n) begin     if (rst_n==0) begin        shake_cnt <= 0;     end    else if(add_shake_cnt) begin        if(shake_flag)            shake_cnt <= 0;         else            shake_cnt <= shake_cnt+1 ;   endendassign add_shake_cnt = key_col_ff1!=4'hf;assign shake_flag = add_shake_cnt  && shake_cnt == TIME_20MS-1 ;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        state_c <= CHK_COL;    end    else begin        state_c <= state_n;    endendalways  @(*)begin    case(state_c)        CHK_COL: begin                     if(shake_flag && shake_flag_ff0==1'b0)begin                         state_n = CHK_ROW;                     end                     else begin                         state_n = CHK_COL;                     end                 end        CHK_ROW: begin                     if(row_index==3 && row_cnt==0)begin                         state_n = DELAY;                     end                     else begin                         state_n = CHK_ROW;                     end                 end        DELAY :  begin                     if(row_cnt==0)begin                         state_n = WAIT_END;                     end                     else begin                         state_n = DELAY;                     end                 end        WAIT_END: begin                     if(key_col_ff1==4'hf)begin                         state_n = CHK_COL;                     end                     else begin                         state_n = WAIT_END;                     end                  end       default: state_n = CHK_COL;    endcaseendassign chk_col2chk_row = shake_flag && shake_flag_ff0 ==1'b0;assign chk_row2delay   = row_index==3 && row_cnt==0;assign delay2wait_end  = row_cnt==0;assign wait_end2chk_col= key_col_ff1==4'hf;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        key_row <= 4'b0;    end    else if(state_c==CHK_ROW)begin        key_row <= ~(1'b1 << row_index);    end    else begin        key_row <= 4'b0;    endendalways  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        row_index <= 0;    end    else if(state_c==CHK_ROW)begin       if(row_cnt==0)begin           if(row_index==3)               row_index <= 0;           else               row_index <= row_index + 1;       end    end    else begin        row_index <= 0;    endendwire        add_row_cnt ;wire        end_row_cnt ;always @(posedge clk or negedge rst_n) begin     if (rst_n==0) begin        row_cnt <= COL_CNT;     end    else if(add_row_cnt) begin        if(end_row_cnt)            row_cnt <= COL_CNT;         else            row_cnt <= row_cnt-1 ;   end   else begin       row_cnt <= COL_CNT;   endendassign add_row_cnt = state_c==CHK_ROW || state_c==DELAY;assign end_row_cnt = add_row_cnt  && row_cnt == 0 ;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        shake_flag_ff0 <= 1'b0;    end    else begin        shake_flag_ff0 <= shake_flag;    endendalways  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        key_col_get <= 0;    end    else if(state_c==CHK_COL && shake_flag==1'b1 && shake_flag_ff0==1'b0) begin        if(key_col_ff1==4'b1110)            key_col_get <= 0;        else if(key_col_ff1==4'b1101)            key_col_get <= 1;        else if(key_col_ff1==4'b1011)            key_col_get <= 2;        else             key_col_get <= 3;    endendalways  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        key_out <= 0;    end    else if(state_c==CHK_ROW && row_cnt==0)begin        key_out <= {row_index,key_col_get};    end    else begin        key_out <= 0;    endendalways  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        key_vld <= 1'b0;    end    else if(state_c==CHK_ROW && row_cnt==0 && key_col_ff1[key_col_get]==1'b0)begin        key_vld <= 1'b1;    end    else begin        key_vld <= 1'b0;    endendendmodue

1.3 控制模块设计

1.3.1接口信号

1.3.2设计思路

  • 状态机架构

本模块的主要功能是根据输入的按键信息进行不同状态的判断和切换当前工作状态。根据项目功能要求,一共有四种工作状态:密码锁开启状态(open)、密码锁闭合状态(clocked)、输入密码状态(password)和提示输入错误状态(error)。

以下为本模块的状态跳转图:

复位后,状态机进入LOCKED的状态,即初始状态为LOCKED;

在LOCKED状态下:

A. 有按键按下,跳到PASSWORD状态;

B. 否则,保持LOCKED状态不变;

在OPEN状态下:

A. 有按键按下,跳到PASSWORD状态;

B. 否则,保持OPEN状态不变;

在PASSWORD状态下:

A. 有密码输入但超过10秒没有确认,跳到原来的LOCKED状态或者OPEN状态;

B. 密码正确输入并确认两次,跳到OPEN状态;

C. 密码错误输入并确认,跳到ERROR状态;

D. 否则,保持PASSWORD状态不变;

在ERROR状态下:

A. 提示输入错误2秒,跳到LOCKED状态;

B. 否则,保持ERROR状态不变;

无论当前处于什么状态,只要不满足状态间的跳转条件就跳到LOCKED状态。

  • 计数器架构

本模块的某些状态跳转之间存在一定的时间间隔,根据项目功能要求,一共有两种时间的间隔:10秒的等待输入时间间隔和2秒的显示提示时间间隔。

以下为计数器的架构示意图:

10秒计数器cnt_10s_nvld:用于计算10秒的时间。加一条件为state_c==PASSWORD,表示进入密码输入状态就开始计数。结束条件为数500_000_000个,系统时钟为50M,一个时钟周期为20ns,500_000_000个时钟周期就是10秒。

2秒计数器cnt_2s:用于计算2秒的时间。加一条件为state_c==ERROR,表示进入提示输入错误状态就开始计数。结束条件为数100_000_000个,系统时钟为50M,一个时钟周期为20ns,100_000_000个时钟周期就是2秒。


1.3.3参考代码

module control(    clk             ,    rst_n           ,    key_num         ,    key_vld         ,    seg_dout        ,     seg_dout_vld             );    parameter PASSWORD_INI     = 16'h2345    ;     parameter CHAR_O           = 5'h10       ;     parameter CHAR_P           = 5'h11       ;     parameter CHAR_E           = 5'h12       ;     parameter CHAR_N           = 5'h13       ;     parameter CHAR_L           = 5'h14       ;     parameter CHAR_C           = 5'h15       ;     parameter CHAR_K           = 5'h16       ;     parameter CHAR_D           = 5'h17       ;     parameter CHAR_R           = 5'h18       ;     parameter NONE_DIS         = 5'h1F       ;     parameter C_10S_WID        = 29          ;    parameter C_10S_NUM        = 500_000_000 ;    parameter C_2S_WID         = 27          ;    parameter C_2S_NUM         = 100_000_000 ;    parameter C_PWD_WID        = 3           ;    input               clk                 ;    input               rst_n               ;    input [3:0]         key_num             ;    input               key_vld             ;    output[6*5-1:0]     seg_dout            ;    output[5:0]         seg_dout_vld        ;    reg   [6*5-1:0]     seg_dout            ;    wire  [5:0]         seg_dout_vld        ;    reg   [1:0]         state_c             ;    reg   [1:0]         state_n             ;    reg                 lock_stata_flag     ;    reg                 password_correct_twice  ;        reg   [C_2S_WID-1:0]    cnt_2s          ;     reg   [C_10S_WID-1:0]   cnt_10s_nvld    ;    reg   [C_PWD_WID-1:0]   cnt_password    ;    reg   [15:0]            password        ;        parameter LOCKED    = 2'b00             ;    parameter OPEN      = 2'b01             ;    parameter PASSWORD  = 2'b10             ;    parameter ERROR     = 2'b11             ;    //current state    always@(posedge clk or negedge rst_n)begin        if(!rst_n)begin            state_c <= LOCKED;        end        else begin            state_c <= state_n;        end    end    //next state and the condition of state LOCKEDtransition    always@(*)begin        case(state_c)            LOCKED:begin                if(locked2password_switch)begin                    state_n = PASSWORD;                end                else begin                    state_n = state_c;                end            end            OPEN:begin                if(open2password_switch)begin                    state_n = PASSWORD;                end                else begin                    state_n = state_c;                end            end                        PASSWORD:begin                if(password2locked_switch0)begin                    state_n = LOCKED;                end                else if(password2open_switch0 || password2open_switch1)begin                    state_n = OPEN;                end                else if(password2error_switch || password2locked_switch1)begin                    state_n = ERROR;                end                else begin                    state_n = state_c;                end            end            ERROR:begin                if(error2locked_switch0 )begin                    state_n = LOCKED;                end                else begin                    state_n = state_c;                end            end            default:begin                state_n = LOCKED;            end        endcase    end    assign locked2password_switch    = state_c==LOCKED   &&  lock_stata_flag && key_num<10 && key_vld;    assign open2password_switch      = state_c==OPEN     && !lock_stata_flag && key_num<10 && key_vld;    assign password2locked_switch0   = state_c==PASSWORD &&  lock_stata_flag && end_cnt_10s_nvld;    assign password2locked_switch1   = state_c==PASSWORD &&  lock_stata_flag && confirm && password!=PASSWORD_INI ;//TO ERROR    assign password2open_switch0     = state_c==PASSWORD &&  lock_stata_flag && confirm && password==PASSWORD_INI &&  password_correct_twice;    assign password2open_switch1     = state_c==PASSWORD && !lock_stata_flag && end_cnt_10s_nvld;    assign password2error_switch     = state_c==PASSWORD && !lock_stata_flag && confirm && password!=PASSWORD_INI;    assign error2locked_switch0      = state_c==ERROR    &&  end_cnt_2s;    //lock_stata_flag    always  @(posedge clk or negedge rst_n)begin        if(rst_n==1'b0)begin            lock_stata_flag <= 1;        end        else if(password2locked_switch0 || password2locked_switch1 || error2locked_switch0)begin            lock_stata_flag <= 1;        end        else if(password2open_switch0 || password2open_switch1 )begin            lock_stata_flag <= 0;        end    end    //cnt_10s_nvld    always  @(posedge clk or negedge rst_n)begin        if(rst_n==1'b0)begin            cnt_10s_nvld <= 0;        end        else if(end_cnt_10s_nvld)begin            cnt_10s_nvld <= 0;        end        else if(add_cnt_10s_nvld)begin            cnt_10s_nvld <= cnt_10s_nvld + 1;        end    end    assign add_cnt_10s_nvld = state_c==PASSWORD;    assign end_cnt_10s_nvld = add_cnt_10s_nvld && cnt_10s_nvld==C_10S_NUM-1;    //confirm    assign confirm = key_num==10 && key_vld;    //password_correct_twice        always  @(posedge clk or negedge rst_n)begin        if(rst_n==1'b0)begin            password_correct_twice <= 0;        end        else if(state_c==PASSWORD && lock_stata_flag && confirm && password==PASSWORD_INI && !password_correct_twice)begin            password_correct_twice <= 1;        end        else if(password2locked_switch0 || password2locked_switch1 || password2open_switch0 || password2open_switch1 || password2error_switch)begin            password_correct_twice <= 0;        end    end    //cnt_2s    always  @(posedge clk or negedge rst_n)begin        if(rst_n==1'b0)begin            cnt_2s <= 0;        end        else if(end_cnt_2s )begin            cnt_2s <= 0;        end        else if(add_cnt_2s )begin            cnt_2s <= cnt_2s + 1;        end    end    assign add_cnt_2s = state_c==ERROR;    assign end_cnt_2s = add_cnt_2s && cnt_2s==C_2S_NUM-1;    //seg_dout    always  @(posedge clk or negedge rst_n)begin        if(rst_n==1'b0)begin            seg_dout <= 0;        end        else if(state_c==OPEN)begin            seg_dout <= {NONE_DIS,NONE_DIS,CHAR_O,CHAR_P,CHAR_E,CHAR_N};        end        else if(state_c==LOCKED)begin            seg_dout <= {CHAR_L,CHAR_O,CHAR_C,CHAR_K,CHAR_E,CHAR_D};        end        else if(state_c==ERROR)begin            seg_dout <= {NONE_DIS,CHAR_E,CHAR_R,CHAR_R,CHAR_O,CHAR_R};        end        else if(state_c==PASSWORD)begin            if(cnt_password==0)                seg_dout <= {NONE_DIS,NONE_DIS,NONE_DIS,NONE_DIS,NONE_DIS,NONE_DIS};            else if(cnt_password==1)                seg_dout <= {NONE_DIS,NONE_DIS,NONE_DIS,NONE_DIS,NONE_DIS,{1'b0,password[3:0]}};            else if(cnt_password==2)                seg_dout <= {NONE_DIS,NONE_DIS,NONE_DIS,NONE_DIS,{1'b0,password[7:4]},{1'b0,password[3:0]}};            else if(cnt_password==3)                seg_dout <= {NONE_DIS,NONE_DIS,NONE_DIS,{1'b0,password[11:8]},{1'b0,password[7:4]},{1'b0,password[3:0]}};            else if(cnt_password==4)                seg_dout <= {NONE_DIS,NONE_DIS,{1'b0,password[15:12]},{1'b0,password[11:8]},{1'b0,password[7:4]},{1'b0,password[3:0]}};        end    end        //seg_dout_vld    assign seg_dout_vld = 6'b11_1111;    //cnt_password    always  @(posedge clk or negedge rst_n)begin        if(rst_n==1'b0)begin            cnt_password <= 0;        end        else if(end_cnt_password)begin            cnt_password <= 0;        end        else if(add_cnt_password)begin            cnt_password <= cnt_password + 1;        end    end    assign add_cnt_password = state_c!=ERROR && key_num<10 && key_vld && cnt_password<4;    assign end_cnt_password = confirm || end_cnt_10s_nvld;    //password    always  @(posedge clk or negedge rst_n)begin        if(rst_n==1'b0)begin            password <= 16'h0000;        end        else if(add_cnt_password)begin            password <= {password[11:0],key_num};        end    end    endmodule

1.4 数码管显示模块设计

1.4.1接口信号

1.4.2设计思路

在前面的案例中已经有数码管显示的介绍,所以这里不在过多介绍,详细介绍请看下方链接:

http://fpgabbs.com/forum.php?mod=viewthread&tid=1085&fromuid=100105

其中,数码管显示的数值和英文字母对应图像如下图所示:

1.4.3参考代码

module seg_display(    clk     ,           rst_n   ,           din     ,           din_vld ,           segment ,           seg_sel             );    parameter SEGMENT_NUM   = 6             ;       parameter W_DATA        = 5             ;       parameter SEGMENT_WID   = 8             ;       parameter TIME_300US    = 15_000         ;      parameter SEG_DATA_0    = 7'b100_0000   ;      parameter SEG_DATA_1    = 7'b111_1001   ;    parameter SEG_DATA_2    = 7'b010_0100   ;    parameter SEG_DATA_3    = 7'b011_0000   ;    parameter SEG_DATA_4    = 7'b001_1001   ;    parameter SEG_DATA_5    = 7'b001_0010   ;    parameter SEG_DATA_6    = 7'b000_0010   ;    parameter SEG_DATA_7    = 7'b111_1000   ;    parameter SEG_DATA_8    = 7'b000_0000   ;    parameter SEG_DATA_9    = 7'b001_0000   ;      parameter SEG_CHAR_O    = 7'b010_0011   ;      parameter SEG_CHAR_P    = 7'b000_1100   ;      parameter SEG_CHAR_E    = 7'b000_0110   ;      parameter SEG_CHAR_N    = 7'b010_1011   ;      parameter SEG_CHAR_L    = 7'b100_0111   ;      parameter SEG_CHAR_C    = 7'b100_0110   ;      parameter SEG_CHAR_K    = 7'b000_0101   ;      parameter SEG_CHAR_D    = 7'b010_0001   ;      parameter SEG_CHAR_R    = 7'b010_1111   ;      parameter SEG_NONE_DIS  = 7'b111_1111   ;      input                           clk         ;    input                           rst_n       ;    input [SEGMENT_NUM*W_DATA-1:0]  din         ;    input [SEGMENT_NUM-1:0]         din_vld     ;    output[SEGMENT_WID-1:0]         segment     ;    output[SEGMENT_NUM-1:0]         seg_sel     ;    reg   [SEGMENT_WID-1:0]         segment     ;    reg   [SEGMENT_NUM-1:0]         seg_sel     ;    reg   [W_DATA-1:0]              segment_pre ;    reg   [SEGMENT_NUM*W_DATA-1:0]  din_get     ;    reg   [14:0]                    cnt_300us   ;    reg   [2:0]                     cnt_sel     ;    wire                            dot         ;   wire        add_cnt_300us ;wire        end_cnt_300us ;always @(posedge clk or negedge rst_n) begin     if (rst_n==0) begin        cnt_300us <= 0;     end    else if(add_cnt_300us) begin        if(end_cnt_300us)            cnt_300us <= 0;         else            cnt_300us <= cnt_300us+1 ;   endendassign add_cnt_300us =1;assign end_cnt_300us = add_cnt_300us  && cnt_300us == TIME_300US-1 ;   wire        add_cnt_sel ;wire        end_cnt_sel ;always @(posedge clk or negedge rst_n) begin     if (rst_n==0) begin        cnt_sel <= 0;     end    else if(add_cnt_sel) begin        if(end_cnt_sel)            cnt_sel <= 0;         else            cnt_sel <= cnt_sel+1 ;   endendassign add_cnt_sel = end_cnt_300us;assign end_cnt_sel = add_cnt_sel  && cnt_sel == SEGMENT_NUM-1 ;reg     [SEGMENT_NUM-1:0]   din_vvld;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        din_vvld <= 0 ;    end    else begin        din_vvld <= din_vld ;    endendreg [ 2:0]  cnt     ;wire        add_cnt ;wire        end_cnt ;always @(posedge clk or negedge rst_n) begin     if (rst_n==0) begin        cnt <= 0;     end    else if(add_cnt) begin        if(end_cnt)            cnt <= 0;         else            cnt <= cnt+1 ;   endendassign add_cnt = 1;assign end_cnt = add_cnt  && cnt == SEGMENT_NUM-1 ;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        din_get <= 0;    end    else if(din_vvld[cnt])begin        din_get[W_DATA*(cnt+1)-1 -:W_DATA] <= din[W_DATA*(cnt+1)-1 -:W_DATA];    endend    always  @(*)begin        segment_pre = din_get[W_DATA*(cnt_sel+1)-1 -:W_DATA];    end    always  @(posedge clk or negedge rst_n)begin        if(rst_n==1'b0)begin            segment <= {dot,SEG_NONE_DIS};        end        else if(add_cnt_300us  && cnt_300us ==10-1)begin            case(segment_pre)                5'h00: segment <= {dot,SEG_DATA_0};                5'h01: segment <= {dot,SEG_DATA_1};                5'h02: segment <= {dot,SEG_DATA_2};                5'h03: segment <= {dot,SEG_DATA_3};                5'h04: segment <= {dot,SEG_DATA_4};                5'h05: segment <= {dot,SEG_DATA_5};                5'h06: segment <= {dot,SEG_DATA_6};                5'h07: segment <= {dot,SEG_DATA_7};                5'h08: segment <= {dot,SEG_DATA_8};                5'h09: segment <= {dot,SEG_DATA_9};                5'h10: segment <= {dot,SEG_CHAR_O};                5'h11: segment <= {dot,SEG_CHAR_P};                5'h12: segment <= {dot,SEG_CHAR_E};                5'h13: segment <= {dot,SEG_CHAR_N};                5'h14: segment <= {dot,SEG_CHAR_L};                5'h15: segment <= {dot,SEG_CHAR_C};                5'h16: segment <= {dot,SEG_CHAR_K};                5'h17: segment <= {dot,SEG_CHAR_D};                5'h18: segment <= {dot,SEG_CHAR_R};                5'h1F: segment <= {dot,SEG_NONE_DIS};                default:segment <= {dot,SEG_NONE_DIS};            endcase        end    end    assign dot = 1'b1;     always@(posedge clk or negedge rst_n)begin        if(rst_n==1'b0)begin            seg_sel <= {SEGMENT_NUM{1'b0}};        end        else begin            seg_sel <= ~(1'b1<

1.5 效果和总结下图是该工程在db603开发板上的现象——密码锁初始状态和闭合状态

下图是该工程在db603开发板上的现象——提示输入错误状态

下图是该工程在db603开发板上的现象——密码锁开启状态

下图是该工程在db603开发板上的现象——输入密码状态

下图是该工程在mp801开发板上的现象——密码锁初始状态和闭合状态

下图是该工程在mp801开发板上的现象——提示输入错误状态


下图是该工程在mp801开发板上的现象——密码锁开启状态
下图是该工程在mp801开发板上的现象——输入密码状态下图是该工程在ms980开发板上的现象——密码锁初始状态和闭合状态

下图是该工程在ms980开发板上的现象——提示输入错误状态

下图是该工程在ms980开发板上的现象——密码锁开启状态

下图是该工程在ms980开发板上的现象——输入密码状态

由于该项目的上板现象是在数码管上显示输入的密码,并且判断密码是否正确:正确则在数码管上显示OPEN,错误则在数码管上显示ERROR并提示输入错误2秒,然后数码管显示LOCKED。想观看完整现象的朋友可以看一下上板演示的视频。

感兴趣的朋友也可以访问明德扬论坛(http://www.fpgabbs.cn/)进行FPGA相关工程设计学习,也可以看一下我们往期的文章:

《波形相位频率可调DDS信号发生器》

《基于FPGA的曼彻斯特编码解码设计》

《基于FPGA的出租车计费系统》

《数电基础与Verilog设计》

《基于FPGA的频率、电压测量》

《基于FPGA的汉明码编码解码设计》

《关于锁存器问题的讨论》

《阻塞赋值与非阻塞赋值》

《参数例化时自动计算位宽的解决办法》

1.6 公司简介

明德扬是一家专注于FPGA领域的专业性公司,公司主要业务包括开发板、教育培训、项目承接、人才服务等多个方向。点拨开发板——学习FPGA的入门之选。
MP801开发板——千兆网、ADDA、大容量SDRAM等,学习和项目需求一步到位。网络培训班——不管时间和空间,明德扬随时在你身边,助你快速学习FPGA。周末培训班——明天的你会感激现在的努力进取,升职加薪明德扬来助你。就业培训班——七大企业级项目实训,获得丰富的项目经验,高薪就业。专题课程——高手修炼课:提升设计能力;实用调试技巧课:提升定位和解决问题能力;FIFO架构设计课:助你快速成为架构设计师;时序约束、数字信号处理、PCIE、综合项目实践课等你来选。项目承接——承接企业FPGA研发项目。人才服务——提供人才推荐、人才代培、人才派遣等服务。

php中怎么判断输入密码与原密码一致_「每周FPGA案例」电子密码锁设计相关推荐

  1. 判断质数和合数python代码_「质数和合数」C语言:质数和合数的判断 - 金橙教程网...

    质数和合数 给定一个正整数 n (2 <= n < 10000),判断是否为质数. 多组输入,每行一个 n (2 <= n <= 10000). 对于每一组数,如果是质数则输出 ...

  2. 「每周译Go」如何在 Go 中编写 Switch 语句

    目录 在 Go 中导入包 理解 Go 中包的可见性 如何在 Go 中编写条件语句 如何在 Go 中编写 Switch 语句 如何在 Go 中构造 for 循环 在循环中使用 Break 和 Conti ...

  3. java里面string什么意思_「Java基础知识」Java中的字符串是什么

    原标题:「Java基础知识」Java中的字符串是什么 字符串顾名思义就是一些字符组合在一起组成的一串数据,称作字符串,在Java中字符串用双引号包围起来,格式为String string = &quo ...

  4. 简述计算机视觉中的单眼线索,知觉的种类之 空间知觉「心理学了18」

    原标题:知觉的种类之 空间知觉「心理学了18」 来自一名活色生香的心理咨询师整理 刘熹微 | No.18 空间知觉是指对物体距离.形状.大小.方位等空间特性的知觉. 两个视网膜上的略有差异的映象,是观 ...

  5. python中字符型用什么表示_「小白学Python」Python中最常用的数据类型:字符串

    Python中有6个标准数据类型,分别是:Number(数值).String(字符串).List(列表).Tuple(元组).Sets(集合).Dictionary(字典). 其中,String(字符 ...

  6. python中序列类型和数组之间的区别_「Python」序列构成的数组

    一.Python 标准库的序列类型分为: 容器序列: 能够存放不同类型数据的序列(list.tuple.collections.deque). 扁平序列: 只能容纳一种类型的数据(str.bytes. ...

  7. 将文件中所有数读到一个数组中_「数据结构与算法」将5个文件中的一千万年龄合并到一个新文件中...

    现在有5个文件,文件里面分别存储着1千万个用户年龄,并且每个文件中的年龄都是有序的(从小到大),现在需要将这5个文件整合到一个文件中,新文件的内容依然要保持有序(从小到大). 初始化数据 1.数据生成 ...

  8. c if 判断select已经选择的值_「Linux」——select和epoll详解

    select和epoll详解 select和epoll的区别(面试常考) select 一.什么是select 1.select函数原型 2.参数解释 3.参数timeout取值 4.返回值 5.监控 ...

  9. java节假日算法_「国家法定节假日」java 国家法定节假日和双休日判断工具类 - seo实验室...

    国家法定节假日 package com.newland.dateutil; import java.text.ParseException; import java.text.simpledatefo ...

最新文章

  1. JQuery -- this 和 $(this) 的区别
  2. python uvloop异步框架简介
  3. 用dos命令给mysql数据库新建表
  4. Linux内核创建一个新进程的过程
  5. linux 管道使用方法,Linux 管道命令
  6. 【37.68%】【hdu 5918】Sequence I
  7. 布隆过滤器误判_布隆过滤器原理
  8. 使用JasperReport 引擎PDF报表,因为iText版本升级,由原来的包名com.lowagie.text.pdf.fonts转化为com.itextpdf.text.pdf.fonts
  9. activemq部署
  10. Swift编程必备的iOS库 Pod
  11. 【每日一题】(D0723)strcpy 智能指针
  12. 采用Armjio非精确线搜索准则的最速下降法--MATLAB实现
  13. 秀才seo博客:搜索引擎优化的前身和未来
  14. OSChina 周五乱弹 ——电影里有在线/离线,递归,循环,矩阵等概念?
  15. sql查询条件有单引号
  16. thinkDifferent思维糖果
  17. OpenCms创建网站过程图解——献给OpenCms的初学者们
  18. matlab湿度廓线,中国气象数据网
  19. 【微服务】SpringBoot 搭建微服务初体验
  20. 硬盘分类(HDD、HHD、SSD)简介

热门文章

  1. 10以内逆向运算题_加减法启蒙系列 | 实战篇二(10以内减法)
  2. Anaconda常用命令大全
  3. 深度学习 --- 优化入门六(正则化、参数范数惩罚L0、L1、L2、Dropout)
  4. Javascript各种运算符第五课(小一节)
  5. python的基础_毫无基础的人如何入门 Python ?
  6. java接口vm和dto的区别_第十八节:详解Java抽象类和接口的区别
  7. php 跨天 时间差 秒,判断时间是否在预设跨天时段
  8. html语言空格怎么写,html的空格代码怎么写?
  9. webbrowser设置横向打印_9个Excel打印神技巧!从此打印不求人!
  10. SVG.属性(各种)