返回该小组首页 回复主题
zhengshitao

zhengshitao

小组等级:     E币:91  (E币换礼)

#1楼主:求助 ps2 键盘 在LCD 上的显示 [fpga]

文章发表于:2008-07-11 12:02

小弟最近在搞ps2 这一块, 发现仿真通过了,但是还是不能通过实测。

很郁闷。。想请大家帮忙,是不是我哪一个部位出现了错误。

主要的目的是:键盘上敲下a、b 时 LCD上显示  而 其他则显示 !

 

代码如下所示:


module MYPS2(clk,ps_clk,ps_data,data);
  input  clk, ps_clk, ps_data;  //定义的输入接口
  output [7:0]         data;           //ps2的数据输出口
  reg      [7:0]         data;   
  reg      [4:0]         cnt   = 0;       
  reg                      check = 1;    //定义的奇校验 
  reg       [10:0]       fifo  = 0 ;    //data 的缓存      

  reg                        stop = 0;    // 停止进行读取 并传输数据的标志)(1)
  reg    [9:0] count_cnt = 0;

  always @ ( negedge ps_clk )      //主要的循环   在ps2时钟 低电平时读取
   begin 
    if ( count_cnt == 0)
                begin    
                     fifo[cnt] <= ps_data;
                    check     <=  check ^ ps_data; 
                end   
    if( cnt == 10 )                        //十一位数据的读取
      begin
       cnt  <= 0;
       stop <= 1;
      end
    else
      cnt <= cnt+1;
    if( stop == 1 )         //读取完毕 进行 缓存胧涑龅?交换
      begin
       if( (!check) && (fifo[10] == 1) &&(fifo[0] == 0))
          begin
             data  <= fifo[ 8:1 ];
             stop   <=  0;
             check <= 0;
         end
       else 
          begin
             stop    <= 0; 
             check <= 0;
         end
          count_cnt <= 10'b1111111111;    \\每次信号读取的延时
      end 

  if(count_cnt != 0)    
      count_cnt <= count_cnt - 1;          
   end

endmodule

 

下面是主top文件 (我不做重要解释了)

module total_top(clk, ps_clk, ps_data, LCD_DB, LCD_RS, LCD_RW, LCD_E);
    input  clk,ps_clk,ps_data;      
   output [7:0] LCD_DB;
   output LCD_RS;
   output LCD_RW;
   output LCD_E;
   wire [7:0]data;
   wire [7:0] LCD_DB;
   wire LCD_RS;
   wire LCD_RW;
   wire LCD_E;
 
 MYPS2 ps2( .clk(clk),
      .ps_clk(ps_clk),
      .ps_data(ps_data),
      .data(data)
    );
 LCD_TOP LCD(.clk(clk),
     .data_ps(data),
     .LCD_DB(LCD_DB),
     .LCD_RS(LCD_RS),
     .LCD_RW(LCD_RW),
     .LCD_E(LCD_E)
      );
endmodule  

 

 

下面是LCD 的显示模块

