/////////////////////////////////////////////////////////////////////////
//
//     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
//     SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR
//     XILINX DEVICES.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION
//     AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION
//     OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS
//     IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
//     AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
//     FOR YOUR IMPLEMENTATION.  XILINX EXPRESSLY DISCLAIMS ANY
//     WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
//     IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
//     REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
//     INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//     FOR A PARTICULAR PURPOSE.
//     
//     (c) Copyright 2004 Xilinx, Inc.
//     All rights reserved.
//
/////////////////////////////////////////////////////////////////////////

module misc_logic (
  clk,              // I
  rst,              // I
  rst_n,            // O
  sys_rst_in,       // I
  sys_rst_in_i,     // O
  plb_arb_error,    // I
  plb_error,        // O
  opb_error,        // O
  phy_mii_int_n,    // I
  phy_mii_int,      // O
  OPB_xferAck,      // I
  OPB_retry,        // I
  OPB_errAck,       // I
  OPB_timeout,      // I
  ps2_clk_rx_1,     // O
  ps2_clk_rx_2,     // O
  ps2_clk_tx_1,     // I
  ps2_clk_tx_2,     // I
  ps2_d_rx_1,       // O
  ps2_d_rx_2,       // O
  ps2_d_tx_1,       // I
  ps2_d_tx_2,       // I
  ps2_mouse_clk_I,  // I
  ps2_mouse_clk_O,  // O
  ps2_mouse_clk_T,  // O
  ps2_mouse_data_I, // I
  ps2_mouse_data_O, // O
  ps2_mouse_data_T, // O
  ps2_keyb_clk_I,   // I
  ps2_keyb_clk_O,   // O
  ps2_keyb_clk_T,   // O
  ps2_keyb_data_I,  // I
  ps2_keyb_data_O,  // O
  ps2_keyb_data_T,  // O
  GPIO2_d_out,      // I
  GPIO2_t_out,      // I
  GPIO2_in,         // O
  sram_oe_n,        // I
  flash_oe_n,       // I
  sram_flash_oe_n,  // O
  usb_hpi_reset_n,  // O
  iic_scl_int_i,    // O
  iic_scl_int_o,    // I
  iic_scl_int_t,    // I
  iic_sda_int_i,    // O
  iic_sda_int_o,    // I
  iic_sda_int_t,    // I
  sda_I,            // I
  sda_O,            // O
  sda_T,            // O
  scl_I,            // I
  scl_O,            // O
  scl_T,            // O
  usb_addr,         // I [0:31]
  usb_data_i,       // O [0:31]
  usb_data_o,       // I [0:31]
  usb_data_t,       // I [0:31]
  usb_rdn,          // I
  usb_wrn,          // I
  usb_ce,           // I
  sysace_mpa,       // I [6:0]
  sysace_mpd_i,     // O [15:0]
  sysace_mpd_o,     // I [15:0]
  sysace_mpd_t,     // I [15:0]
  sysace_mpoe,      // I
  sysace_mpwe,      // I
  sace_usb_a,       // O [6:0]
  sace_usb_d_I,     // I [15:0]
  sace_usb_d_O,     // O [15:0]
  sace_usb_d_T,     // O [15:0]
  sace_usb_oen,     // O
  sace_usb_wen      // O
  );

  input  clk;
  input  rst;
  output rst_n;
  input  sys_rst_in;
  output sys_rst_in_i;
  input  plb_arb_error;
  output plb_error;
  output opb_error;
  input  phy_mii_int_n;
  output phy_mii_int;
  input  OPB_xferAck;
  input  OPB_retry;
  input  OPB_errAck;
  input  OPB_timeout;
  output ps2_clk_rx_1;
  output ps2_clk_rx_2;
  input  ps2_clk_tx_1;
  input  ps2_clk_tx_2;
  output ps2_d_rx_1;
  output ps2_d_rx_2;
  input  ps2_d_tx_1;
  input  ps2_d_tx_2;
  input  ps2_mouse_clk_I;
  output ps2_mouse_clk_O;
  output ps2_mouse_clk_T;
  input  ps2_mouse_data_I;
  output ps2_mouse_data_O;
  output ps2_mouse_data_T;
  input  ps2_keyb_clk_I;
  output ps2_keyb_clk_O;
  output ps2_keyb_clk_T;
  input  ps2_keyb_data_I;
  output ps2_keyb_data_O;
  output ps2_keyb_data_T;
  input  [26:0] GPIO2_d_out;
  input  [26:0] GPIO2_t_out;
  output [26:0] GPIO2_in;
  input  sram_oe_n;
  input  flash_oe_n;
  output sram_flash_oe_n;
  output usb_hpi_reset_n;
  output iic_scl_int_i;
  input  iic_scl_int_o;
  input  iic_scl_int_t;
  output iic_sda_int_i;
  input  iic_sda_int_o;
  input  iic_sda_int_t;
  input  sda_I;
  output sda_O;
  output sda_T;
  input  scl_I;
  output scl_O;
  output scl_T;
  // USB and SysAce Mux Logic
  input  [0:31] usb_addr;
  output [0:31] usb_data_i;
  input  [0:31] usb_data_o;
  input  [0:31] usb_data_t;
  input         usb_rdn;
  input         usb_wrn;
  input         usb_ce;
  input  [6:0]  sysace_mpa;
  output [15:0] sysace_mpd_i;
  input  [15:0] sysace_mpd_o;
  input  [15:0] sysace_mpd_t;
  input         sysace_mpoe;
  input         sysace_mpwe;
  output [6:0]  sace_usb_a;
  input  [15:0] sace_usb_d_I;
  output [15:0] sace_usb_d_O;
  output [15:0] sace_usb_d_T;
  output        sace_usb_oen;
  output        sace_usb_wen;

  reg    opb_error;
  reg    plb_error;

  // inverters
  assign rst_n = ~rst;
  assign phy_mii_int = ~phy_mii_int_n;

  // latch PLB error condition since error signal is just a pulse  
  always @(posedge clk)
  if (rst | GPIO2_t_out[4])
    plb_error <= 1'b0;
  else if (plb_arb_error | GPIO2_t_out[5])
    plb_error <= 1'b1;

  always @(posedge clk)
  if (rst | GPIO2_t_out[2])
    opb_error <= 1'b0;
  else if (OPB_errAck | (OPB_timeout & ~(OPB_xferAck | OPB_retry))
         | GPIO2_t_out[3])
    opb_error <= 1'b1;

  // Reset Button Logic - Can be switched over to a general purpose input
  assign sys_rst_in_i = (GPIO2_t_out[12])? 1'b1 : sys_rst_in;
  assign GPIO2_in[12] = ~sys_rst_in;

  // PS/2 Assignments
  assign ps2_clk_rx_1 = ps2_mouse_clk_I;
  assign ps2_clk_rx_2 = ps2_keyb_clk_I;
  assign ps2_d_rx_1   = ps2_mouse_data_I;
  assign ps2_d_rx_2   = ps2_keyb_data_I;

  assign GPIO2_in[8]  = ps2_mouse_clk_I;
  assign GPIO2_in[9]  = ps2_mouse_data_I;
  assign GPIO2_in[10] = ps2_keyb_clk_I;
  assign GPIO2_in[11] = ps2_keyb_data_I;

  assign ps2_mouse_clk_O  = (GPIO2_t_out[7])? GPIO2_d_out[8]  : 1'b0;
  assign ps2_mouse_clk_T  = (GPIO2_t_out[7])? GPIO2_t_out[8]  : ~ps2_clk_tx_1;
  assign ps2_mouse_data_O = (GPIO2_t_out[7])? GPIO2_d_out[9]  : 1'b0;
  assign ps2_mouse_data_T = (GPIO2_t_out[7])? GPIO2_t_out[9]  : ~ps2_d_tx_1;
  assign ps2_keyb_clk_O   = (GPIO2_t_out[7])? GPIO2_d_out[10] : 1'b0;
  assign ps2_keyb_clk_T   = (GPIO2_t_out[7])? GPIO2_t_out[10] : ~ps2_clk_tx_2;
  assign ps2_keyb_data_O  = (GPIO2_t_out[7])? GPIO2_d_out[11] : 1'b0;
  assign ps2_keyb_data_T  = (GPIO2_t_out[7])? GPIO2_t_out[11] : ~ps2_d_tx_2;

  // combine sram and flash oe_n signals together
  // (chips are distinguished via CE pins)
  assign sram_flash_oe_n = sram_oe_n & flash_oe_n;

  // Drive USB Reset
  assign usb_hpi_reset_n = ~GPIO2_t_out[13];

  // IIC mux between OPB_IIC or GPIO control of ML401 IIC bus
  // GPIO2_t_out[6] = 1 for GPIO, 0 for OPB_IIC
  assign scl_O = (GPIO2_t_out[6])? GPIO2_d_out[0] : iic_scl_int_o;
  assign scl_T = (GPIO2_t_out[6])? GPIO2_t_out[0] : iic_scl_int_t;
  assign iic_scl_int_i = (GPIO2_t_out[6])? 1'b1 : scl_I;
  assign GPIO2_in[0] = (GPIO2_t_out[6])? scl_I : 1'b1;

  assign sda_O = (GPIO2_t_out[6])? GPIO2_d_out[1] : iic_sda_int_o;
  assign sda_T = (GPIO2_t_out[6])? GPIO2_t_out[1] : iic_sda_int_t;
  assign iic_sda_int_i = (GPIO2_t_out[6])? 1'b1 : sda_I;
  assign GPIO2_in[1] = (GPIO2_t_out[6])? sda_I : 1'b1;

  // USB and SysAce Mux Logic
  assign usb_data_i = {sace_usb_d_I, 16'b0};
  assign sysace_mpd_i = sace_usb_d_I;
  assign sace_usb_a   = (usb_ce)? {4'b0,usb_addr[28:29],1'b0} : sysace_mpa;
  assign sace_usb_d_O = (usb_ce)? usb_data_o[0:15] : sysace_mpd_o;
  assign sace_usb_d_T = (usb_ce)? usb_data_t[0:15] : sysace_mpd_t;
  assign sace_usb_oen = (usb_ce)? usb_rdn : sysace_mpoe;
  assign sace_usb_wen = (usb_ce)? usb_wrn : sysace_mpwe;

endmodule // misc_logic
