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。

原文地址:https://www.cnblogs.com/wen2376/p/3383331.html