至简设计法---分享一份实现矩阵键盘的verilog代码 可直接使用

2020-01-27 13:13发布

`define  SCANmodule  key_scan(                 clk    ,                  rst_n  ,                 key_col, //键盘列输入                 key_row, //键盘行输出                 key_num, //指示哪一个按键按下,用0~15指示                 key_vld  //按下有效指示信号,其为1表示按下一次。               );    parameter      KEY_W    =   4 ;    parameter      COL      =   0 ;    parameter      ROW      =   1 ;    parameter      DLY      =   2 ;    parameter      FIN      =   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_num;    output[KEY_W-1:0]   key_row;    //输出信号reg定义    reg   [3:0]         key_num;    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   ;    reg                 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       ;reg   [ 2:0]        x             ;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;    endendalways  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        shake_cnt <= 0;    end    else if(add_shake_cnt)begin        if(end_shake_cnt)            shake_cnt <= 0;        else            shake_cnt <= shake_cnt + 1;    end    else begin        shake_cnt <= 0;    endendassign  add_shake_cnt = key_col_ff1!=4'hf && shake_flag==0;assign  end_shake_cnt = add_shake_cnt && shake_cnt==TIME_20MS-1;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        shake_flag <= 0;    end    else if(end_shake_cnt) begin        shake_flag <= 1'b1;    end    else if(key_col_ff1==4'hf) begin        shake_flag <= 1'b0;    endend`ifdef SCANalways  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        state_c <= COL;    end    else begin        state_c <= state_n;    endendalways  @(*)begin    case(state_c)        COL: begin                     if(col2row_start)begin                         state_n = ROW;                     end                     else begin                         state_n = state_c;                     end                 end        ROW: begin                     if(row2dly_start)begin                         state_n = DLY;                     end                     else begin                         state_n = state_c;                     end                 end        DLY :  begin                     if(dly2fin_start)begin                         state_n = FIN;                     end                     else begin                         state_n = state_c;                     end                 end        FIN: begin                     if(fin2col_start)begin                         state_n = COL;                     end                     else begin                         state_n = state_c;                     end                  end       default: state_n = COL;    endcaseendassign  col2row_start = state_c==COL && end_shake_cnt;assign  row2dly_start = state_c==ROW && end_row_index; assign  dly2fin_start = state_c==DLY && end_row_index; assign  fin2col_start = state_c==FIN && 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==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_cnt <= 0;    end    else if(add_row_cnt) begin        if(end_row_cnt)            row_cnt <= 0;        else            row_cnt <= row_cnt + 1;    endendassign add_row_cnt = state_c==ROW || state_c==DLY;assign end_row_cnt = add_row_cnt && row_cnt==COL_CNT-1;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        row_index <= 0;    end    else if(add_row_index) begin        if(end_row_index)            row_index <= 0;        else            row_index <= row_index + 1;    endendassign add_row_index = end_row_cnt;assign end_row_index = add_row_index && row_index==x-1;always  @(*)begin    if(state_c==ROW)        x = 4;    else        x = 1;endalways  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        key_col_get <= 0;    end    else if(col2row_start) 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_num <= 0;    end    else if(state_c==ROW && end_row_cnt)begin        key_num <= {row_index,key_col_get};    end    else begin        key_num <= 0;    endendalways  @(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begin        key_vld <= 1'b0;    end    else if(state_c==ROW && end_row_cnt && key_col_ff1[key_col_get]==1'b0)begin        key_vld <= 1'b1;    end    else begin        key_vld <= 1'b0;    endend`else    always  @(posedge clk or negedge rst_n)begin        if(rst_n==1'b0)begin            key_vld <= 0;        end        else begin            key_vld <= end_shake_cnt;        end    end    always  @(*)begin        key_num = 0;    end`endifendmodule  
0条回答

一周热门 更多>