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

📄 ps2_keyboard.v

📁 ps2接口源程序。标准的键盘和鼠标接口
💻 V
📖 第 1 页 / 共 2 页
字号:
  ps2_data_hi_z <= #1 1;
  tx_error_no_keyboard_ack <= #1 1'b0;
  enable_timer_60usec <= #1 0;
  enable_timer_5usec <= #1 0;

  case (m1_state)

    m1_rx_clk_h :
      begin
        enable_timer_60usec <= #1 1;
        if (tx_write) m1_next_state <= #1 m1_tx_reset_timer;
        else if (~ps2_clk_s) m1_next_state <= #1 m1_rx_falling_edge_marker;
        else m1_next_state <= #1 m1_rx_clk_h;
      end

    m1_rx_falling_edge_marker :
      begin
        enable_timer_60usec <= #1 0;
        m1_next_state <= #1 m1_rx_clk_l;
      end

    m1_rx_rising_edge_marker :
      begin
        enable_timer_60usec <= #1 0;
        m1_next_state <= #1 m1_rx_clk_h;
      end


    m1_rx_clk_l :
      begin
        enable_timer_60usec <= #1 1;
        if (tx_write) m1_next_state <= #1 m1_tx_reset_timer;
        else if (ps2_clk_s) m1_next_state <= #1 m1_rx_rising_edge_marker;
        else m1_next_state <= #1 m1_rx_clk_l;
      end

    m1_tx_reset_timer:
      begin
        enable_timer_60usec <= #1 0;
        m1_next_state <= #1 m1_tx_force_clk_l;
      end

    m1_tx_force_clk_l :
      begin
        enable_timer_60usec <= #1 1;
        ps2_clk_hi_z <= #1 0;  // Force the ps2_clk line low.
        if (timer_60usec_done) m1_next_state <= #1 m1_tx_first_wait_clk_h;
        else m1_next_state <= #1 m1_tx_force_clk_l;
      end

    m1_tx_first_wait_clk_h :
      begin
        enable_timer_5usec <= #1 1;
        ps2_data_hi_z <= #1 0;        // Start bit.
        if (~ps2_clk_s && timer_5usec_done)
          m1_next_state <= #1 m1_tx_clk_l;
        else
          m1_next_state <= #1 m1_tx_first_wait_clk_h;
      end

    // This state must be included because the device might possibly
    // delay for up to 10 milliseconds before beginning its clock pulses.
    // During that waiting time, we cannot drive the data (q[0]) because it
    // is possibly 1, which would cause the keyboard to abort its receive
    // and the expected clocks would then never be generated.
    m1_tx_first_wait_clk_l :
      begin
        ps2_data_hi_z <= #1 0;
        if (~ps2_clk_s) m1_next_state <= #1 m1_tx_clk_l;
        else m1_next_state <= #1 m1_tx_first_wait_clk_l;
      end

    m1_tx_wait_clk_h :
      begin
        enable_timer_5usec <= #1 1;
        ps2_data_hi_z <= #1 q[0];
        if (ps2_clk_s && timer_5usec_done)
          m1_next_state <= #1 m1_tx_rising_edge_marker;
        else
          m1_next_state <= #1 m1_tx_wait_clk_h;
      end

    m1_tx_rising_edge_marker :
      begin
        ps2_data_hi_z <= #1 q[0];
        m1_next_state <= #1 m1_tx_clk_h;
      end

    m1_tx_clk_h :
      begin
        ps2_data_hi_z <= #1 q[0];
        if (tx_shifting_done) m1_next_state <= #1 m1_tx_wait_keyboard_ack;
        else if (~ps2_clk_s) m1_next_state <= #1 m1_tx_clk_l;
        else m1_next_state <= #1 m1_tx_clk_h;
      end

    m1_tx_clk_l :
      begin
        ps2_data_hi_z <= #1 q[0];
        if (ps2_clk_s) m1_next_state <= #1 m1_tx_wait_clk_h;
        else m1_next_state <= #1 m1_tx_clk_l;
      end

    m1_tx_wait_keyboard_ack :
      begin
        if (~ps2_clk_s && ps2_data_s)
          m1_next_state <= #1 m1_tx_error_no_keyboard_ack;
        else if (~ps2_clk_s && ~ps2_data_s)
          m1_next_state <= #1 m1_tx_done_recovery;
        else m1_next_state <= #1 m1_tx_wait_keyboard_ack;
      end

    m1_tx_done_recovery :
      begin
        if (ps2_clk_s && ps2_data_s) m1_next_state <= #1 m1_rx_clk_h;
        else m1_next_state <= #1 m1_tx_done_recovery;
      end

    m1_tx_error_no_keyboard_ack :
      begin
        tx_error_no_keyboard_ack <= #1 1;
        if (ps2_clk_s && ps2_data_s) m1_next_state <= #1 m1_rx_clk_h;
        else m1_next_state <= #1 m1_tx_error_no_keyboard_ack;
      end

    default : m1_next_state <= #1 m1_rx_clk_h;
  endcase
end

