【【verilog典型电路设计之键盘扫描和编码器】】

verilog典型电路设计之键盘扫描和编码器

典型电路设计之键盘扫描和编码器
键盘扫描和编码器用于在拥有键盘的数字系统中手工输入数据,通过检测按钮是否按下,产生一个唯一对应此按键的扫描码。

例: 用Verilog HDL 设计十六进制键盘电路的键盘扫描和编码器
在这里插入图片描述
我们面对如图所示的十六进制的键盘电路的键盘扫描和编码器
我们键盘的每一行都会通过一个下拉电阻连接到地,而行与列之间有一个以按键为开关的连接,当按下按键时,行与列之间就建立了连接。 如果列线的值为1,则由按键连接到的那个列的行值也会被拉升到1,反之行线将会被下拉至0。通过键盘扫描码发生器单元来控制列线,使列线上的电压有规律而有效地检测行线的电压值,进而来确定按下按键的位置。

键盘扫描码发生器必须具备检测识别按键,并产生一个与按键唯一对应扫描码输出的功能。为此可以设计一个时序状态机,通过不同状态之间的转换来实现信号的检测识别以及对应扫描码的输出。首先,令所有的列线同时为1来检测行线的值,直到发现一条行线的值被上拉为1,此时说明有按键被按下,但是仍然不能确定按键的位置;然后,通过依次将列线的值拉高来检测各个行线的值,直到检测到一条行线的值为1为止。

我怕不理解再解释一下
就是如下图
在这里插入图片描述
意思是指列线其实是横跨在行线上的 当开关合上时,列线一旦为1 就会带起行线连接 使得这条行线也会为1

下图是控制信号的状态转移图
在这里插入图片描述
下表是键盘编码表对应的值
在这里插入图片描述
为了使测试更接近于真实的物理环境,测试平台中必须包括模拟按键状态的信号发生器,能确认按键对应行线的模块Row_Signal和被测试模块Hex_Keypad_Grayhill_072。模拟按键状态的信号发生器可以嵌入在测试平台中,通过不断地给key信号赋值,模拟产生不同的按键信号。Row_Signal模块用于检测按键的有效性并确定按键所处的行。而Synchronizer模块通过检测各个行线值的或来确定是否有按键按下,当此模块的输出发生变化时,被测模块Hex_Keypad Grayhill_072将会确定按键的位置并输出相应的代码

下面是代码
其Verilog HDL程序代码是:/顶层模块:

