• [笔记]再笔记边干边学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解码,最重要的是利用通码,将通码编辑为有效的命令或触发事件。输出只是方式而已,不论是要显示字符还是命令。

  • 相关阅读:
    js面向对象和PHP面相对象
    git
    css3动画、2D与3D效果
    渲染数据方式
    ajax
    面向对象
    Date 日期
    Math 数值对象
    What is CGLib and JDK动态代理
    IDEA中lock对象不提示newCondition();
  • 原文地址:https://www.cnblogs.com/halflife/p/2123364.html
Copyright © 2020-2023  润新知