module simple_gpio(
  clk_i, rst_i, cyc_i, stb_i, adr_i, we_i, dat_i, dat_o, ack_o,
  gpio
);

  //
  // Inputs & outputs
  //
  parameter io = 8;            // number of GPIOs

  // 8bit WISHBONE bus slave interface
  input         clk_i;         // clock
  input         rst_i;         // reset (asynchronous active low)
  input         cyc_i;         // cycle
  input         stb_i;         // strobe
  input         adr_i;         // address adr_i[1]
  input         we_i;          // write enable
  input  [ 7:0] dat_i;         // data output
  output [ 7:0] dat_o;         // data input
  output        ack_o;         // normal bus termination

  // GPIO pins
  inout  [io:1] gpio;

  //
  // Module body
  //
  reg [io:1] ctrl, line;                  // ControlRegister, LineRegister
  reg [io:1] lgpio, llgpio;               // LatchedGPIO pins

  //
  // perform parameter checks
  //
  // synopsys translate_off
  initial
  begin
      if(io > 8)
        $display("simple_gpio: max. 8 GPIOs supported.");
  end
  // synopsys translate_on

  //
  // WISHBONE interface

  wire wb_acc = cyc_i & stb_i;            // WISHBONE access
  wire wb_wr  = wb_acc & we_i;            // WISHBONE write access

  always @(posedge clk_i or negedge rst_i)
    if (~rst_i)
      begin
          ctrl <= #1 {io{1'b0}};
          line <= #1 {io{1'b0}};
      end
    else if (wb_wr)
       if ( adr_i )
         line <= #1 dat_i[io-1:0];
       else
         ctrl <= #1 dat_i[io-1:0];


  reg [7:0] dat_o;
  always @(posedge clk_i)
    if ( adr_i )
      dat_o <= #1 { {(8-io){1'b0}}, llgpio};
    else
      dat_o <= #1 { {(8-io){1'b0}}, ctrl};

  reg ack_o;
  always @(posedge clk_i or negedge rst_i)
    if (~rst_i)
      ack_o <= #1 1'b0;
    else
      ack_o <= #1 wb_acc & !ack_o;


  //
  // GPIO section

  // latch GPIO input pins
  always @(posedge clk_i)
    lgpio <= #1 gpio;

  // latch again (reduce meta-stability risc)
  always @(posedge clk_i)
    llgpio <= #1 lgpio;

  // assign GPIO outputs
  integer n;
  reg [io:1] igpio; // temporary internal signal

  always @(ctrl or line)
    for(n=1;n<=io;n=n+1)
      igpio[n] <= ctrl[n] ? line[n] : 1'bz;

  assign gpio = igpio;

endmodule