module jz_keys(
input clk,
input rst,
input [3:0] row, // 矩阵键盘 行
output reg [3:0] col, // 矩阵键盘 列
output reg [6:0] keyboard_val // 键盘值
);
//++++++++++++++++++++++++++++++++++++++
// 状态机部分 开始
//++++++++++++++++++++++++++++++++++++++
// 状态编码
parameter NO_KEY_PRESSED = 6'b000_001; // 没有按键按下
parameter SCAN_COL0 = 6'b000_010; // 扫描第0列
parameter SCAN_COL1 = 6'b000_100; // 扫描第1列
parameter SCAN_COL2 = 6'b001_000; // 扫描第2列
parameter SCAN_COL3 = 6'b010_000; // 扫描第3列
parameter KEY_PRESSED = 6'b100_000; // 有按键按下
parameter delay = 6'b111_111; //延时5ms
reg [5:0] current_state, next_state; // 现态、次态
reg key_pressed_flag; // 键盘按下标志
reg [3:0] col_reg, row_reg; // 列值、行值
reg delay_en; //延时5ms后使能端为1,否则为0
reg [10:0]c0;
reg clk0;
always @(posedge clk or negedge rst)
if(!rst)
current_state<=NO_KEY_PRESSED;
else
current_state<=next_state;
always @*
begin
case(current_state)
NO_KEY_PRESSED:
if(row!=4'b1111) next_state=SCAN_COL0;
else begin next_state=NO_KEY_PRESSED;end
SCAN_COL0:begin
if(row!=4'b1111) next_state=delay;
else if((row!=4'b1111)&&(delay_en==1))
next_state=KEY_PRESSED;
else next_state=SCAN_COL1; end
SCAN_COL1: begin
if(row!=4'b1111) next_state=delay;
else if((row!=4'b1111)&&(delay_en==1))
next_state=KEY_PRESSED;
else next_state=SCAN_COL2; end
SCAN_COL2: begin
if(row!=4'b1111) next_state=delay;
else if((row!=4'b1111)&&(delay_en==1))
next_state=KEY_PRESSED;
else next_state=SCAN_COL3; end
SCAN_COL3: begin
if(row!=4'b1111) next_state=delay;
else if((row!=4'b1111)&&(delay_en==1))
next_state=KEY_PRESSED;
else next_state=NO_KEY_PRESSED; end
KEY_PRESSED:begin
if((row!=4'b1111)&&(delay_en==1))
next_state=KEY_PRESSED;
else next_state=NO_KEY_PRESSED; end
default: next_state=NO_KEY_PRESSED;
endcase
end
always @ (posedge clk0 or negedge rst)
begin
if (!rst)
begin
col<= 4'h0; key_pressed_flag<=0;
end
else
case(next_state)
NO_KEY_PRESSED:begin col<=4'b0000;key_pressed_flag<=0;end
SCAN_COL0: col<=4'b1110;
SCAN_COL1: col<=4'b1101;
SCAN_COL2: col<=4'b1011;
SCAN_COL3: col<=4'b0111;
KEY_PRESSED: begin
col_reg<=col;row_reg<=row;
key_pressed_flag<=1;
end
endcase
end
always@(posedge clk0 or negedge rst) begin
if(!rst) keyboard_val<=7'b0000000;
else if(key_pressed_flag)
begin
case({col_reg,row_reg})
8'b1110_1110: keyboard_val<=7'b1111110; //显示"0"
8'b1110_1101: keyboard_val<=7'b0110011; //显示"4"
8'b1110_1011: keyboard_val<=7'b1111111; //显示"8"
8'b1110_0111: keyboard_val<=7'b1001111; //显示"C"
8'b1101_1110: keyboard_val<=7'b0110000; //显示"1"
8'b1101_1101: keyboard_val<=7'b1011011; //显示"5"
8'b1101_1011: keyboard_val<=7'b1110011; //显示"9"
8'b1101_0110: keyboard_val<=7'b0111101; //显示"d"
8'b1011_1110: keyboard_val<=7'b1101101; //显示"2"
8'b1011_1101: keyboard_val<=7'b1011111; //显示"6"
8'b1011_1011: keyboard_val<=7'b1110111; //显示"A"
8'b1011_0111: keyboard_val<=7'b1001111; //显示"E"
8'b0111_1110: keyboard_val<=7'b1111001; //显示"3"
8'b0111_1101: keyboard_val<=7'b1110000; //显示"7"
8'b0111_1011: keyboard_val<=7'b0011111; //显示"b"
8'b0111_0111: keyboard_val<=7'b1000111; //显示"F"
default: keyboard_val<=7'b0000000;
endcase
end
end
always @(posedge clk or negedge rst)
begin //分频为5KHz
if(next_state==delay)
begin
if (!rst)
begin
c0<=0;
clk0<=1'b0;
end
else if(c0<2000)begin c0<=c0+1;delay_en>=0;end
else begin clk0<=~clk0; c0<=0;delay_en=1;end
end end
endmodule
预览源代码打印关于001 //这里将共阳数码管位选信号省略了,在硬件电路上我直接将其接高低平了
002 module mat_keyscan(clk,rst_n,col,row,seg_data); //接口设置
003 input clk,rst_n;
004 input [3:0] row; //4行
005 output reg [3:0] col; //4列
006 output reg [7:0] seg_data; //输出所按下键的编号
007 wire [7:0] data;
008 assign data= key_data; //
009 parameter clk_20ms_par = 1000000; //延时20ms所需要的计数次数
010 reg clk_20ms; //周期为20ms的高脉冲
011 reg [19:0] clk_20ms_r; //用于计数的寄存器
012 //一下always语句用于产生一个周期为20ms的高脉冲clk_20ms
013 always@(posedge clk,negedge rst_n)
014 if(!rst_n)
015 clk_20ms_r <= 20'b0;
016 else
017 if(clk_20ms_r == clk_20ms_par)
018 begin
019 clk_20ms_r <= 20'b0;
020 clk_20ms <= 1'b1;
021 end
022 else
023 begin
024 clk_20ms_r <= clk_20ms_r+1'b1;
025 clk_20ms <= 1'b0;
026 end
027
028 wire [7:0] colrow;
029 assign colrow = {col[3:0],row[3:0]}; //将行值和列值输出
030
031 parameter coln = 5'b00_001,
032 col0 = 5'b00_010,
033 col1 = 5'b00_100,
034 col2 = 5'b01_000,
035 col3 = 5'b10_000;
036 reg [4:0] state;
037 reg [7:0] key_data_buf,key_data;
038 reg [1:0] delay;
039 always@(posedge clk,negedge rst_n)
040 begin
041 if(!rst_n) //复位时对寄存器赋予初值
042 begin
043 delay <= 2'b0;
044 col <= 4'hf;
045 state <= coln;
046 end
047 else
048 begin
049 case(state)
050 coln: state <= col0;
051 col0: //col1,col2等与此类同,略去
052 begin
053 delay <= 2'b0;
054 col <= 4'b1110; //第一行输出低电平,其他全部输出为高电平
055 key_data_buf <= colrow; //寄存键值
056 if(clk_20ms)
057 delay <= delay+1'b1;
058 if(delay == 2'b01) //产生20ms(用于消抖)的延时后进入此if语句
059 begin
060 if(key_data_buf == colrow) //与之前的值相同,则将当前键值锁存,同时状态转移
061 begin
062 key_data <= key_data_buf; //将得到的值存入key_data
063 state <= col1;
064 end
065 else
066 state <= coln; //返回到初始状态
067 end
068 end
069 col1:
070 begin
071 delay <= 2'b0;
072 col <= 4'b1101; //第二行输出低电平,其他全部输出为高电平
073 key_data_buf <= colrow;
074 if(clk_20ms)
075 delay <= delay+1'b1;
076 if(delay == 2'b01)
077 begin
078 if(key_data_buf == colrow)
079 begin
080 key_data <= key_data_buf;
081 state <= col2;
082 end
083 else
084 state <= coln;
085