デザイン思考
キーボード スキャンおよびエンコーダは、キーボードを使用してデジタル システムにデータを手動で入力するために使用され、キーが押されたかどうかを検出することによって、キーに対応する固有のスキャン コードが生成され、16 進キーボード回路のキーボード スキャンおよびエンコーダが使用されます。設計。
ステート マシンを使用して、検出信号の列位置をループします。ここで、ab/c は、a: S_row (すべての行信号 AND)、b: row (行信号)、c: Vaild (イネーブル信号) として表されます。S_0 は初期状態、S_i は i 番目の列の状態を検出することを意味し、S_5 は列信号が見つかったことを意味します。まず、S_rawが有効であることが検出されたら、ボタンが押されたことを意味し、このときすべてのカラム信号がセット(clo=1111、つまり15)された時点で、ロウ信号が順番に検出され、 S_1 状態の行が有効 (ボタンが押されたことを意味する) の場合、col の値を変更することで列番号が記録され、そうでない場合は、他の状態が順番に検出されます。 。
このモジュールは hex_keypad_grayhill として定義されています。入力信号には S_row と row が含まれ、出力信号には code (キーパッド文字)、valid、col が含まれます。S_row 信号と row 信号を使用すると、ステート マシンを通じて行信号の Col が検出され、コード (キーパッド文字) は、行と列を組み合わせることによって見つかります。)
上記のモジュールで使用される S_row は、デザイン モジュールに行信号行が与えられている限り、各行のライン値の OR を検出することによってモジュール シンクロナイザーによって決定できます。
したがって、最上位モジュール全体がキーパッドとして定義され、入力信号行が入力されると列colとcodeを出力することができます。
キーパッドに初期行値を与える方法については、row_signal モジュール (アナログ キーボード信号モジュール) を呼び出して、テスト モジュールを通じて行を生成できます。row_signal モジュールの入力信号は、列信号の Col と key (キーボード) であり、出力信号は、col と key. row の間の論理関係を通じて行われます。
row_sign 入力: キー、列; 出力: 行;
キーパッド入力: 行; 出力: コード、列;
シンクロナイザー入力: 行; 出力: S_row
hex_keypad_grayhill 入力: S_row、row; 出力: code、col;
したがって、テストするときは、まずアナログ キー信号ジェネレーターを使用してキー値 (文字) を設定し、row_signal を呼び出してキーの有効性を検出し、キーが配置されている行を特定してから、パラメーターをキーパッドに渡してキー値 (文字) を取得します。出力コード(文字)。
//顶层模块:
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_O=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)||(state==s_2)||(state==s_3)||(state==s_4))&&row;
always@(row or col)
case({row,col})
8'b0001_0001: code=0;
8'b0001_0010: code=1;
8'b0001_0100: code=2;
8'b0001_1000: code=3;
8'b0010_0001: code=4;
8'b0010_0010: code=5;
8'b0010_0100: code=6;
8'b0010_1000: code=7;
8'b0100_0001: code=8;
8'b0100_0010: code=9;
8'b0100_0100: code=10; //A
8'b0100_1000: code=11; //B
8'b1000_0001: code=12;
8'b1000_0010: code=13;
8'b1000_0100: code=14;
8'b1000_1000: code=15;
default code=O;
endcase
always@(state or s_row or row) //next-state logic
begin
next_state=state; col=O;
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_o;
else
state<=next_state;
endmodule
//计算s_row模块
module synchronizer(s_row, row,clock,reset);
output s_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<=O;
end
else
begin
a_row<=(row[0]||[row[1]||row[2]||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]||key[2]&&col[2]||key[3]&&col[3];
row[1]=key[4]&&col[0]||key[5]&&col[1]||key[6]&&coI[2]||key[7]&&col[3];
row[2]=key[8]&&col[0]||key[9]&&col[1]||key[10]&&col[2]||key[11]&&col[3];
row[3]=key[12]&&col[0]||key[13]&&col[1]||key[14]&&col[2]||key[15]&&col[3];
end
endmodule
//Testbench
module hex_keypad_grayhill_tb;
wire [3:0] code;
wire valid;
wire [3:0] col;
wire [3:0] row;
reg clock;
reg reset;
reg [15:0] key;
integer j,k;
reg [39:0] pressed;
parameter [39:0] key_0="key_o";
parameter [39:0] key_1="key_1";
parameter i39:0] key3="key_a";
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));// Simulatesignal generation
always@(key)
begin
case(key)
16'h0000: pressed=None;
16'h0001: pressed=key_0;
16'h0002: pressed=key_1;
16'h0004: pressed=key_2;
16'h0008: pressed=key_3;
16'h0010: pressed=key_4;
16'h0020: pressed=key_5;
16'h0040: pressed=key_6;
16'h0080: pressed=key_7;
16'h0100: pressed=key_8;
16'h0200: pressed=key_9;
16'h0400: pressed=key_A;
16'h0800: pressed=key_B;
16'h1000: pressed=key_C;
16'h2000: pressed=key_D;
16'h4000: pressed=key_E;
16'h8000: pressed=key_F;
default:pressed=None;
endcase
end
initial #2000 $stop;
initial
begin
clock=O;
forever #5 clock=~clock;
end
initial
begin
reset=1;
#10 reset=0;
end
initial
begin
for(k=O;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