// State register
always @(posedge clk or posedge reset)
begin : m2_state_register
  if (reset) m2_state <= #1 m2_rx_data_ready_ack;
  else m2_state <= #1 m2_next_state;
end

// State transition logic
always @(m2_state or rx_output_strobe or rx_read)
begin : m2_state_logic
  case (m2_state)
    m2_rx_data_ready_ack:
          begin
            rx_data_ready <= #1 1'b0;
            if (rx_output_strobe) m2_next_state <= #1 m2_rx_data_ready;
            else m2_next_state <= #1 m2_rx_data_ready_ack;
          end
    m2_rx_data_ready:
          begin
            rx_data_ready <= #1 1'b1;
            if (rx_read) m2_next_state <= #1 m2_rx_data_ready_ack;
            else m2_next_state <= #1 m2_rx_data_ready;
          end
    default : m2_next_state <= #1 m2_rx_data_ready_ack;
  endcase
end

// This is the bit counter
always @(posedge clk or posedge reset)
begin
  if ( reset) bit_count <= #1 0;
  else if ( rx_shifting_done || (m1_state == m1_tx_wait_keyboard_ack)        // After tx is done.
      ) bit_count <= #1 0;  // normal reset
  else if (timer_60usec_done
           && (m1_state == m1_rx_clk_h)
           && (ps2_clk_s)
      ) bit_count <= #1 0;  // rx watchdog timer reset
  else if ( (m1_state == m1_rx_falling_edge_marker)   // increment for rx
           ||(m1_state == m1_tx_rising_edge_marker)   // increment for tx
           )
    bit_count <= #1 bit_count + 1;
end
// This signal is high for one clock at the end of the timer count.
assign rx_shifting_done = (bit_count == `TOTAL_BITS);
assign tx_shifting_done = (bit_count == `TOTAL_BITS-1);

// This is the signal which enables loading of the shift register.
// It also indicates "ack" to the device writing to the transmitter.
assign tx_write_ack_o = (  (tx_write && (m1_state == m1_rx_clk_h))
                         ||(tx_write && (m1_state == m1_rx_clk_l))
                         );

// This is the ODD parity bit for the transmitted word.
assign tx_parity_bit = ~^tx_data;

// This is the shift register
always @(posedge clk or posedge reset)
begin
  if (reset) q <= #1 0;
  else if (tx_write_ack_o) q <= #1 {1'b1,tx_parity_bit,tx_data,1'b0};
  else if ( (m1_state == m1_rx_falling_edge_marker)
           ||(m1_state == m1_tx_rising_edge_marker) )
    q <= #1 {ps2_data_s,q[`TOTAL_BITS-1:1]};
end

// This is the 60usec timer counter
always @(posedge clk)
begin
  if (~enable_timer_60usec) timer_60usec_count <= #1 0;
  else if ( timer_done && !timer_60usec_done)
         timer_60usec_count<= #1 timer_60usec_count +1;
  end
assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP ));



always @(posedge clk or posedge reset)
if (reset) timer_5usec <= #1 1;
else if (!enable_timer_60usec) timer_5usec <= #1 1;
else if (timer_5usec == devide_reg_i) 
 begin
   timer_5usec <= #1 1;
   timer_done  <= #1 1;
  end
else 
  begin
    timer_5usec<= #1 timer_5usec +1;
    timer_done  <= #1 0;
 end

// This is the 5usec timer counter
always @(posedge clk)
begin
  if (~enable_timer_5usec) timer_5usec_count <= #1 0;
  else if (~timer_5usec_done) timer_5usec_count <= #1 timer_5usec_count + 1;
end
assign timer_5usec_done = (timer_5usec_count == devide_reg_i -1);


// Create the signals which indicate special scan codes received.
// These are the "unlatched versions."
assign released = (q[8:1] == `RELEASE_CODE) && rx_shifting_done && translate ;

// Store the special scan code status bits
// Not the final output, but an intermediate storage place,
// until the entire set of output data can be assembled.
always @(posedge clk or posedge reset)
begin
  if (reset) hold_released <= #1 0;
  else if (rx_output_event)
  begin
    hold_released <= #1 0;
  end
  else
  begin
    if (rx_shifting_done && released) hold_released <= #1 1;
  end
end

// Output the special scan code flags, the scan code and the ascii
always @(posedge clk or posedge reset)
begin
  if (reset)
  begin
    rx_released <= #1 0;
    rx_scan_code <= #1 0;
  end
  else if (rx_output_strobe)
  begin
    rx_released <= #1 hold_released;
    rx_scan_code <= #1 q[8:1];
  end
end

// Store the final rx output data only when all extend and release codes
// are received and the next (actual key) scan code is also ready.
// (the presence of rx_extended or rx_released refers to the
// the current latest scan code received, not the previously latched flags.)
assign rx_output_event  = (rx_shifting_done
                          && ~released
                          );

assign rx_output_strobe = (rx_shifting_done
                          && ~released
                          );

endmodule

//`undefine TOTAL_BITS
//`undefine EXTEND_CODE
//`undefine RELEASE_CODE
//`undefine LEFT_SHIFT
//`undefine RIGHT_SHIFT

⌨️ 快捷键说明

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