1.IDE:Quartus II
2.设备:Cyclone II EP2C8Q208C8N
3.实验:数码管显示矩阵键盘按下的数字
4.时序图:
5.步骤:(1)行raw扫描
(2)行raw作为输出,列col作为输入
(3)20ms扫描一行
(4)特别要注意输入端口引脚的初始化电平,这个问题让我花了很久时间才发现。特别是 我所使用的开发板上面没有上拉或者下拉。
(5)矩阵键盘引脚分配
(6)原理图
(7) 运行效果
FPGA矩阵键盘运行效果
6.代码:
marix_keypad.v
/*
*col默认为输入高电平!!!
*/
module marix_keypad(
input wire sys_clk ,
input wire sys_rst_n ,
input wire [3:0] col ,
output reg [3:0] row ,
output reg [3:0] char
);
reg wait_filter ;
reg [19:0] cnt ;
parameter row_scan_period = 20'd1000_000; //20ms扫描一次
parameter first_row = 4'b1110;
parameter second_row = 4'b1101;
parameter third_row = 4'b1011;
parameter fourth_row = 4'b0111;
parameter first_col = 4'b1110;
parameter second_col = 4'b1101;
parameter third_col = 4'b1011;
parameter fourth_col = 4'b0111;
/*
*row扫描控制
*/
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
row <= first_row;
else if(cnt == row_scan_period && wait_filter == 1'b0) //循环扫描
row <= {row[2:0],row[3]};
else
row <= row;
end
/*
*char 字符赋值
*/
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0) begin
char <= 4'd0;
wait_filter <= 1'b0;
end
else if(row == first_row) begin //第一row扫描
case(col)
first_col : begin char <= 4'd0; wait_filter <= 1'b1; end
second_col : begin char <= 4'd1; wait_filter <= 1'b1; end
third_col : begin char <= 4'd2; wait_filter <= 1'b1; end
fourth_col : begin char <= 4'd3; wait_filter <= 1'b1; end
default : begin char <= char; wait_filter <= 1'b0; end
endcase
end
else if(row == second_row) begin //第二row扫描
case(col)
first_col : begin char <= 4'd4; wait_filter <= 1'b1; end
second_col : begin char <= 4'd5; wait_filter <= 1'b1; end
third_col : begin char <= 4'd6; wait_filter <= 1'b1; end
fourth_col : begin char <= 4'd7; wait_filter <= 1'b1; end
default : begin char <= char; wait_filter <= 1'b0; end
endcase
end
else if(row == third_row) begin //第三row扫描
case(col)
first_col : begin char <= 4'd8; wait_filter <= 1'b1; end
second_col : begin char <= 4'd9; wait_filter <= 1'b1; end
third_col : begin char <= 4'd10; wait_filter <= 1'b1; end
fourth_col : begin char <= 4'd11; wait_filter <= 1'b1; end
default : begin char <= char; wait_filter <= 1'b0; end
endcase
end
else if(row == fourth_row) begin //第四row扫描
case(col)
first_col : begin char <= 4'd12; wait_filter <= 1'b1; end
second_col : begin char <= 4'd13; wait_filter <= 1'b1; end
third_col : begin char <= 4'd14; wait_filter <= 1'b1; end
fourth_col : begin char <= 4'd15; wait_filter <= 1'b1; end
default : begin char <= char; wait_filter <= 1'b0; end
endcase
end
else begin
char <= char;
end
end
/*
*扫描计数器控制(2ms)
*/
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n == 1'b0)
cnt <= 20'd0;
else if(cnt == row_scan_period)
cnt <= 20'd0;
else
cnt <= cnt + 1'b1;
end
endmodule
顶层代码
module keypad_smg(
input sys_clk ,
input sys_rst_n ,
input wire [3:0] col ,
output wire [3:0] row ,
output wire qw ,
output wire bw ,
output wire sw ,
output wire gw ,
output wire [7:0] smg
);
wire [3:0] char ;
/*
*实例化矩阵键盘
*/
marix_keypad marix_keypad_inst(
.sys_clk (sys_clk ) ,
.sys_rst_n (sys_rst_n) ,
.col (col ) ,
.row (row ) ,
.char (char )
);
/*
*实例化数码管
*/
smg smg_inst
(
. clk (sys_clk ),
. rst_n (sys_rst_n ),
. data (char ),
. qw (qw ),
. bw (bw ),
. sw (sw ),
. gw (gw ),
. smg (smg )
);
endmodule