⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyboard_test1.v

📁 ps2_键盘控制器源码verilog源码
💻 V
字号:
////////////////////////////////////////////////////////////////////////////////
//公司: <Company Name>
//工程师: Lawson_jian
//
//创建日期: 2004年12月10日
//设计名字: 
//模块名字: 键盘驱动器 KeyBoard Divider
//目标装置: 
//工具版本: <tool_versions>
//描述:
//    
//属性:
//    <Dependencies here>
//修改:
//    <Code_revision_information>
//附加说明:
//    <Additional_comments>
////////////////////////////////////////////////////////////////////////////////

`timescale 1 ns / 1 ns

module  keyboard_test1 (
      PS2K_DATA,
      PS2K_CLK,
      R_DATA,
      W_DATA,
      BUSY,
      Complete,
      Error,
      RW,
      ENA,
      CLK,
      CLR
      );

//+---------------------------KeyBoard 状态设置---------------------------+

   parameter Data_Width = 8;     //输入/输出数据宽度
   parameter Count    = 5;     //状态码宽度

//+-----------------------------------------------------------------------+

 inout PS2K_DATA;
 inout PS2K_CLK;
 input [Data_Width-1:0] W_DATA;
 input RW;
 input ENA;
 input CLR;       // synthesis attribute clock_buffer of CLR is ibufg;
 input CLK;
 output [Data_Width-1:0] R_DATA;
 output BUSY;
 output Complete;
 output [1:0] Error;

//+---------------------------频率发生器状态代码-------------------------+

 parameter Add_CounteState = 0;
 parameter Dec_CounteState = 1;

//+---------------------------KeyBoard 读状态代码-------------------------+

 parameter Read_start     = 4'h0;
 parameter Read_start_complete  = 4'h1;
 parameter Read_data      = 4'h2;
 parameter Read_data_complete   = 4'h3;
 parameter Read_parity     = 4'h4;
 parameter Read_parity_complete  = 4'h5;
 parameter Read_stop      = 4'h6;
 parameter Read_finish     = 4'h7;

//+---------------------------KeyBoard 写状态代码--------------------------+

 parameter Write_start     = 4'h0;
 parameter Restrain_read    = 4'h1;
 parameter Write_data     = 4'h2;
 parameter Write_data_complete  = 4'h3;
 parameter Write_parity     = 4'h4;
 parameter Write_parity_complete  = 4'h5;
 parameter Write_stop     = 4'h6;
 parameter Write_stop_complete  = 4'h7;
 parameter Write_ACK      = 4'h8;
 parameter Write_finish     = 4'h9;

//+-----------------------------KeyBoard 错误代码--------------------------+

 parameter No_R_stop_signal   = 4'h1;
 parameter Checkout_error    = 4'h2;
 parameter No_ACK_signal    = 4'h3; 

//+------------------------------------------------------------------------+

 reg [3:0] W_State;
 reg [3:0] R_State;
 reg [Data_Width-1:0] R_DATA;
 reg [Data_Width-1:0] W_Reg;
 reg CLK_W;
 reg DATA_W;
 reg K_DATA;
 reg BUSY;
 reg Complete;
 reg P_Reg;
 reg [7:0] Counter;
 reg [1:0] Error;
 reg [Data_Width-1:0] Counter_reg;        //计数器寄存器
 reg CounteState;              //计数器状态寄存器
 reg Pulse_Out_reg;             //脉冲发生寄存器

 wire [Data_Width-1:0] Half_Frequency_Data;
 wire [Data_Width-1:0] Frequency_Data;
 wire us_CLK;
 wire P;

//----------------------------------------------------------------------------//
//                          //
//               接口逻辑函数           //
//                          //
//----------------------------------------------------------------------------//

 assign Frequency_Data = 8'd100;          //频率数据
 assign us_CLK = Pulse_Out_reg;
 assign Half_Frequency_Data = Frequency_Data/2;

 assign PS2K_DATA = DATA_W ? 1'bz : K_DATA;
 assign PS2K_CLK = CLK_W ? 1'bz : 0;
 assign P = RW ? ^~R_DATA : ^~W_Reg;

//----------------------------------------------------------------------------//
//                          //
//            1ms脉冲发生器          //
//                          //
//----------------------------------------------------------------------------//

 always @(posedge CLK or negedge CLR)
 begin
  if (!CLR)                //复位
  begin
   Counter_reg = 1;
   CounteState = Add_CounteState;
   Pulse_Out_reg = 0;
  end
  else begin

   Counter_reg = Counter_reg + 1;

   case (CounteState)

   Add_CounteState :             //增量计数状态
   begin    
    if(Counter_reg == Half_Frequency_Data)     //Half_Frequency_Data = Frequency_Reg/2 产生半个时钟脉冲 
    begin
     CounteState = Dec_CounteState;
     Pulse_Out_reg = 1;
    end
   end
   
   Dec_CounteState :             //减量计数状态
   begin
    if(Counter_reg == Frequency_Data)      //产生完整时钟脉冲
    begin
     Counter_reg = 1;
     CounteState = Add_CounteState;
     Pulse_Out_reg = 0;
    end
   end
   endcase
  end
 end

//----------------------------------------------------------------------------//
//                          //
//          KeyBoard Read or Wrie         //
//                          //
//----------------------------------------------------------------------------//

   always @( posedge us_CLK or negedge CLR)
      if (!CLR) begin
   R_DATA = 0;
   W_Reg = 0;
   CLK_W = 1;
   DATA_W = 1;
   K_DATA = 0;
   BUSY = 0;
   Complete = 0;
   Counter = 0;
   P_Reg = 0;
   Error = 0;
   Counter = 0;
   W_State = Write_start;
   R_State = Read_start;
      end
      else if (ENA) begin
   if(RW) begin
      case (R_State)
         Read_start: begin
           CLK_W = 1;
         DATA_W = 1;
         Error = 0;
         Complete = 0;
                    if( PS2K_CLK == 0 && PS2K_DATA == 0) begin         
         BUSY = 1;
         R_State = Read_start_complete;
        end
        else begin 
         R_State = Read_start;
        end
                 end

         Read_start_complete: begin
                    if( PS2K_CLK == 1) begin
         Counter = 8'd0;
         R_State = Read_data;
        end
        else R_State = Read_start_complete;
                 end

         Read_data: begin
                    if( PS2K_CLK == 0 ) begin
         R_DATA[Counter] = PS2K_DATA;
         Counter = Counter + 1;
         R_State = Read_data_complete;
         $display("read R_DATA[%d] BIT is %b",Counter,PS2K_DATA);
        end
        else R_State = Read_data;
                 end

         Read_data_complete: begin
                    if( PS2K_CLK == 1 ) begin
         if( Counter == 8'd8) begin
          R_State = Read_parity;
         end
         else begin
          R_State = Read_data;
         end
        end
        else R_State = Read_data_complete;
                 end

         Read_parity: begin
                    if( PS2K_CLK == 0 ) begin
         P_Reg = PS2K_DATA;
         R_State = Read_parity_complete;
         $display("read PS2K parity bit "); 
        end
        else R_State = Read_parity;
                  end

      Read_parity_complete: begin
                    if( PS2K_CLK == 1 ) begin
         R_State = Read_stop;
        end
        else R_State = Read_parity_complete;
                  end

      Read_stop: begin
                    if( PS2K_CLK == 0) begin
         if(PS2K_DATA == 1) begin
          $display("PS2K_DATA STOP ");
          R_State = Read_finish; 
         end
         else begin
          Error = No_R_stop_signal;
          R_State = Read_finish;
         end
        end
        else R_State = Read_stop;
                 end

     Read_finish: begin
                    if( PS2K_CLK == 1) begin
         BUSY = 0;
         Complete = 1;
         $display("PS2K parity bit is %b",P_Reg);
         if( P == P_Reg ) begin
          $display("PS2K parity bit is right");
          $display("Complete read R_DATA is %b",R_DATA);          
          R_State = Read_start;
         end
         else begin
          $display("PS2K parity bit is error");          
          Error = Checkout_error;
          R_State = Read_start;
         end
        end
        else R_State = Read_finish;
                  end

         default: begin
                     R_State = Read_start;
                  end
     endcase
     end
     else begin
      case (W_State)
       Write_start: begin
                     CLK_W = 0;
         DATA_W = 0;
         W_Reg = W_DATA;
         K_DATA = 1;
         Counter = 0;
         BUSY = 1;
         Complete = 0;
         Error = 0;
         W_State = Restrain_read;
        end

         Restrain_read: begin
                    if(Counter == 8'd100) begin       //抑制键盘通讯400μS
         K_DATA = 0;
         Counter = 0;
         CLK_W = 1;
         $display("Complete Restrain Read ");
         W_State = Write_data;
        end
        else begin
         Counter = Counter + 1;
         W_State = Restrain_read;
        end
                  end

         Write_data: begin
                    if( PS2K_CLK == 0 ) begin
         K_DATA = W_Reg [Counter];
         Counter = Counter + 1;
         $display("write W_DATA[%d] BIT is %b",Counter,W_DATA[Counter]);
         W_State = Write_data_complete;
        end
        else W_State = Write_data;
                  end

         Write_data_complete: begin
                    if( PS2K_CLK == 1 ) begin
         if( Counter == 8'd8) W_State = Write_parity;
         else W_State = Write_data; 
        end
        else W_State = Write_data_complete;
                  end

         Write_parity: begin
                    if( PS2K_CLK == 0 ) begin
         K_DATA = P;
         $display("write Parity Bit is %b",P);
         W_State = Write_parity_complete;
        end
        else W_State = Write_parity;
                  end

     Write_parity_complete: begin
                    if( PS2K_CLK == 1 ) begin
         W_State = Write_stop;
        end
        else W_State = Write_parity_complete;
                  end

      Write_stop: begin
                    if( PS2K_CLK == 0 ) begin
         $display("Write stop ");
         K_DATA = 1;
         W_State = Write_stop_complete;
        end
        else W_State = Write_stop;
                  end


      Write_stop_complete: begin
                    if( PS2K_CLK == 1 ) begin
         DATA_W = 1;
         W_State = Write_ACK;
        end
        else W_State = Write_stop_complete;
                  end

     Write_ACK: begin
                    if( PS2K_CLK == 0) begin
         if( PS2K_DATA == 0) begin
          $display("PS2K_DATA ACK ");
          W_State = Write_finish;
         end
         else begin
          $display("PS2K_DATA NO ACK ");
          Error = No_ACK_signal;
          W_State = Write_finish;
         end
        end
        else begin
         W_State = Write_ACK;
        end
                 end

      Write_finish: begin
                    if( PS2K_DATA == 1 && PS2K_CLK == 1 ) begin
         $display("Complete write PS2K DATA");
         BUSY = 0;
         Complete = 1;
         W_State = Write_start;
        end
        else begin
         W_State = Write_finish;
        end
                  end

         default: begin
                     W_State = Write_start;
                  end
      endcase
   end
      end
endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -