[笔记]再笔记边干边学Verilog HDL –008

lab08—PS/2解码

DE2上有一个PS/2接口,可接键盘或鼠标,本实验利用PS/2接口外接一个键盘,并对其按键解码,按下X键,DE2上的LEDG3-0右移;按下W键,LEDG3-0左移,按下Ctrl,反转。

1. PS/2 简介

image

研究PS/2解码,只需关心数据和时钟引脚即可。下图是PS/2协议的时序图,读数据是在时钟的下降沿有效。PS/2的时钟大约为10khz。

image

PS/2一桢是11位,对其解码,只需关注1-8位数据位。

键盘编码:

键盘编码分为通码和断码,按下为通码,释放为断码。比如,按下W不放,每秒约输出10个0x1d。释放W,输出0xf0 0x1d。编码规则,一次只能一个有效输出。

2. 设计

image

ps2_module.v包含电平检测模块detect_module.v和ps2解码模块ps2_decode_module.v。detect_module.v用来检测ps2时钟的下降沿,ps2_decode_module.v用来对每帧数据(11位)解码和过滤,输出8位的ps2_data和一个高脉冲ps2_done,表示解码完成。

detect_module.v

 1 /**
2 * File name: detect_module.v
3 *
4 */
5
6 module detect_module
7 (
8 clk, rst_n,
9 ps2_clk,
10 h2l_sig
11 );
12
13 input clk;
14 input rst_n;
15 input ps2_clk;
16 output h2l_sig;
17
18 reg h2l_f1;
19 reg h2l_f2;
20
21 always @(posedge clk or negedge rst_n)
22 if (!rst_n)
23 begin
24 h2l_f1 <= 1'b1;
25 h2l_f2 <= 1'b1;
26 end
27 else
28 begin
29 h2l_f1 <= ps2_clk;
30 h2l_f2 <= h2l_f1;
31 end
32
33 assign h2l_sig = h2l_f2 & !h2l_f1;
34
35 endmodule
36

