没有多大的技术含量,就是将用按键少的矩阵按键转化为普通按键,减少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
