/***************************************************************************** * * * Module: Altera_UP_PS2 * * Description: * * This module communicates with the PS2 core. * * * * www.eecg.toronto.edu/~jayar/ece241_08F/AudioVideoCores/ps2/ps2.html * *****************************************************************************/ module ps2controller #(parameter INITIALIZE_MOUSE = 0) ( // Inputs CLOCK_50, reset, the_command, send_command, // Bidirectionals PS2_CLK, // PS2 Clock PS2_DAT, // PS2 Data // Outputs command_was_sent, error_communication_timed_out, received_data, received_data_en // If 1 - new data has been received ); /***************************************************************************** * Port Declarations * *****************************************************************************/ // Inputs input CLOCK_50; input reset; input [7:0] the_command; input send_command; // Bidirectionals inout PS2_CLK; inout PS2_DAT; // Outputs output command_was_sent; output error_communication_timed_out; output [7:0] received_data; output received_data_en; // --------------------------------------------------------------------- wire [7:0] the_command_w; wire send_command_w, command_was_sent_w, error_communication_timed_out_w; generate if (INITIALIZE_MOUSE) begin assign the_command_w = init_done ? the_command : 8'hf4; assign send_command_w = init_done ? send_command : (!command_was_sent_w && !error_communication_timed_out_w); assign command_was_sent = init_done ? command_was_sent_w : 0; assign error_communication_timed_out = init_done ? error_communication_timed_out_w : 1; reg init_done; always @(posedge CLOCK_50) if (reset) init_done <= 0; else if (command_was_sent_w) init_done <= 1; end else begin assign the_command_w = the_command; assign send_command_w = send_command; assign command_was_sent = command_was_sent_w; assign error_communication_timed_out = error_communication_timed_out_w; end endgenerate /***************************************************************************** * Constant Declarations * *****************************************************************************/ // states localparam PS2_STATE_0_IDLE = 3'h0, PS2_STATE_1_DATA_IN = 3'h1, PS2_STATE_2_COMMAND_OUT = 3'h2, PS2_STATE_3_END_TRANSFER = 3'h3, PS2_STATE_4_END_DELAYED = 3'h4; /***************************************************************************** * Internal wires and registers Declarations * *****************************************************************************/ // Internal Wires wire ps2_clk_posedge; wire ps2_clk_negedge; wire start_receiving_data; wire wait_for_incoming_data; // Internal Registers reg [7:0] idle_counter; reg ps2_clk_reg; reg ps2_data_reg; reg last_ps2_clk; // State Machine Registers reg [2:0] ns_ps2_transceiver; reg [2:0] s_ps2_transceiver; /***************************************************************************** * Finite State Machine(s) * *****************************************************************************/ always @(posedge CLOCK_50) begin if (reset == 1'b1) s_ps2_transceiver <= PS2_STATE_0_IDLE; else s_ps2_transceiver <= ns_ps2_transceiver; end always @(*) begin // Defaults ns_ps2_transceiver = PS2_STATE_0_IDLE; case (s_ps2_transceiver) /* Ожидание */ PS2_STATE_0_IDLE: begin if ((idle_counter == 8'hFF) && (send_command == 1'b1)) ns_ps2_transceiver = PS2_STATE_2_COMMAND_OUT; else if ((ps2_data_reg == 1'b0) && (ps2_clk_posedge == 1'b1)) ns_ps2_transceiver = PS2_STATE_1_DATA_IN; else ns_ps2_transceiver = PS2_STATE_0_IDLE; end /* Получение данных */ PS2_STATE_1_DATA_IN: begin if ((received_data_en == 1'b1)/* && (ps2_clk_posedge == 1'b1)*/) ns_ps2_transceiver = PS2_STATE_0_IDLE; else ns_ps2_transceiver = PS2_STATE_1_DATA_IN; end /* Команда */ PS2_STATE_2_COMMAND_OUT: begin if ((command_was_sent == 1'b1) || (error_communication_timed_out == 1'b1)) ns_ps2_transceiver = PS2_STATE_3_END_TRANSFER; else ns_ps2_transceiver = PS2_STATE_2_COMMAND_OUT; end /* Завершение передачи */ PS2_STATE_3_END_TRANSFER: begin if (send_command == 1'b0) ns_ps2_transceiver = PS2_STATE_0_IDLE; else if ((ps2_data_reg == 1'b0) && (ps2_clk_posedge == 1'b1)) ns_ps2_transceiver = PS2_STATE_4_END_DELAYED; else ns_ps2_transceiver = PS2_STATE_3_END_TRANSFER; end /* Завершение передачи с задержкой */ PS2_STATE_4_END_DELAYED: begin if (received_data_en == 1'b1) begin if (send_command == 1'b0) ns_ps2_transceiver = PS2_STATE_0_IDLE; else ns_ps2_transceiver = PS2_STATE_3_END_TRANSFER; end else ns_ps2_transceiver = PS2_STATE_4_END_DELAYED; end /* Все другие статусы */ default: ns_ps2_transceiver = PS2_STATE_0_IDLE; endcase end /***************************************************************************** * Sequential logic * *****************************************************************************/ always @(posedge CLOCK_50) begin if (reset == 1'b1) begin last_ps2_clk <= 1'b1; ps2_clk_reg <= 1'b1; ps2_data_reg <= 1'b1; end else begin last_ps2_clk <= ps2_clk_reg; ps2_clk_reg <= PS2_CLK; ps2_data_reg <= PS2_DAT; end end always @(posedge CLOCK_50) begin if (reset == 1'b1) idle_counter <= 6'h00; else if ((s_ps2_transceiver == PS2_STATE_0_IDLE) && (idle_counter != 8'hFF)) idle_counter <= idle_counter + 6'h01; else if (s_ps2_transceiver != PS2_STATE_0_IDLE) idle_counter <= 6'h00; end /***************************************************************************** * Combinational logic * *****************************************************************************/ assign ps2_clk_posedge = ((ps2_clk_reg == 1'b1) && (last_ps2_clk == 1'b0)) ? 1'b1 : 1'b0; assign ps2_clk_negedge = ((ps2_clk_reg == 1'b0) && (last_ps2_clk == 1'b1)) ? 1'b1 : 1'b0; assign start_receiving_data = (s_ps2_transceiver == PS2_STATE_1_DATA_IN); assign wait_for_incoming_data = (s_ps2_transceiver == PS2_STATE_3_END_TRANSFER); /***************************************************************************** * Internal Modules * *****************************************************************************/ Altera_UP_PS2_Data_In PS2_Data_In ( // Inputs .clk (CLOCK_50), .reset (reset), .wait_for_incoming_data (wait_for_incoming_data), .start_receiving_data (start_receiving_data), .ps2_clk_posedge (ps2_clk_posedge), .ps2_clk_negedge (ps2_clk_negedge), .ps2_data (ps2_data_reg), // Bidirectionals Outputs .received_data (received_data), .received_data_en (received_data_en) ); Altera_UP_PS2_Command_Out PS2_Command_Out ( // Inputs .clk (CLOCK_50), .reset (reset), .the_command (the_command_w), .send_command (send_command_w), .ps2_clk_posedge (ps2_clk_posedge), .ps2_clk_negedge (ps2_clk_negedge), // Bidirectionals .PS2_CLK (PS2_CLK), .PS2_DAT (PS2_DAT), // Outputs .command_was_sent (command_was_sent_w), .error_communication_timed_out (error_communication_timed_out_w) ); endmodule
29 июн, 2020
© 2007-2023 Сидел психический компьютер