module LCD_TOP(clk, data_ps, LCD_DB, LCD_RS, LCD_RW, LCD_E);
    input clk;
  input [7:0]data_ps;
  output [7:0] LCD_DB;
    output LCD_RS;
    output LCD_RW;
    output LCD_E;

    wire [7:0] LCD_DB;
    wire LCD_RS;
    wire LCD_RW;
    wire LCD_E;

 parameter S0  = 9'b000000001;
   parameter S1  = 9'b000000010;
   parameter S2  = 9'b000000100;
   parameter S3  = 9'b000001000;
   parameter S4  = 9'b000010000;
   parameter S5  = 9'b000100000;
   parameter S6  = 9'b001000000;
   parameter S7  = 9'b010000000;
   parameter S8  = 9'b100000000;
 //inner reg
 reg [15:0] count_16 = 16'h0000;
 reg [7:0]  count_ms = 8'h00;
 reg count_en = 1'b0;
 
  // ms timer
 always @( posedge clk or negedge count_en )
 begin
  if( count_en == 1'b0 )
   begin
   count_16 <= 16'h0000;
   count_ms <= 8'h00;
   end
  else
   if( count_16 == 16'hC350 )
    begin
    count_16 <= 16'h0000;
    count_ms <= count_ms + 1;
    end
   else
   count_16 <= count_16 + 1;
 end
 

 reg [15:0] curr_state = S0;
 reg [15:0] next_state;
 reg [7:0] data       = 0;
   reg       rs         = 0;
   reg       issue      = 0; 
 reg [7:0] cntdata;
 always @(posedge clk)
 begin
 case(data_ps)
   16'h1c: cntdata <= 8'h41;
   16'h32: cntdata <= 8'h42;
   default : cntdata <= 8'h21;
  endcase
 end
 // Main FSM
  (* FSM_ENCODING="ONE-HOT", SAFE_IMPLEMENTATION="NO" *)
 always @( posedge clk )
 begin
  curr_state <= next_state;
 end

 // Main FSM control
 always @( curr_state or count_ms )
 begin
  case( curr_state )
     // Power On
   S0: if( count_ms == 8'd40 ) next_state = S1; 
     else                    next_state = S0;
   // Function Set
   S1: if( count_ms == 8'd1  ) next_state = S2; 
     else                    next_state = S1;
   // Function Set again
   S2: if( count_ms == 8'd1  ) next_state = S3; 
     else                    next_state = S2;
   // Display On/Off control
   S3: if( count_ms == 8'd1  ) next_state = S4; 
     else                    next_state = S3;
   // Display clear
   S4: if( count_ms == 8'd2  ) next_state = S5; 
     else                    next_state = S4;
   // Entry mode set
   S5: if( count_ms == 8'd2  ) next_state = S6; 
     else                    next_state = S5;
   // Set DDRAM Address
   S6: if( count_ms == 8'd2  ) next_state = S7;
     else                    next_state = S6;
   S7: if( count_ms == 8'd2  ) next_state = S8;
     else        next_state = S7;
   default:        next_state = S8;
  endcase
 end
 
 // Main FSM output
 always @( posedge clk)
 begin
 case ( next_state )
    S0 :                                               // Wait PowerOn 40ms 
   begin count_en <= 1'b1;  data <= 8'h00;  rs <= 1'b0;  issue <= 1'b0; end
    S1 :
   if ( curr_state == S0 )                    // Prepare "Function Set" issue
    begin count_en <= 1'b0; data <= 8'h38;  rs <= 1'b0;  issue <= 1'b0; end
   else                                               // wait 1ms
    begin count_en <= 1'b1; data <= 8'h38;  rs <= 1'b0;  issue <= 1'b1; end
    S2 :
   if ( curr_state == S1 )                     // Prepare "Function Set" issue
    begin count_en <= 1'b0; data <= 8'h38;  rs <= 1'b0;  issue <= 1'b0; end
   else        // wait 1ms
    begin count_en <= 1'b1; data <= 8'h38;  rs <= 1'b0;  issue <= 1'b1; end
  S3 :
   if ( curr_state == S2 )                   // Prepare "Display On/Off control" issue
    begin count_en <= 1'b0; data <= 8'h0C;  rs <= 1'b0;  issue <= 1'b0; end
   else        // wait 1ms
    begin count_en <= 1'b1; data <= 8'h0C;  rs <= 1'b0;  issue <= 1'b1; end
  S4 :
   if ( curr_state == S3 )                   // Prepare "Display clear" issue
    begin count_en <= 1'b0; data <= 8'h01;  rs <= 1'b0;  issue <= 1'b0; end
   else                                                // wait 2ms
    begin count_en <= 1'b1; data <= 8'h01;  rs <= 1'b0;  issue <= 1'b1; end
  S5 :
   if ( curr_state == S4 )                   // Prepare "Entry mode set" issue
    begin count_en <= 1'b0; data <= 8'h03;  rs <= 1'b0;  issue <= 1'b0; end
   else                                                // wait 2ms
    begin count_en <= 1'b1; data <= 8'h03;  rs <= 1'b0;  issue <= 1'b1; end
  S6 :
   if ( curr_state == S5 )                     // Prepare "Set DDRAM address" issue
    begin count_en <= 1'b0; data <= 8'h84;  rs <= 1'b0;  issue <= 1'b0; end
   else                                                // wait 2ms
    begin count_en <= 1'b1; data <= 8'h84;  rs <= 1'b0;  issue <= 1'b1; end

  S7 :
   if ( curr_state == S6 )                      // Prepare "data_ps" issue
    begin count_en <= 1'b0; data <= cntdata ;  rs <= 1'b1;  issue <= 1'b0; end
   else                                                 // wait 2ms
    begin count_en <= 1'b1; data <= cntdata ;  rs <= 1'b1;  issue <= 1'b1; end

  S8 :
   begin count_en <= 1'b0;  data <= 8'h00;  rs <= 1'b0;  issue <= 1'b0; end
  
 endcase
 end
 
                      // WrLCD unit
 WrLCD U_WrLCD( .clk( clk), .data(data), .rs(rs), .ce(issue),
                  .LCD_DB(LCD_DB), .LCD_E(LCD_E), .LCD_RS(LCD_RS), .LCD_RW(LCD_RW)) ;

endmodule

 

 

 

 

 

 

下面则为LCD的底层驱动模块

module WrLCD( clk, data, rs, ce,
              LCD_DB, LCD_E, LCD_RS, LCD_RW );
    // input
    input clk;
  input [7:0] data;
    input rs;
    input ce;
  // output
  output [7:0] LCD_DB;
  output LCD_E;
  output LCD_RS;
  output LCD_RW;
  // output reg
    reg [7:0] LCD_DB = 8'h00;
  reg  LCD_E       = 0;
  reg  LCD_RS      = 0;
  wire LCD_RW;

    parameter S1  = 5'b00001;
    parameter S2  = 5'b00010;
    parameter S3  = 5'b00100;
    parameter S4  = 5'b01000;
    parameter S5  = 5'b10000;

  // inner sign
  reg [3:0] counter;
  reg counter_run;
 
// (* INIT  = "5'b00001" *)
  reg [4:0] curr_state = 5'b00001;
  reg [4:0] next_state;
 
  // LCD_RW
  assign LCD_RW = 1'b0;
  // LCD_DB, LCD_RS
  always @( posedge clk )
  begin
  if( ce == 1'b0 )
   begin
    LCD_DB <= 8'b0;
    LCD_RS <= 1'b0;
   end
  else
   begin
    LCD_DB <= data;
    LCD_RS <= rs;
   end
  end
 
 
 // Main FSM
  (* FSM_ENCODING="ONE-HOT", SAFE_IMPLEMENTATION="NO" *)
 always @( posedge clk )
 begin
  if( ce == 1'b0 )
   curr_state <= S1;
  else
   curr_state <= next_state;
 end
 
 // Main FSM control
 always @( curr_state or counter or ce )
 begin
  case( curr_state )
   S1: if( ce == 1'b1 )   next_state = S2;
     else                   next_state = S1;
   S2: if( counter == 4'h3 )  next_state = S3;
     else                   next_state = S2;
   S3:        next_state = S4;
   S4: if( counter == 4'hB ) next_state = S5;
       else                   next_state = S4;
   S5: if( ce == 1'b1 )   next_state = S5;
     else                   next_state = S1;
   default:       next_state = S1;
  endcase
 end
 
 // Main FSM out
 always @( posedge clk or negedge ce )
 begin
    if( ce == 1'b0 )
   begin
   counter_run <= 1'b0;
   LCD_E       <= 1'b0;
   end
  else if( next_state == S2 )  // 建立时间
   begin
   counter_run <= 1'b1;
   LCD_E       <= 1'b0;
   end
  else if( next_state == S3 )  // CE Hight
   begin
   counter_run <= 1'b0;
   LCD_E       <= 1'b1;
   end
  else if( next_state == S4 ) // 保持时间
   begin
   counter_run <= 1'b1;
   LCD_E       <= 1'b1;
   end
  else if( next_state == S5 ) // CE Low
   begin
   counter_run <= 1'b0;
   LCD_E       <= 1'b0;
   end
  else
   begin
   counter_run <= 1'b0;
   LCD_E       <= 1'b0;
   end
  
 end
 
 // Timer counter
 always @( posedge clk )
 begin
  if( counter_run == 1'b1 )
   counter <= counter + 1;
  else
   counter <= 4'h0;
 end

endmodule

下面是我的波形图:第一张为data图 可以看到此时的data为 b 时候的键盘码

第二张为LCD的显示

黄线标记的位置为结果输出的位置 是16进制的42 为LCD上“B”的

显示。

自我感觉通过了仿真调试

 

 

 

 

经过调试后,板子上只是显示
“!” 键盘敲a、b都没  反应  ····

 

求助啊啊啊啊啊啊  各位大侠

q4949

   小组等级:    E币:63  (E币换礼)

#2

文章发表于:2008-10-08 09:47

 很简单啊

q4949

   小组等级:    E币:63  (E币换礼)

#3

文章发表于:2008-10-08 09:50

lcd显示的ASCII 码,与PS传过来的是有不同的,不能直接显示,要有一个译码过程

craftor

   小组等级:    E币:1155  (E币换礼)

#4

文章发表于:2008-11-07 22:41

偶是用VHDL的,Verilog不熟~

总共 , 当前 /

快速回复主题--如果想加入编辑器功能,建议使用 [高级回复]

您目前还不是小组成员,请先加入

回复贴子区

用户名:    您没有注册?

密码:    忘记了密码?

内容:

  • DesignDesign
  • HTMLHTML

浏览该小组的用户还看过...

所有小组精华文章