FPGA矩阵键盘驱动设计

阅读了小梅哥的FPGA的系统设计与验证实战指南矩阵键盘这一节,了解了矩阵键盘的原理,会写Verilog代码去驱动矩阵键盘,Verilog代码中采用的是三段式状态机的方式。

图片节选自小梅哥的文档
在这里插入图片描述
代码如下

//矩阵键盘模块
module key_4(clk,rst_n,col,row,key_flag,key_value);
	
	input clk;
	input rst_n;
	input [3:0]row;
	
	output reg key_flag;
	output reg [3:0]key_value;
	output reg [3:0]col;
	
	reg [3:0]row_r;
	reg [4:0]c_state,n_state;
	reg [7:0]key_value_r;
	reg en_delay;
	reg [19:0]delay;
	
	parameter CNT_MAX = 999_999;
	
	localparam
		scan 			= 5'b00001,
		judge  		= 5'b00010,
		filter0 	 	= 5'b00100,
		down			= 5'b01000,
		filter1	 	= 5'b10000;

//寄存行的值	
	always@(posedge clk or negedge rst_n)
	if(!rst_n)
		row_r <= 0;
	else 
		row_r <= row;

		
//状态机第一段		
	always@(posedge clk or negedge rst_n)
	if(!rst_n)
		c_state <= scan;
	else 
		c_state <= n_state;

//状态机第二段		
	always@(*)
		begin
			n_state = 5'bxxxxx;
			case(c_state)
				scan: n_state = judge;
						
				judge:
					if(row_r != 4'b1111)
						n_state = filter0;
					else 
						n_state = scan;
					
				filter0:
					if(delay == CNT_MAX) 
						begin
							if(row_r != 4'b1111)
								n_state = down;
							else 
								n_state = scan;
						end 
					else
						n_state = c_state;
						
				down:
					if(row_r == 4'b1111)
						n_state = filter1;
					else 
						n_state = c_state;
						
				filter1:
					if(delay == CNT_MAX) 
						begin
							if(row_r != 4'b1111)
								n_state = down;
							else 
								n_state = scan;
						end 
					else
						n_state = c_state;
				default:n_state = scan;
			endcase
		end 
					
//状态机第三段
	always@(posedge clk or negedge rst_n)
	if(!rst_n)
		begin
			en_delay <= 0;
			col <= 4'b1110;
			key_flag <= 0;
			key_value_r <= 0;
		end 
	else 
		begin
			case(n_state)
				scan:
					begin
						en_delay <= 0;
						col <= {col[2:0],col[3]};
					end 
					
				judge: key_flag <= 0;

				filter0:
					begin
						en_delay <= 1;
						if(delay == CNT_MAX-1)
							begin
								key_flag <= 1;
								key_value_r <= {row_r,col};
							end 
						else 
							begin
								key_flag <= 0;
								key_value_r <= 0;
							end 
					end 
				down:
					begin
						key_flag <= 0;
						en_delay <= 0;
						key_value_r <= 0;
					end 
					
				filter1:en_delay <= 1;
				
				default:
					begin
						en_delay <= 0;
						col <= 4'b1110;
						key_flag <= 0;
					end 
			endcase
		end	

//抖动20ms的时间计数		
	always@(posedge clk or negedge rst_n)
	if(!rst_n)
		delay <= 0;
	else if(en_delay)
		if(delay == CNT_MAX)
			delay <= 0;
		else 
			delay <= delay + 1'b1;
	else 
		delay <= 0;

//根据行和列的值确定输出按键值	
	always@(posedge clk or negedge rst_n)
	if(!rst_n)
		key_value <= 0;
	else 
		begin
			case(key_value_r)
				8'b1110_1110: key_value <= 4'd0;
				8'b1110_1101: key_value <= 4'd1;
				8'b1110_1011: key_value <= 4'd2;
				8'b1110_0111: key_value <= 4'd3;
				8'b1101_1110: key_value <= 4'd4;
				8'b1101_1101: key_value <= 4'd5;
				8'b1101_1011: key_value <= 4'd6;
				8'b1101_0111: key_value <= 4'd7;
				8'b1011_1110: key_value <= 4'd8;
				8'b1011_1101: key_value <= 4'd9;
				8'b1011_1011: key_value <= 4'd10;
				8'b1011_0111: key_value <= 4'd11;
				8'b0111_1110: key_value <= 4'd12;
				8'b0111_1101: key_value <= 4'd13;
				8'b0111_1011: key_value <= 4'd14;
				8'b0111_0111: key_value <= 4'd15;
				default:;
			endcase
		end 
endmodule 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值