• PS2鼠标+LCD12864实验(调试未成功)


    此试验我一人调试许久都未成功,但发送ff时,读出来的数据确是对的,一开始让我窃喜,但发送f4时,读出来的数据确是错的,哎让苦恼啊,能力有限,只能先暂时就这样吧,那位什么还要贴出来呢,有两个原因:

    1、等自己能力达到一定时,在回过头来,把这个问题解决掉,我相信,一定能实现的。

    2、晒出来就是希望能得到各位网友能帮忙指点哪个地方容易出问题。在此先拜谢了!

    >>PS2鼠标实验是一个双向通信实验,那就得知道PS2鼠标传输协议,本人觉得自己对PS2传输协议有所掌握(也许理解的还不够到位)。具体传输协议就不多描述,还是看专业的“PS/2 技术参考”。

    >>在写代码之前,我参考网上一个例子,链接“http://www.360doc.com/content/13/0612/20/2260882_292421295.shtml”,这位网友例化时,看起来有点累,思路基本能看懂,自己稍微整理了一下,整体框架如下图。

    步骤:

    1、先由控制模块启动发送模块,把指令“0XF4”发送给鼠标。

    2、发送模块发送完后,产生一个发送完标志,传给控制模块,在由控制模块启动接收模块。

    3、接收模块接收完数据,产生一个接收完标志,传给控制模块,模块在进行相应的数据处理。

    4、数据处理完后,传给显示模块进行显示。

    代码实现:

    ps2_data_control.v

      1 module ps2_data_control(
      2                          //input 
      3                          sys_clk,
      4                          rst_n, 
      5                          send_done_sig,  //发送完标志
      6                          rx_done_sig,    //接收完标志
      7                          data_buf,        //接收到的数据
      8                          
      9                          //output
     10                          rx_en,            //接收使能
     11                          send_en,        //发送使能
     12                          send_cmd,        //要发送的命令
     13                          dis_data_low1,        //要显示的数据
     14                          dis_data_hig1,
     15                          
     16                          dis_data_low2,        //要显示的数据
     17                          dis_data_hig2,
     18                          
     19                          dis_data_low3,        //要显示的数据
     20                          dis_data_hig3,
     21                          
     22                          dis_data_low4,        //要显示的数据
     23                          dis_data_hig4,
     24                          
     25                          dis_data_btn
     26                          );
     27 input sys_clk;
     28 input rst_n;
     29 input send_done_sig;
     30 input rx_done_sig;
     31 input [7:0] data_buf;
     32 
     33 output rx_en;
     34 output send_en;
     35 output [7:0] send_cmd;
     36 output [7:0] dis_data_low1;
     37 output [7:0] dis_data_hig1;
     38 output [7:0] dis_data_low2;
     39 output [7:0] dis_data_hig2;
     40 output [7:0] dis_data_low3;
     41 output [7:0] dis_data_hig3;
     42 output [7:0] dis_data_low4;
     43 output [7:0] dis_data_hig4;
     44 output [7:0] dis_data_btn;
     45 /**********************************************************************/
     46 parameter  T100MS = 23'd4_999_999;
     47 parameter  T500MS = 25'd24_999_999;
     48 parameter  T100US = 13'd4_999;
     49 parameter   PS2_RST    = 8'hf4;  //复位cmd
     50 parameter   PS2_EN     = 8'hf4;  //数据报告使能cmd
     51 parameter   IDLE          = 4'd0,
     52             SEND_PS2_RST  = 4'd1,
     53             RX_EN1        = 4'd2,
     54             RX_ANSWER_FA  = 4'd3,
     55             RX_ANSWER_AA  = 4'd4,
     56             RX_ANSWER_ID  = 4'd5,
     57             SEND_PS2_EN   = 4'd6,
     58             RX_EN2        = 4'd7,
     59             RX_ANSWER2    = 4'd8,
     60             RX_BYTE1      = 4'd9,
     61             RX_BYTE2      = 4'd10,
     62             RX_BYTE3      = 4'd11,
     63             DELAY         = 4'd12,
     64             STOP          = 4'd13;        
     65 /**********************************************************************/
     66 //assign      send_cmd   = STREAM;
     67 /**********************************************************************/
     68 //200us计数器
     69 reg [24:0] cnt;
     70 always @(posedge sys_clk or negedge rst_n)
     71 if(!rst_n)
     72     cnt <= 25'd0;
     73 else if(!cnt_en || cnt == T500MS)
     74     cnt <= 25'd0;
     75 else 
     76     cnt <= cnt + 1'b1;
     77 /**********************************************************************/
     78 reg    send_en;
     79 reg rx_en;
     80 reg [7:0] data_answer;    //保存应答位
     81 reg x_sign;     //x的符号位 
     82 reg y_sign;        //y的符号位
     83 reg [7:0] x_move;  //x的偏移量
     84 reg [7:0] y_move;  //y的偏移量
     85 reg [3:0] state;
     86 reg [7:0] dis_data_temp1;
     87 reg [7:0] dis_data_temp2;
     88 reg [7:0] dis_data_temp3;
     89 reg [7:0] dis_data_temp4;
     90 reg [7:0] dis_data_btn;
     91 reg cnt_en;
     92 reg [7:0] send_cmd;
     93 always @(posedge sys_clk or negedge rst_n)
     94 if(!rst_n) begin
     95     send_en <= 1'b0;
     96     rx_en <= 1'b0;
     97     data_answer <= 8'h00;
     98     x_sign <= 1'b0;
     99     y_sign <= 1'b0;
    100     state <= IDLE;
    101     dis_data_temp1 <= 8'h00;
    102     dis_data_temp2 <= 8'h00;
    103     dis_data_temp3 <= 8'h00;
    104     dis_data_temp4 <= 8'h00;
    105     cnt_en <= 1'b0;
    106     dis_data_btn <= "X";
    107     send_cmd <= 8'h00;
    108 end
    109 else begin
    110     case(state)
    111         IDLE: 
    112         begin
    113             state <= SEND_PS2_RST;
    114             cnt_en <= 1'b1;
    115         end
    116         
    117         SEND_PS2_RST: //发送复位 0xff
    118         if(cnt == T100MS) begin
    119             cnt_en <= 1'b0;
    120             send_en <= 1'b1; //启动发送
    121             send_cmd <= PS2_RST;
    122             state <= RX_EN1;
    123         end
    124         
    125         RX_EN1:
    126         if(send_done_sig) begin
    127             rx_en <= 1'b1;
    128             send_en <= 1'b0;
    129             state <= RX_ANSWER_FA;
    130         end 
    131         
    132         RX_ANSWER_FA:  //接收鼠标发回的应答数据0xfa
    133         if(rx_done_sig) begin
    134             dis_data_temp1 <= data_buf;
    135             state <= RX_ANSWER_AA;//RX_BYTE1;
    136         end
    137         
    138         RX_ANSWER_AA:  //接收鼠标发回的应答数据0xaa
    139         if(rx_done_sig) begin
    140             dis_data_temp2 <= data_buf;
    141             state <= RX_ANSWER_ID;
    142         end
    143         
    144         RX_ANSWER_ID:  //接收鼠标发回的应答数据0x00
    145         if(rx_done_sig) begin
    146             dis_data_temp3 <= data_buf;
    147             cnt_en <= 1'b1;
    148             state <= SEND_PS2_RST;
    149         end
    150         
    151         SEND_PS2_EN: //发送0xf4
    152         if(cnt == T100MS)begin
    153             rx_en <= 1'b0;
    154             cnt_en <= 1'b0;
    155             send_en <= 1'b1; //启动发送
    156             send_cmd <= PS2_EN;
    157             state <= RX_EN2;
    158         end
    159         
    160         RX_EN2:
    161         if(send_done_sig) begin
    162             rx_en <= 1'b1; //启动接收
    163             send_en <= 1'b0;
    164             state <= RX_ANSWER2;
    165         end 
    166         
    167         RX_ANSWER2:  //第二次应答位
    168         if(rx_done_sig) begin
    169             dis_data_temp4 <= data_buf;
    170             state <= RX_BYTE1;
    171         end
    172         
    173         RX_BYTE1:
    174         if(rx_done_sig) begin
    175             if(data_buf[0] == 1'b1)//左键被按下
    176                 dis_data_btn <= "L";  
    177             else if(data_buf[1] == 1'b1) //右键被按下
    178                 dis_data_btn <= "R";  
    179             else if(data_buf[2] == 1'b1)  //中键被按下
    180                 dis_data_btn <= "M";
    181 
    182             x_sign <= data_buf[4];
    183             y_sign <= data_buf[5];
    184             
    185             state <= RX_BYTE2;
    186         end
    187         
    188         RX_BYTE2:
    189         if(rx_done_sig) begin //接收到第二个字节
    190             x_move <= data_buf;
    191             state <= RX_BYTE3;
    192         end
    193         
    194         RX_BYTE3:  //接收到第三个字节
    195         if(rx_done_sig) begin
    196             y_move <= data_buf;
    197             state <= STOP;
    198             cnt_en <= 1'b1;
    199         end 
    200         
    201         STOP:
    202         if(cnt == T100MS) begin
    203             cnt_en <= 1'b0;
    204             state <= RX_BYTE1;
    205         end
    206     endcase
    207 end
    208 
    209 reg [7:0] dis_data_low1;
    210 always @(dis_data_temp1[3:0])
    211     case(dis_data_temp1[3:0])
    212         4'h0: dis_data_low1 = "0";
    213         4'h1: dis_data_low1 = "1";
    214         4'h2: dis_data_low1 = "2";
    215         4'h3: dis_data_low1 = "3";
    216         4'h4: dis_data_low1 = "4";
    217         4'h5: dis_data_low1 = "5";
    218         4'h6: dis_data_low1 = "6";
    219         4'h7: dis_data_low1 = "7";
    220         4'h8: dis_data_low1 = "8";
    221         4'h9: dis_data_low1 = "9";
    222         4'ha: dis_data_low1 = "a";
    223         4'hb: dis_data_low1 = "b";
    224         4'hc: dis_data_low1 = "c";
    225         4'hd: dis_data_low1 = "d";
    226         4'he: dis_data_low1 = "e";
    227         4'hf: dis_data_low1 = "f";
    228     endcase
    229 
    230 reg [7:0] dis_data_hig1;
    231 always @(dis_data_temp1[7:4])
    232     case(dis_data_temp1[7:4])
    233         4'h0: dis_data_hig1 = "0";
    234         4'h1: dis_data_hig1 = "1";
    235         4'h2: dis_data_hig1 = "2";
    236         4'h3: dis_data_hig1 = "3";
    237         4'h4: dis_data_hig1 = "4";
    238         4'h5: dis_data_hig1 = "5";
    239         4'h6: dis_data_hig1 = "6";
    240         4'h7: dis_data_hig1 = "7";
    241         4'h8: dis_data_hig1 = "8";
    242         4'h9: dis_data_hig1 = "9";
    243         4'ha: dis_data_hig1 = "a";
    244         4'hb: dis_data_hig1 = "b";
    245         4'hc: dis_data_hig1 = "c";
    246         4'hd: dis_data_hig1 = "d";
    247         4'he: dis_data_hig1 = "e";
    248         4'hf: dis_data_hig1 = "f";
    249     endcase
    250     
    251 reg [7:0] dis_data_low2;
    252 always @(dis_data_temp2[3:0])
    253     case(dis_data_temp2[3:0])
    254         4'h0: dis_data_low2 = "0";
    255         4'h1: dis_data_low2 = "1";
    256         4'h2: dis_data_low2 = "2";
    257         4'h3: dis_data_low2 = "3";
    258         4'h4: dis_data_low2 = "4";
    259         4'h5: dis_data_low2 = "5";
    260         4'h6: dis_data_low2 = "6";
    261         4'h7: dis_data_low2 = "7";
    262         4'h8: dis_data_low2 = "8";
    263         4'h9: dis_data_low2 = "9";
    264         4'ha: dis_data_low2 = "a";
    265         4'hb: dis_data_low2 = "b";
    266         4'hc: dis_data_low2 = "c";
    267         4'hd: dis_data_low2 = "d";
    268         4'he: dis_data_low2 = "e";
    269         4'hf: dis_data_low2 = "f";
    270     endcase
    271 
    272 reg [7:0] dis_data_hig2;
    273 always @(dis_data_temp2[7:4])
    274     case(dis_data_temp2[7:4])
    275         4'h0: dis_data_hig2 = "0";
    276         4'h1: dis_data_hig2 = "1";
    277         4'h2: dis_data_hig2 = "2";
    278         4'h3: dis_data_hig2 = "3";
    279         4'h4: dis_data_hig2 = "4";
    280         4'h5: dis_data_hig2 = "5";
    281         4'h6: dis_data_hig2 = "6";
    282         4'h7: dis_data_hig2 = "7";
    283         4'h8: dis_data_hig2 = "8";
    284         4'h9: dis_data_hig2 = "9";
    285         4'ha: dis_data_hig2 = "a";
    286         4'hb: dis_data_hig2 = "b";
    287         4'hc: dis_data_hig2 = "c";
    288         4'hd: dis_data_hig2 = "d";
    289         4'he: dis_data_hig2 = "e";
    290         4'hf: dis_data_hig2 = "f";
    291     endcase
    292 
    293 reg [7:0] dis_data_low3;
    294 always @(dis_data_temp3[3:0])
    295     case(dis_data_temp3[3:0])
    296         4'h0: dis_data_low3 = "0";
    297         4'h1: dis_data_low3 = "1";
    298         4'h2: dis_data_low3 = "2";
    299         4'h3: dis_data_low3 = "3";
    300         4'h4: dis_data_low3 = "4";
    301         4'h5: dis_data_low3 = "5";
    302         4'h6: dis_data_low3 = "6";
    303         4'h7: dis_data_low3 = "7";
    304         4'h8: dis_data_low3 = "8";
    305         4'h9: dis_data_low3 = "9";
    306         4'ha: dis_data_low3 = "a";
    307         4'hb: dis_data_low3 = "b";
    308         4'hc: dis_data_low3 = "c";
    309         4'hd: dis_data_low3 = "d";
    310         4'he: dis_data_low3 = "e";
    311         4'hf: dis_data_low3 = "f";
    312     endcase
    313 
    314 reg [7:0] dis_data_hig3;
    315 always @(dis_data_temp3[7:4])
    316     case(dis_data_temp3[7:4])
    317         4'h0: dis_data_hig3 = "0";
    318         4'h1: dis_data_hig3 = "1";
    319         4'h2: dis_data_hig3 = "2";
    320         4'h3: dis_data_hig3 = "3";
    321         4'h4: dis_data_hig3 = "4";
    322         4'h5: dis_data_hig3 = "5";
    323         4'h6: dis_data_hig3 = "6";
    324         4'h7: dis_data_hig3 = "7";
    325         4'h8: dis_data_hig3 = "8";
    326         4'h9: dis_data_hig3 = "9";
    327         4'ha: dis_data_hig3 = "a";
    328         4'hb: dis_data_hig3 = "b";
    329         4'hc: dis_data_hig3 = "c";
    330         4'hd: dis_data_hig3 = "d";
    331         4'he: dis_data_hig3 = "e";
    332         4'hf: dis_data_hig3 = "f";
    333     endcase
    334     
    335 reg [7:0] dis_data_low4;
    336 always @(dis_data_temp4[3:0])
    337     case(dis_data_temp4[3:0])
    338         4'h0: dis_data_low4 = "0";
    339         4'h1: dis_data_low4 = "1";
    340         4'h2: dis_data_low4 = "2";
    341         4'h3: dis_data_low4 = "3";
    342         4'h4: dis_data_low4 = "4";
    343         4'h5: dis_data_low4 = "5";
    344         4'h6: dis_data_low4 = "6";
    345         4'h7: dis_data_low4 = "7";
    346         4'h8: dis_data_low4 = "8";
    347         4'h9: dis_data_low4 = "9";
    348         4'ha: dis_data_low4 = "a";
    349         4'hb: dis_data_low4 = "b";
    350         4'hc: dis_data_low4 = "c";
    351         4'hd: dis_data_low4 = "d";
    352         4'he: dis_data_low4 = "e";
    353         4'hf: dis_data_low4 = "f";
    354     endcase
    355 
    356 reg [7:0] dis_data_hig4;
    357 always @(dis_data_temp4[7:4])
    358     case(dis_data_temp4[7:4])
    359         4'h0: dis_data_hig4 = "0";
    360         4'h1: dis_data_hig4 = "1";
    361         4'h2: dis_data_hig4 = "2";
    362         4'h3: dis_data_hig4 = "3";
    363         4'h4: dis_data_hig4 = "4";
    364         4'h5: dis_data_hig4 = "5";
    365         4'h6: dis_data_hig4 = "6";
    366         4'h7: dis_data_hig4 = "7";
    367         4'h8: dis_data_hig4 = "8";
    368         4'h9: dis_data_hig4 = "9";
    369         4'ha: dis_data_hig4 = "a";
    370         4'hb: dis_data_hig4 = "b";
    371         4'hc: dis_data_hig4 = "c";
    372         4'hd: dis_data_hig4 = "d";
    373         4'he: dis_data_hig4 = "e";
    374         4'hf: dis_data_hig4 = "f";
    375     endcase
    376 endmodule 
    377         
    View Code

    ps2_send_control.v (注意ps2_clk和ps2_data控制方向)

      1 module ps2_send_control(
      2                         //input 
      3                         sys_clk,
      4                         rst_n,
      5                         send_en,    //发送使能
      6                         send_cmd,  //要发送的数据 0xf4
      7                         
      8                         //output
      9                         send_done_sig,//发送完标志
     10                         
     11                         //inout
     12                         ps2_clk,  //鼠标时钟
     13                         ps2_data  //鼠标数据
     14                        );
     15                        
     16 input  sys_clk;
     17 input  rst_n;
     18 input  send_en;
     19 input  [7:0] send_cmd;
     20 
     21 output send_done_sig;
     22 
     23 inout  ps2_clk;
     24 inout  ps2_data;
     25 /**************************************************************/
     26 parameter T200US = 14'd9999;
     27 parameter T40US = 11'd1999;
     28 parameter IDLE = 3'd0,
     29           PS2_CLK_SET0  = 3'd1,  //时钟拉低
     30           PS2_DATA_SET0 = 3'd2,     //数据拉低
     31           PS2_CLK_SET1  = 3'd3,  //释放时钟,拉高
     32           SEND_DATA     = 3'd4,  //发送8bit数据和校验位
     33           PS2_DATA_SET1 = 3'd5,  //释放数据,拉高
     34           STOP          = 3'd6;
     35 /**************************************************************/
     36 //如果send_data中有偶数个1,那么^send_data结果为0,否则为1,在取反即为奇校验位应设置的值
     37 wire odd_parity;
     38 assign odd_parity = ~(^send_cmd);  
     39 //上面这句,一位网友说是下面的操作方式
     40 //  ~(odd_parity ^send_cmd[0]) -> ~(~(odd_parity ^send_cmd[0]) ^send_cmd[1]) 
     41 //  -> ~(~(~(odd_parity ^send_cmd[0]) ^send_cmd[1]) ^send_cmd[2])... 一次类推
     42 /**************************************************************/
     43 //控制鼠标时钟和数据的方向
     44 //link_clk = 1,ps2_clk为output ,link_clk = 0,ps2_clk为input,FPGA内部得把该管脚设置为高阻态,以便接收时钟
     45 //link_data = 1,ps2_data为output ,link_data = 0,ps2_data为input,FPGA内部得把该管脚设置为高阻态,以便接受数据
     46 assign ps2_clk = link_clk ? ps2_clk_out : 1'bz;  
     47 assign ps2_data = link_data ? ps2_data_out : 1'bz;
     48 /**************************************************************/
     49 //200us计数器
     50 reg [13:0] cnt;
     51 always @(posedge sys_clk or negedge rst_n)
     52 if(!rst_n)
     53     cnt <= 14'd0;
     54 else if(!cnt_en || cnt == T200US)
     55     cnt <= 14'd0;
     56 else 
     57     cnt <= cnt + 1'b1;
     58 /**************************************************************/
     59 reg ps2_clk_1;
     60 reg ps2_clk_2;
     61 always @(posedge sys_clk or negedge rst_n)
     62 if(!rst_n) begin
     63     ps2_clk_1 <= 1'b1;
     64     ps2_clk_2 <= 1'b1;
     65 end
     66 else begin
     67     ps2_clk_1 <= ps2_clk;
     68     ps2_clk_2 <= ps2_clk_1;
     69 end
     70 
     71 wire ps2_clk_n;
     72 assign ps2_clk_n = ps2_clk_2& (~ps2_clk_1);
     73 /**************************************************************/
     74 reg link_clk;
     75 reg link_data;
     76 reg cnt_en;
     77 reg ps2_clk_out;
     78 reg ps2_data_out;
     79 reg send_done_sig;
     80 reg [2:0] state;
     81 reg [3:0] i;
     82 reg [8:0] s_data;
     83 always @(posedge sys_clk or negedge rst_n)
     84 if(!rst_n) begin
     85     link_clk      <= 1'b0;
     86     link_data     <= 1'b0;
     87     cnt_en        <= 1'b0;
     88     ps2_clk_out   <= 1'b1;
     89     ps2_data_out  <= 1'b1;
     90     send_done_sig <= 1'b0;
     91     state         <= IDLE;
     92     i             <= 4'd0;
     93     s_data        <= 9'd0;
     94 end
     95 else if(send_en) begin
     96     case(state)
     97         IDLE: 
     98         begin
     99             state <= PS2_CLK_SET0;
    100             s_data <= /*{1'b0,send_cmd}*/{odd_parity,send_cmd};
    101         end
    102         
    103         PS2_CLK_SET0:
    104         begin
    105             link_clk <= 1'b1;  //输出状态
    106             ps2_clk_out <= 1'b0;
    107             cnt_en <= 1'b1;  //启动计数器
    108             state <= PS2_DATA_SET0;
    109         end
    110         
    111         PS2_DATA_SET0: 
    112         if(cnt == T200US) begin  //200us后 拉低数据线
    113             cnt_en <= 1'b0;
    114             link_data <= 1'b1;
    115             ps2_data_out <= 1'b0;    
    116             state <= PS2_CLK_SET1;
    117         end
    118         
    119         PS2_CLK_SET1:
    120         /*if(cnt == T40US)*/begin
    121 //            cnt_en <= 1'b0;
    122             link_clk <= 1'b0;  //输入状态     link_clk置0的话,LCD上没有数据显示,写0还能显示几个数据
    123 //            ps2_clk_out <= 1'b1;  //释放时钟线
    124             state <= SEND_DATA;
    125         end
    126         
    127         SEND_DATA:
    128         if(ps2_clk_n) begin  //在时钟的下降沿设置数据
    129             if(i == 4'd9) begin
    130                 i <= 4'd0;
    131                 state <= PS2_DATA_SET1;
    132             end
    133             else begin
    134                 link_clk <= 1'b0;
    135                 link_data <= 1'b1;
    136                 ps2_data_out <= s_data[i];
    137                 i <= i + 1'b1;
    138                 state <= SEND_DATA;
    139             end
    140         end
    141         
    142         PS2_DATA_SET1:  //释放数据线 发送停止位
    143         if(ps2_clk_n) begin
    144             link_data <= 1'b1;
    145             ps2_data_out <= 1'b1;
    146             state <= STOP;
    147             send_done_sig <= 1'b1;
    148         end
    149         
    150         STOP:
    151         begin
    152             link_data <= 1'b0; //link_data置1的话,LCD上没有数据显示,写0还能显示几个数据
    153             state <= IDLE;
    154         end
    155     endcase 
    156 end
    157 
    158 endmodule
    View Code

    ps2_rx_control.v

     1 module ps2_rx_control(
     2                             //input 
     3                             sys_clk,
     4                             rst_n,
     5                             ps2_clk_in,  //鼠标时钟
     6                             ps2_data_in, //鼠标数据
     7                             rx_en,       //接收模块使能信号
     8                             
     9                             //output
    10                             rx_done_sig, //接收完标志信号
    11                             data_buf     //保存接收到的数据
    12                         );
    13 input sys_clk;
    14 input rst_n;
    15 input ps2_clk_in;
    16 input ps2_data_in;
    17 input rx_en;
    18 
    19 output rx_done_sig;
    20 output [7:0] data_buf;
    21 /**************************************************************/
    22 reg ps2_clk_in_1;
    23 reg ps2_clk_in_2;
    24 wire ps2_clk_in_n;
    25 always @(posedge sys_clk or negedge rst_n)
    26 if(!rst_n) begin
    27     ps2_clk_in_1 <= 1'b1;
    28     ps2_clk_in_2 <= 1'b1;
    29 end
    30 else begin
    31     ps2_clk_in_1 <= ps2_clk_in;
    32     ps2_clk_in_2 <= ps2_clk_in_1;
    33 end
    34 
    35 assign ps2_clk_in_n = ps2_clk_in_2 & (~ps2_clk_in_1);
    36 /**************************************************************/
    37 reg [3:0] i;
    38 reg [7:0] data_buf;
    39 reg rx_done_sig;
    40 always @(posedge sys_clk or negedge rst_n)
    41 if(!rst_n) begin
    42     i <= 4'd0;
    43     data_buf <= 8'h00;
    44     rx_done_sig <= 1'b0;
    45 end
    46 else if(rx_en/*ps2_clk_in_n*/) begin  //ps2_clk_in_n不能写在这个地方,rx_done_sig置1和置0没必要等到ps2_clk_in下降沿时设置,否则会出问题
    47     case(i)
    48         4'd0: 
    49         if(ps2_clk_in_n) begin
    50             i <= i + 1'b1;  //起始位不处理
    51         end
    52         4'd1,4'd2,4'd3,4'd4,4'd5,4'd6,4'd7,4'd8: //接收8位数据
    53         if(ps2_clk_in_n) begin
    54             i <= i + 1'b1;
    55             data_buf[i-1] <= ps2_data_in;
    56         end
    57 
    58         4'd9: 
    59         if(ps2_clk_in_n)
    60             i <= i + 1'b1;  //奇校验位不处理
    61     
    62         4'd10: 
    63         if(ps2_clk_in_n)
    64             i <= i + 1'b1;    //停止位不处理
    65         
    66         4'd11: 
    67         begin
    68             rx_done_sig <= 1'b1;  //标志着一帧数据接收完
    69             i <= i + 1'b1;
    70         end
    71         
    72         4'd12:
    73         begin
    74             rx_done_sig <= 1'b0;  //置0,给下次接收做好准备
    75             i <= 4'd0;
    76         end
    77     endcase
    78 end
    79 
    80 endmodule
    81 
    82         
    View Code

    LCD12864.v

      1 module LCD12864(
      2                     //input 
      3                     sys_clk,
      4                     rst_n,
      5                     dis_data_low1,
      6                     dis_data_hig1,
      7 
      8                     dis_data_low2,
      9                     dis_data_hig2,
     10 
     11                     dis_data_low3,
     12                     dis_data_hig3,
     13                     
     14                     dis_data_low4,
     15                     dis_data_hig4,
     16                     
     17                     dis_data_btn,
     18                     
     19                     //output 
     20                     lcd_rs,
     21                     lcd_rw,
     22                     lcd_en,
     23                     lcd_data,
     24                     lcd_psb
     25                 );
     26 input sys_clk;// 50MHZ
     27 input rst_n;
     28 input [7:0] dis_data_low1;
     29 input [7:0] dis_data_hig1;
     30 input [7:0] dis_data_low2;
     31 input [7:0] dis_data_hig2;
     32 input [7:0] dis_data_low3;
     33 input [7:0] dis_data_hig3;
     34 input [7:0] dis_data_low4;
     35 input [7:0] dis_data_hig4;
     36 
     37 input [7:0] dis_data_btn;
     38 
     39 output lcd_rs;//H:data    L:command
     40 output lcd_rw;//H:read module    L:write module
     41 output lcd_en;//H active
     42 output [7:0] lcd_data;
     43 output lcd_psb;//H:parallel    module    L:SPI module
     44 
     45 /***************************************************/
     46 parameter T3MS = 18'd149_999;
     47 parameter    IDLE           = 5'd0,
     48             INIT_FUN_SET1 = 5'd1,
     49             INIT_FUN_SET2 = 5'd2,
     50             INIT_DISPLAY  = 5'd3,
     51             INIT_CLEAR       = 5'd4,
     52             INIT_DOT_SET  = 5'd5,
     53             SET_DDRAM      = 5'd6,
     54             WRITE_DATA0      = 5'd7,
     55             WRITE_DATA1   = 5'd8,
     56             WRITE_DATA2   = 5'd9,
     57             WRITE_BLANK1  = 5'd10,
     58             WRITE_DATA3   = 5'd11,
     59             WRITE_DATA4   = 5'd12,
     60             WRITE_BLANK2  = 5'd13,
     61             WRITE_DATA5   = 5'd14,
     62             WRITE_DATA6   = 5'd15,
     63             SET_DDRAM1    = 5'd16,
     64             WRITE_DATA7   = 5'd17,
     65             WRITE_DATA8   = 5'd18,
     66             WRITE_DATA9   = 5'd19,
     67             SET_DDRAM2    = 5'd20,
     68             WRITE_DATA10  = 5'd21,
     69             WRITE_DATA11  = 5'd22;
     70 
     71 /***************************************************/
     72 //产生周期为6MS的lcd_clk给LCD
     73 reg [17:0] cnt;
     74 reg lcd_clk;
     75 always @(posedge sys_clk or negedge rst_n)
     76 if(!rst_n) begin
     77     cnt <= 18'd0;
     78     lcd_clk <= 1'b0;
     79 end
     80 else if(cnt == T3MS)begin
     81     cnt <= 18'd0;
     82     lcd_clk <= ~lcd_clk;
     83 end
     84 else
     85     cnt <= cnt + 1'b1;
     86 
     87 /***************************************************/
     88 reg lcd_rs;
     89 always @(posedge lcd_clk or negedge rst_n)
     90 if(!rst_n)
     91     lcd_rs <= 1'b0;
     92 else if(   (state == WRITE_DATA1)  || (state == WRITE_DATA2) 
     93         || (state == WRITE_DATA3)  || (state == WRITE_DATA4)
     94         || (state == WRITE_DATA5)  || (state == WRITE_DATA6)
     95         || (state == WRITE_DATA7)  || (state == WRITE_DATA8)
     96         || (state == WRITE_DATA9)  || (state == WRITE_DATA10)
     97         || (state == WRITE_DATA11) || (state == WRITE_DATA0)
     98         ||(state == WRITE_BLANK1)  || (state == WRITE_BLANK2))
     99     lcd_rs <= 1'b1;        //写数据模式
    100 else
    101     lcd_rs <= 1'b0;        //写命令模式
    102 /***************************************************/
    103 reg [4:0] state;
    104 reg [7:0] lcd_data;
    105 reg [6:0] num;
    106 reg en;
    107 always @(posedge lcd_clk or negedge rst_n)
    108 if(!rst_n) begin
    109     state <= IDLE;
    110     lcd_data <= 8'h00;
    111     en <= 1'b1;
    112     num <= 6'd0;
    113 end    
    114 else 
    115     case(state)
    116         IDLE: 
    117         begin
    118             state <= INIT_FUN_SET1;
    119             lcd_data <= 8'hzz;
    120             en <= 1'b1;
    121         end
    122         
    123         INIT_FUN_SET1: 
    124         begin
    125             lcd_data <= 8'h30;    //功能设定
    126             state <= INIT_FUN_SET2;
    127         end 
    128         
    129         INIT_FUN_SET2:
    130         begin
    131             lcd_data <= 8'h30;    //功能设定
    132             state <= INIT_DISPLAY;
    133         end
    134             
    135         INIT_DISPLAY:
    136         begin
    137             lcd_data <= 8'h0c;    //显示设定
    138             state <= INIT_CLEAR;
    139         end
    140             
    141         INIT_CLEAR:
    142         begin
    143             lcd_data <= 8'h01;    //清屏
    144             state <= INIT_DOT_SET;
    145         end
    146         
    147         INIT_DOT_SET:
    148         begin
    149             lcd_data <= 8'h06;    //进入点设定
    150             state <= SET_DDRAM;
    151         end
    152         
    153         SET_DDRAM:
    154         begin
    155             lcd_data <= 8'h90;//2 line            
    156             state <= WRITE_DATA0;
    157         end
    158         
    159         WRITE_DATA0:  ////ff应答::
    160         begin
    161             if(num == 7'd7)
    162                 state <= WRITE_DATA1;
    163             else begin
    164                 num <= num + 1'b1;
    165                 lcd_data <= dis_data;
    166                 state <= WRITE_DATA0;  
    167             end
    168         end
    169         
    170         WRITE_DATA1: //回应的第一个数据高字节
    171         begin
    172             lcd_data <= dis_data_hig1;
    173             state <= WRITE_DATA2;  
    174         end
    175         
    176         WRITE_DATA2://回应的第一个数据低字节
    177         begin
    178             lcd_data <= dis_data_low1;
    179             state <= WRITE_BLANK1;  
    180         end
    181         
    182         WRITE_BLANK1:  //写一个空格
    183         begin
    184             lcd_data <= " ";
    185             state <= WRITE_DATA3;  
    186         end
    187         
    188         WRITE_DATA3: //回应的第二个数据高字节
    189         begin
    190             lcd_data <= dis_data_hig2;
    191             state <= WRITE_DATA4;  
    192         end
    193         
    194         WRITE_DATA4://回应的第二个数据低字节
    195         begin
    196             lcd_data <= dis_data_low2;
    197             state <= WRITE_BLANK2;  
    198         end
    199         
    200         WRITE_BLANK2:  //写一个空格
    201         begin
    202             lcd_data <= " ";
    203             state <= WRITE_DATA5;  
    204         end
    205         
    206         WRITE_DATA5: //回应的第三个数据高字节
    207         begin
    208             lcd_data <= dis_data_hig3;
    209             state <= WRITE_DATA6;  
    210         end
    211         
    212         WRITE_DATA6://回应的第三个数据低字节
    213         begin
    214             lcd_data <= dis_data_low3;
    215             state <= SET_DDRAM1;  
    216         end
    217         
    218         SET_DDRAM1:
    219         begin
    220             lcd_data <= 8'h88;//3 line            
    221             state <= WRITE_DATA7;
    222         end
    223         
    224         WRITE_DATA7:  //f4应答
    225         begin
    226             if(num == 7'd14) begin
    227                 state <= WRITE_DATA8;
    228             end
    229             else begin
    230                 num <= num + 1'b1;
    231                 lcd_data <= dis_data;
    232                 state <= WRITE_DATA7;  
    233             end
    234         end
    235         
    236         ////
    237         WRITE_DATA8: //第二次回应的高字节
    238         begin
    239             lcd_data <= dis_data_hig4;
    240             state <= WRITE_DATA9;  
    241         end
    242         
    243         WRITE_DATA9://第二次回应的低字节
    244         begin
    245             lcd_data <= dis_data_low4;
    246             state <= SET_DDRAM2;  
    247         end
    248         
    249         SET_DDRAM2:
    250         begin
    251             lcd_data <= 8'h98;//4 line            
    252             state <= WRITE_DATA10;
    253         end
    254         
    255         WRITE_DATA10:
    256         begin
    257             if(num == 7'd19) begin
    258                 num <= 7'd0;
    259                 state <= WRITE_DATA11;
    260             end
    261             else begin
    262                 num <= num + 1'b1;
    263                 lcd_data <= dis_data;
    264                 state <= WRITE_DATA10;
    265             end
    266         end
    267         
    268         WRITE_DATA11:
    269         begin
    270             lcd_data <= dis_data_btn;
    271             state <= SET_DDRAM;
    272         end
    273 /*        STOP: 
    274         begin
    275             en <= 1'b0;//显示完了,lcd_e就一直拉为低
    276             state <= STOP;
    277         end   */
    278         
    279         default: state <= IDLE;
    280     endcase
    281 
    282 reg [7:0] dis_data;
    283 always @(posedge sys_clk or negedge rst_n)
    284 if(!rst_n)
    285     dis_data <= 8'hzz;
    286 else
    287     case(num)
    288     //ff应答:
    289     7'd0   :    dis_data <= "f";//8'h66; 
    290     7'd1   :    dis_data <= "f";//8'h66; 
    291     7'd2   :    dis_data <= 8'hd3; 
    292     7'd3   :    dis_data <= 8'ha6; 
    293     7'd4   :    dis_data <= 8'hb4;
    294     7'd5   :    dis_data <= 8'hf0;
    295     7'd6   :    dis_data <= " ";
    296     //f4应答:
    297     7'd7   :    dis_data <= "f";
    298     7'd8   :    dis_data <= "4";
    299     7'd9   :    dis_data <= 8'hd3;
    300     7'd10  :    dis_data <= 8'ha6;
    301     7'd11  :    dis_data <= 8'hb4;
    302     7'd12  :    dis_data <= 8'hf0;
    303     7'd13  :    dis_data <= " ";
    304     //按键:
    305     7'd14  :    dis_data <= 8'hb0; 
    306     7'd15  :    dis_data <= 8'hb4; 
    307     7'd16  :    dis_data <= 8'hbc; 
    308     7'd17  :    dis_data <= 8'hfc;
    309     7'd18  :    dis_data <= " ";
    310     default:    dis_data <= 8'h00;
    311     endcase
    312 /***************************************************/
    313 assign lcd_rw = 1'b0;//只有写模式
    314 assign lcd_psb = 1'b1;//并口模式
    315 assign lcd_en = en ?  lcd_clk : 1'b0;
    316 /***************************************************/
    317 endmodule
    View Code

    ps2_mouse_top.v

      1 module  ps2_mouse_top(
      2                         //input 
      3                         sys_clk,
      4                         rst_n,
      5                         
      6                         //inout
      7                         ps2_clk,
      8                         ps2_data,
      9                         
     10                         //output
     11                         lcd_rs,
     12                         lcd_rw,
     13                         lcd_en,
     14                         lcd_data,
     15 //                        lcd_psb
     16                      );
     17 
     18                      
     19 input  sys_clk;
     20 input  rst_n;        
     21             
     22 inout  ps2_clk;
     23 inout  ps2_data;
     24 
     25 output lcd_rs;//H:data    L:command
     26 output lcd_rw;//H:read module    L:write module
     27 output lcd_en;//H active
     28 output [7:0] lcd_data;
     29 //output lcd_psb;//H:parallel    module    L:SPI module
     30 
     31 wire send_done_sig;
     32 wire rx_done_sig;
     33 wire [7:0] data_buf;
     34 wire rx_en;
     35 wire send_en;
     36 wire [7:0] send_cmd;
     37 wire [7:0] dis_data_low1;
     38 wire [7:0] dis_data_hig1;
     39 wire [7:0] dis_data_low2;
     40 wire [7:0] dis_data_hig2;
     41 wire [7:0] dis_data_low3;
     42 wire [7:0] dis_data_hig3;
     43 wire [7:0] dis_data_low4;
     44 wire [7:0] dis_data_hig4;
     45 wire [7:0] dis_data_btn;
     46 //控制模块例化
     47 ps2_data_control     u1_control(
     48                          //input 
     49                          .sys_clk(sys_clk),
     50                          .rst_n(rst_n), 
     51                          .send_done_sig(send_done_sig),  //发送完标志
     52                          .rx_done_sig(rx_done_sig),    //接收完标志
     53                          .data_buf(data_buf),        //接收到的数据
     54                          
     55                          //output
     56                          .rx_en(rx_en),            //接收使能
     57                          .send_en(send_en),        //发送使能
     58                          .send_cmd(send_cmd),        //要发送的命令
     59                          .dis_data_low1(dis_data_low1),        //要显示的数据
     60                          .dis_data_hig1(dis_data_hig1),
     61                          
     62                          .dis_data_low2(dis_data_low2),        //要显示的数据
     63                          .dis_data_hig2(dis_data_hig2),
     64                          
     65                          .dis_data_low3(dis_data_low3),        //要显示的数据
     66                          .dis_data_hig3(dis_data_hig3),
     67                          
     68                          .dis_data_low4(dis_data_low4),        //要显示的数据
     69                          .dis_data_hig4(dis_data_hig4),
     70                          
     71                          .dis_data_btn(dis_data_btn)
     72                          );
     73 //显示模块例化
     74 LCD12864    u2_lcd(
     75                     //input 
     76                     .sys_clk(sys_clk),
     77                     .rst_n(rst_n),
     78                     .dis_data_low1(dis_data_low1),        //要显示的数据
     79                     .dis_data_hig1(dis_data_hig1),
     80                     
     81                     .dis_data_low2(dis_data_low2),        //要显示的数据
     82                     .dis_data_hig2(dis_data_hig2),
     83                     
     84                     .dis_data_low3(dis_data_low3),        //要显示的数据
     85                     .dis_data_hig3(dis_data_hig3),
     86                     
     87                     .dis_data_low4(dis_data_low4),        //要显示的数据
     88                     .dis_data_hig4(dis_data_hig4),
     89                          
     90                     .dis_data_btn(dis_data_btn),
     91                     
     92                     //output 
     93                     .lcd_rs(lcd_rs),
     94                     .lcd_rw(lcd_rw),
     95                     .lcd_en(lcd_en),
     96                     .lcd_data(lcd_data),
     97 //                    .lcd_psb(lcd_psb)
     98                 );
     99 //发送模块例化                         
    100 ps2_send_control     u3_send(
    101                         //input 
    102                         .sys_clk(sys_clk),
    103                         .rst_n(rst_n),
    104                         .send_en(send_en),    //发送使能
    105                         .send_cmd(send_cmd),  //要发送的命令 0xf4
    106                         
    107                         //output
    108                         .send_done_sig(send_done_sig),//发送完标志
    109                         
    110                         //inout
    111                         .ps2_clk(ps2_clk),  //鼠标时钟
    112                         .ps2_data(ps2_data) //鼠标数据
    113                        );
    114 //接收模块例化                       
    115 ps2_rx_control    u4_rx(
    116                             //input 
    117                             .sys_clk(sys_clk),
    118                             .rst_n(rst_n),
    119                             .ps2_clk_in(ps2_clk),  //鼠标时钟
    120                             .ps2_data_in(ps2_data), //鼠标数据
    121                             .rx_en(rx_en),       //接收模块使能信号
    122                             
    123                             //output
    124                             .rx_done_sig(rx_done_sig), //接收完标志信号
    125                             .data_buf(data_buf)     //保存接收到的数据
    126                         );
    127 endmodule
    View Code

    现象1、发送0xff命令给鼠标时,PS/2 技术参考上有写,发送此命令进入复位模式,鼠标并会给主机三个数据0xfa、0xaa、0x00(ID)作为回应,如下图,显示是正确的,那说明传送和接收应该没错,但在发送0xf4命令,按道理接收到回应数据应该是0xfa,而这里没有收到数据:

    现象2、若直接先发送0xf4命令时,接收到回应的数据是0xfe,按复位又变为0xfc,在按一次又变为0xfe,反复按复位,一直在这两数据变动,查PS/2 技术参考资料,说是校验位出错或是干扰造成,换了两个板子都是这样,换了鼠标也是这样。如下图:

    以上两个现象让我彻底的无语了,估计我现在的思维已定死了,无法想到其他方法去调试,想写个仿真嘛,又觉得比较棘手,毕竟要模拟一个鼠标还是有费点功夫,哎。。


    按键  后面本来是要显示 左(L)右(R)中(M)几个字母,若没有接收到数据,显示默认值X。

  • 相关阅读:
    别了,DjVu!
    DjVu转PDF
    我的电子书历程
    连续翻页浏览器面临的共同问题
    对超过2TB的硬盘进行分区需要使用parted
    DB2常用命令
    CentOS增加网卡
    mysql相关参数解读
    max_user_connections参数设置试验
    mysql最大连接数试验
  • 原文地址:https://www.cnblogs.com/wen2376/p/3383331.html
Copyright © 2020-2023  润新知