没有多大的技术含量,就是将用按键少的矩阵按键转化为普通按键,减少IO口的使用,一个按键一个作用,按键松开则按键结束。
转化程序:
/********************************Copyright************************************** **----------------------------File information-------------------------- ** File name :keyboard_to_key.v ** CreateDate :2015. ** Funtions : ** Operate on :M5C06N3L114C7 ** Copyright :All rights reserved. ** Version :V1.0 **---------------------------Modify the file information---------------- ** Modified by : ** Modified data : ** Modify Content: *******************************************************************************/ module keyboard_to_key ( clk, rst_n, l_in, h_out, key_0, key_1, key_2, key_3, key_4, key_5, key_6, key_7, key_8, key_9, key_10, key_11, key_12, key_13, key_14, key_15, seg_bit, seg_data ); input clk; input rst_n; input [3:0] l_in; //列输入,一般接上拉,为高电平 output [3:0] h_out; //行输出信号,低有效 output key_0; output key_1; output key_2; output key_3; output key_4; output key_5; output key_6; output key_7; output key_8; output key_9; output key_10; output key_11; output key_12; output key_13; output key_14; output key_15; output seg_bit; output [7:0] seg_data; //************************************* /* 分频Ƶ*20ms,用于消抖 .状态机直接用clk_20ms,则可以跳过消抖*/ // `define CLK_50M // `define CLK_24M `define CLK_20M `ifdef CLK_50M parameter t_20ms = 20'd999999; `endif `ifdef CLK_24M parameter t_20ms = 20'd479999; `endif `ifdef CLK_20M parameter t_20ms = 20'd399999; `endif reg [19:0] cnt; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin cnt <= 'd0; end else begin if(cnt == t_20ms) cnt <= 'd0; else cnt <= cnt + 'd1; end end wire shake_over; assign shake_over = (cnt == t_20ms); //******************状态机****************** localparam NO_KEY_pressed = 3'd0; /* 初始化 */ localparam key_shake_1 = 3'd1; /* 消抖1 */ localparam KEY_h_1 = 3'd2; /* 检测第一列 */ localparam KEY_h_2 = 3'd3; /* 检测第二列 */ localparam KEY_h_3 = 3'd4; /* 检测第三列 */ localparam KEY_h_4 = 3'd5; /* 检测第四列 */ localparam KEY_pressed = 3'd6; /* 按键值输出*/ localparam key_shake_2 = 3'd7; /* 消抖2 */ /* 3-1 */ reg [2:0] current_state; reg [2:0] next_state; reg key_pressed_flag; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin current_state <= 0; end else if(shake_over) begin current_state <= next_state; end else current_state <= current_state ; end /* 3-2 */ always @(*) begin next_state = NO_KEY_pressed; case(current_state) NO_KEY_pressed: begin if(l_in != 4'hf) next_state = key_shake_1; else next_state = NO_KEY_pressed; end key_shake_1: begin if(l_in != 4'hf) next_state = KEY_h_1; else next_state = NO_KEY_pressed; end KEY_h_1: begin if(l_in != 4'hf) next_state = KEY_pressed; else next_state = KEY_h_2; end KEY_h_2: begin if(l_in != 4'hf) next_state = KEY_pressed; else next_state = KEY_h_3; end KEY_h_3: begin if(l_in != 4'hf) next_state = KEY_pressed; else next_state = KEY_h_4; end KEY_h_4: begin if(l_in != 4'hf) next_state = KEY_pressed; else next_state = NO_KEY_pressed; end KEY_pressed: begin if(l_in != 4'hf) next_state = key_shake_2; else next_state = NO_KEY_pressed; end key_shake_2: begin if(l_in != 4'hf) next_state = key_shake_2; else next_state = NO_KEY_pressed; end default:next_state = NO_KEY_pressed; endcase end /* 3-3 */ reg [3:0] l_in_reg; reg [3:0] h_out_reg; reg [3:0] h_out; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin l_in_reg <= 4'd0; h_out_reg<= 4'd0; h_out <= 4'd0; key_pressed_flag <= 0; end else if(shake_over) begin case(next_state) NO_KEY_pressed: begin l_in_reg <= l_in_reg; h_out_reg<= h_out_reg; h_out <= 4'd0; key_pressed_flag <= 0; end KEY_h_1: begin h_out <= 4'b1110; end KEY_h_2: begin h_out <= 4'b1101; end KEY_h_3: begin h_out <= 4'b1011; end KEY_h_4: begin h_out <= 4'b0111; end KEY_pressed: begin l_in_reg <= l_in; h_out_reg<= h_out; end key_shake_2: begin key_pressed_flag <= 1; end default:; endcase end end reg [15:0] temp_key_val; always @(posedge clk or negedge rst_n) begin if(!rst_n) temp_key_val <= 16'h0000; else begin if(key_pressed_flag) begin case ({h_out_reg,l_in_reg}) 8'b1110_1110 : temp_key_val <= 16'h0001; 8'b1110_1101 : temp_key_val <= 16'h0002; 8'b1110_1011 : temp_key_val <= 16'h0004; 8'b1110_0111 : temp_key_val <= 16'h0008; 8'b1101_1110 : temp_key_val <= 16'h0010; 8'b1101_1101 : temp_key_val <= 16'h0020; 8'b1101_1011 : temp_key_val <= 16'h0040; 8'b1101_0111 : temp_key_val <= 16'h0080; 8'b1011_1110 : temp_key_val <= 16'h0100; 8'b1011_1101 : temp_key_val <= 16'h0200; 8'b1011_1011 : temp_key_val <= 16'h0400; 8'b1011_0111 : temp_key_val <= 16'h0800; 8'b0111_1110 : temp_key_val <= 16'h1000; 8'b0111_1101 : temp_key_val <= 16'h2000; 8'b0111_1011 : temp_key_val <= 16'h4000; 8'b0111_0111 : temp_key_val <= 16'h8000; default: temp_key_val <= 16'h0000; endcase end else temp_key_val <= 16'h0000; end end assign {key_15,key_14,key_13,key_12,key_11,key_10,key_9,key_8,key_7,key_6,key_5,key_4,key_3,key_2,key_1,key_0} = temp_key_val; key_signl key_signl_1 ( .clk(clk), .rst_n(rst_n), .key_0(key_0), .key_1(key_1), .key_2(key_2), .key_3(key_3), .key_4(key_4), .key_5(key_5), .key_6(key_6), .key_7(key_7), .key_8(key_8), .key_9(key_9), .key_10(key_10), .key_11(key_11), .key_12(key_12), .key_13(key_13), .key_14(key_14), .key_15(key_15), .seg_bit(seg_bit), .seg_data(seg_data) ); endmodule
辅助验证程序:
/********************************Copyright************************************** **----------------------------File information-------------------------- ** File name :key_signl.v ** CreateDate :2015. ** Funtions : 测试单个按键的好与坏,按下按键是,数码管会显示响应的值,没有按下时,数码管无显示 ** Operate on :M5C06N3L114C7 ** Copyright :All rights reserved. ** Version :V1.0 **---------------------------Modify the file information---------------- ** Modified by : ** Modified data : ** Modify Content: *******************************************************************************/ module key_signl( clk, rst_n, key_0, key_1, key_2, key_3, key_4, key_5, key_6, key_7, key_8, key_9, key_10, key_11, key_12, key_13, key_14, key_15, seg_bit, seg_data ); input clk; input rst_n; input key_0; input key_1; input key_2; input key_3; input key_4; input key_5; input key_6; input key_7; input key_8; input key_9; input key_10; input key_11; input key_12; input key_13; input key_14; input key_15; output seg_bit; output [7:0] seg_data; //---------------------------------------------// reg [3:0] vaule; reg prass_flag; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin vaule <= 0; prass_flag <= 0; end else begin if(key_0 == 0) begin prass_flag <= 1; vaule <= 0; end else if(key_1 == 0) begin prass_flag <= 1; vaule <= 1; end else if(key_2 == 0) begin prass_flag <= 1; vaule <= 2; end else if(key_3 == 0) begin prass_flag <= 1; vaule <= 3; end else if(key_4 == 0) begin prass_flag <= 1; vaule <= 4; end else if(key_5 == 0) begin prass_flag <= 1; vaule <= 5; end else if(key_6 == 0) begin prass_flag <= 1; vaule <= 6; end else if(key_7 == 0) begin prass_flag <= 1; vaule <= 7; end else if(key_8 == 0) begin prass_flag <= 1; vaule <= 8; end else if(key_9 == 0) begin prass_flag <= 1; vaule <= 9; end else if(key_10 == 0) begin prass_flag <= 1; vaule <= 10; end else if(key_11 == 0) begin prass_flag <= 1; vaule <= 11; end else if(key_12 == 0) begin prass_flag <= 1; vaule <= 12; end else if(key_13 == 0) begin prass_flag <= 1; vaule <= 13; end else if(key_14 == 0) begin prass_flag <= 1; vaule <= 14; end else if(key_15 == 0) begin prass_flag <= 1; vaule <= 15; end else begin prass_flag <= 0; vaule <= 0; end end end reg [7:0] temp_data; //共阳数码管 always @(posedge clk or negedge rst_n) begin if(!rst_n) begin temp_data <= 8'hff; end else begin case(vaule) 'd0: temp_data <= 8'hc0; 'd1: temp_data <= 8'hf9; 'd2: temp_data <= 8'ha4; 'd3: temp_data <= 8'hb0; 'd4: temp_data <= 8'h99; 'd5: temp_data <= 8'h92; 'd6: temp_data <= 8'h82; 'd7: temp_data <= 8'hf8; 'd8: temp_data <= 8'h80; 'd9: temp_data <= 8'h98; 'd10: temp_data <= 8'h88; 'd11: temp_data <= 8'h83; 'd12: temp_data <= 8'hc6; 'd13: temp_data <= 8'ha1; 'd14: temp_data <= 8'h86; 'd15: temp_data <= 8'h8e; default :temp_data <= 8'hff; endcase end end assign seg_data = temp_data; assign seg_bit = ~prass_flag; endmodule
仿真程序:
/********************************Copyright************************************** **----------------------------File information-------------------------- ** File name :testbench.v ** CreateDate :2015.07 ** Funtions : 测试文件 ** Operate on :M5C06N3L114C7 ** Copyright :All rights reserved. ** Version :V1.0 **---------------------------Modify the file information---------------- ** Modified by : ** Modified data : ** Modify Content: *******************************************************************************/ module testbench; reg clk; reg rst_n; reg [3:0] l_in; //列输入,一般接上拉,为高电平 wire [3:0] h_out; //行输出信号,低有效 wire key_0; wire key_1; wire key_2; wire key_3; wire key_4; wire key_5; wire key_6; wire key_7; wire key_8; wire key_9; wire key_10; wire key_11; wire key_12; wire key_13; wire key_14; wire key_15; wire seg_bit; wire [7:0] seg_data; keyboard_to_key u1( .clk, .rst_n, .l_in, .h_out, .key_0, .key_1, .key_2, .key_3, .key_4, .key_5, .key_6, .key_7, .key_8, .key_9, .key_10, .key_11, .key_12, .key_13, .key_14, .key_15, .seg_bit, .seg_data ); defparam u1.t_20ms = 99; parameter tck = 24; parameter t = 1000/tck; always #(t/2) clk = ~clk; initial begin clk = 0; rst_n = 0; l_in = 4'hf; #(5*t) rst_n = 1; #(100*t) l_in = 4'b1110; #(500*t) l_in = 4'b1111; #(1000*t) l_in = 4'b1101; #(500*t) l_in = 4'b1111; #(1000*t) l_in = 4'b1011; #(500*t) l_in = 4'b1111; #(1000*t) l_in = 4'b0111; #(500*t) l_in = 4'b1111; #(1000*t) l_in = 4'b1110; #(500*t) l_in = 4'b1111; end endmodule