module keypad(clock,reset,row,code,vaild,col);
input clock,reset;
input [3:0] row;
output [3:0] code;
output vaild;
output [3:0] col;
wire s_row;
hex_keypad_grayhill U1(.code(code),.col(col),.valid(valid),
.row(row),.s_row(s_row),.clock(clock),
.reset(reset));
synchronizer U2(.s_row(s_row),.row(row),.clock(clock),.reset(reset));endmodule
编码模块:
module hex_keypad_grayhill(code,col,valid,row,s_row,clock,reset);output[3:0] code ;
output valid;
output[3:0] col;
input[3:0]  row;
input s_row;
input clock,reset;
reg[3:0] col;
reg[3:0] code;
reg [5:0] state,next_state;
parameter s_0=6'b000001,s_1=6'b000010,s_2=6'b000100;
parameter s_3=6'b001000,s_4=6'b010000,s_5=6'b100000;
assign valid=((state==s_1)lI(state==s_2)ll(state==s_3)|l(state==s_4))&&row;
always@(row or col)
case({row,col})
8'b0001_0001: code=0;
8'b0001_0010: code=1;
18'b0001_0100: code=2;
8'b0001_1000: code=3;
8'b0010_0001: code=4;
8'b0010_0010: code=5;
8'b0010_0100: code=6;//6
8'b0010_1000: code=7;//7
8'b0100_0001: code=8;
8'b0100_0010: code=9;
8'b0100_0100: code=10;
8'b0100_1000: code=11;//B
8'b1000_0001: code=12;
8'b1000_0010: code=13;//D
8'b1000_0100: code=14; 
8'b1000_1000: code=15;//F
default code=0;
endcase
always@(state or s_row or row) //next-state logic
begin
next_state=state; col=0;
case(state)
s_0:begin col=15;
if(s_row) next_state=s_1;
end
s_1:begin col=1;
if(row) next_state=s_5;
else next_state=s_2;
end
s_2:begin col=2;
if(row)  next_state=s_5;
else 
next_state=s_3;
end
s_3:begin
col=4;
if(row) next_state=s_5;
else
next_state=s_4;
end
s_4:begin col=8;
if(row)  next_state=s_5;
else next_state=s_0;
end
s_5: begin
col=15;
if(!row)  next_state=s_0;
end
endcase end
always@( posedge clock or posedge reset)
if(reset) state<=s_0;
else state<=next_state;
endmodule
module synchronizer(s_row,row,clock,reset);
outputs_row;
input [3:0] row;
input clock,reset;
reg  a_row,s_row;
always@(negedge clock or posedge reset)begin
if(reset)begin
a_row<=0; 
s_row<=0;
end
else begin
a_row<=(row[o]l[row[1]llrow[2]l[row[3]);
s_row<=a_row;
end
end
endmodule
//模拟键盘产生信号
module row_signal(row,key,col);
output [3:0] row;
input [15:0] key;
input [3:0] col;reg[3:0] row;
always@(key or col)begin
row[0]=key[0]&&col[0][|key[1]&&col[1]l|key[2]&&colI[2]key[3]&&col[3];
row[1]=key[4]&&col[0]l|key[5]&&coI[1]|key[6]&&col[2]lkey[7]&&col[3];
row[2]=key[8]&&col[0][lkey[9]&&col[1][|key[10]&&col[2]|key[11]&&col[3];
row[3]=key[12]&&coI[0][|key[13]&&col[1]llkey[14]&&col[2]llkey[15]&&colI[3];
end
endmodule

下面是testbench

//Testbench
module hex_keypad_grayhill_tb;wire [3:0] code;
wirevalid;wire [3:0] col;wire [3:0] row;reg
clock;regreset;reg [15:0] key;integer j,k;
reg [39:0] pressed;
parameter [39:0] key_O="key_o";
parameter [39:0] key_1="key_1";
parameter [39:0] key_2="key_2";
parameter [39:0] key_3="key_3";
parameter [39:0] key_4="key_4";
parameter [39:0] key_5="key_5";
parameter [39:0] key_6="key_6";
parameter [39:0] key_7="key_7";
parameter [39:0] key_8="key_8";
parameter [39:0] key_9="key_9";
parameter [39:0] key_A="key_A";parameter [39:0] key_B="key_B";parameter [39:0] key_C="key_c";parameter [39:0] key_D="key_D";parameter [39:0] key_E="key_E";parameter [39:0] key_F="key_F";parameter [39:0] None="None";
keypad
U1(.clock(clock),.reset(reset),.row(row),.code(code),.vaild(vaild),.col(col));
//top module
row_signal U2(.row(row),.key(key),.col(col)); ll Simulatesignal generation

always@(key)begincase(key)
16'h0000: pressed=None;
16'h0001: pressed=key_o;
16'hO002: pressed=key_1;
16'h0004: pressed=key_2;
16'h0008:
 pressed=key_3;
initial #2000 $stop;
initial begin clock=0;
forever #5 clock=~clock;
end
initial begin reset=1;
#10 reset=0;
end
initial begin for(k=0;k<=1;k=k+1)
begin 
key=0;
#20 for(j=0;j<=16;j=j+1)
begin
#20 key[j]=1;
#60 key=0;
end
end 
end
endmodule
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的八位数码扫描显示电路Verilog HDL代码: ``` module digit_scan_display(clk, reset_n, data_in, seg_out, dig_out); input clk, reset_n; input [7:0] data_in; output reg [6:0] seg_out; output reg [7:0] dig_out; // 数码管显示码表 // a // f b // g // e c // d // 0x3F表示0, 0x06表示1, 0x5B表示2, 0x4F表示3, 0x66表示4, // 0x6D表示5, 0x7D表示6, 0x07表示7, 0x7F表示8, 0x6F表示9 reg [9:0] digit_code = {10'd63, 10'd6, 10'd91, 10'd79, 10'd102, 10'd109, 10'd125, 10'd7, 10'd127, 10'd111}; reg [2:0] digit_num = 3'b000; // 当前扫描的数码管编号 reg [23:0] scan_cnt = 24'd0; // 扫描计数器,用于控制扫描频率 // 译码电路 always @ (posedge clk or negedge reset_n) begin if (~reset_n) begin seg_out <= 7'b111_1111; dig_out <= 8'b1111_1110; end else begin seg_out <= ~digit_code[data_in]; dig_out <= ~(1 << digit_num); end end // 扫描电路 always @ (posedge clk or negedge reset_n) begin if (~reset_n) begin digit_num <= 3'b000; scan_cnt <= 24'd0; end else begin if (scan_cnt >= 24'd200000) begin // 扫描频率为 50 Hz scan_cnt <= 24'd0; digit_num <= digit_num + 1'b1; if (digit_num >= 3'b100) begin digit_num <= 3'b000; end end else begin scan_cnt <= scan_cnt + 1'b1; end end end endmodule ``` 该代码中包括了译码电路扫描电路两部分。 译码电路将输入的八位数据译码成七段数码管的输出码,同时控制当前扫描的数码管编号。 扫描电路则根据时钟信号控制扫描频率,并通过控制数码管编号实现数码管的扫描显示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值