ps2_decode_module.v

 1 /**
2 * File name : ps2_decode_module.v
3 *
4 */
5
6 module ps2_decode_module
7 (
8 clk, rst_n,
9 h2l_sig, ps2_data_in,
10 ps2_data, ps2_done
11 );
12
13 input clk;
14 input rst_n;
15 input h2l_sig;
16 input ps2_data_in;
17 output [7:0] ps2_data;
18 output ps2_done;
19
20 reg [7:0] rdata;
21 reg [4:0] i;
22 reg isshift;
23 reg isdone;
24
25 always @(posedge clk or negedge rst_n)
26 if (!rst_n)
27 begin
28 rdata <= 8'd0;
29 i <= 5'd0;
30 isdone <= 1'b0;
31 end
32 else
33 case (i)
34 5'd0:
35 if (h2l_sig) i <= i + 1'b1;
36
37 5'd1, 5'd2, 5'd3, 5'd4, 5'd5, 5'd6, 5'd7, 5'd8:
38 if (h2l_sig)
39 begin
40 i <= i + 1'b1;
41 rdata[i-1] <= ps2_data_in;
42 end
43
44 5'd9, 5'd10:
45 if (h2l_sig)
46 i <= i + 1'b1;
47
48 5'd11:
49 if (rdata == 8'hf0)
50 i <= 5'd12;
51 else
52 i <= 5'd23;
53
54 5'd12, 5'd13, 5'd14, 5'd15, 5'd16, 5'd17, 5'd18, 5'd19, 5'd20, 5'd21, 5'd22:
55 if (h2l_sig)
56 i <= i + 1'b1;
57
58 5'd23:
59 begin
60 i <= i + 1'b1;
61 isdone <= 1'b1;
62 end
63
64 5'd24:
65 begin
66 i <= 5'd0;
67 isdone <= 1'b0;
68 end
69 endcase
70
71 assign ps2_data = rdata;
72 assign ps2_done = isdone;
73
74 endmodule
75
76
77

ps2_decode_module.v的技巧主要是对无关的数据位直接忽视,利用i <= i + 1跳过,第48行判断是否为通码,忽略断码后的通码。

ps2_module.v

 1 /**
2 * File name: ps2_module.v
3 *
4 */
5
6 module ps2_module
7 (
8 clk, rst_n,
9 ps2_clk, ps2_data_in,
10 ps2_data, ps2_done
11 );
12
13 input clk;
14 input rst_n;
15 input ps2_clk;
16 input ps2_data_in;
17 output [7:0] ps2_data;
18 output ps2_done;
19
20 wire h2l_sig;
21
22 detect_module U1
23 (
24 .clk (clk),
25 .rst_n (rst_n),
26 .ps2_clk (ps2_clk),
27 .h2l_sig (h2l_sig)
28 );
29
30 ps2_decode_module U2
31 (
32 .clk (clk),
33 .rst_n (rst_n),
34 .h2l_sig (h2l_sig),
35 .ps2_data_in (ps2_data_in),
36 .ps2_data (ps2_data),
37 .ps2_done (ps2_done)
38 );
39
40 endmodule
41

cmd_control_module.v

 1 /**
2 * File name: cmd_control_module.v
3 *
4 */
5
6 module cmd_control_module
7 (
8 clk, rst_n,
9 ps2_done, ps2_data,
10 data_out
11 );
12
13 input clk;
14 input rst_n;
15 input ps2_done;
16 input [7:0] ps2_data;
17 output [3:0] data_out;
18
19 reg [3:0] rdata;
20
21 always @(posedge clk or negedge rst_n)
22 if (!rst_n)
23 begin
24 rdata <= 4'b0001;
25 end
26 else if (ps2_done)
27 case (ps2_data)
28 8'h1d: //W
29 rdata <= {rdata[2:0], rdata[3]};
30
31 8'h22: //X
32 rdata <= {rdata[0], rdata[3:1]};
33
34 8'h14: //Ctrl
35 rdata <= {rdata[0], rdata[1], rdata[2], rdata[3]};
36
37 endcase
38
39 assign data_out = rdata;
40
41 endmodule
42

exp08_module.v

 1 /**
2 * File name: exp08_module.v
3 * Function: use the ps/2 keyboard to test the de2's ps/2
4 * interface.
5 * x--right shift
6 * w--left shift
7 * ctrl--turn back
8 * Pins: PS2_DAT--X,W,Ctrl;
9 * KEY0--reset;
10 * LEDG3-0--data_out.
11 *
12 * yf.x
13 * 07-30-2011
14 *
15 */
16
17 module exp08_module
18 (
19 CLOCK_50, KEY,
20 PS2_CLK, PS2_DAT,
21 LEDG
22 );
23
24 input CLOCK_50;
25 input [0:0] KEY;
26 input PS2_CLK;
27 input PS2_DAT;
28 output [3:0] LEDG;
29
30 wire [7:0] ps2_data;
31 wire ps2_done;
32
33 ps2_module U1
34 (
35 .clk (CLOCK_50),
36 .rst_n (KEY),
37 .ps2_clk (PS2_CLK),
38 .ps2_data_in (PS2_DAT),
39 .ps2_data (ps2_data),
40 .ps2_done (ps2_done)
41 );
42
43 cmd_control_module U2
44 (
45 .clk (CLOCK_50),
46 .rst_n (KEY),
47 .ps2_done (ps2_done),
48 .ps2_data (ps2_data),
49 .data_out (LEDG)
50 );
51
52 endmodule
53

3. RTL 图

image

image 

4. 小结

PS/2解码,最重要的是利用通码,将通码编辑为有效的命令或触发事件。输出只是方式而已,不论是要显示字符还是命令。

原文地址:https://www.cnblogs.com/halflife/p/2123364.html