+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+
+--------------------------------------------------------------------------------
+
+entity gpio is
+ generic (
+ W : integer := 8); -- GPIO port width (pin count)
+ port (
+ -- Peripheral bus interface
+ ACK_O : out std_logic;
+ ADR_I : in std_logic_vector (1 downto 0);
+ CLK_I : in std_logic;
+ DAT_I : in std_logic_vector (W-1 downto 0);
+ DAT_O : out std_logic_vector (W-1 downto 0);
+ RST_I : in std_logic;
+ SEL_I : in std_logic;
+ STB_I : in std_logic;
+ WE_I : in std_logic;
+ -- GPIO port pins
+ GPIO_I : in std_logic_vector (W-1 downto 0);
+ GPIO_O : out std_logic_vector (W-1 downto 0));
+end gpio;
+
+--------------------------------------------------------------------------------
+
+architecture behavioral of gpio is
+
+ signal gpio_output : std_logic_vector (W-1 downto 0) := (others => '0');
+ signal gpio_output_new : std_logic_vector (W-1 downto 0);
+ signal write_en : std_logic;
+
+begin
+
+ ACK_O <= SEL_I and STB_I;
+
+ with ADR_I select
+ DAT_O <=
+ GPIO_I when "00",
+ gpio_output when "01",
+ (others => '-') when others;
+
+
+ with ADR_I select
+ gpio_output_new <=
+ DAT_I when "01",
+ gpio_output or DAT_I when "10",
+ gpio_output and not DAT_I when "11",
+ gpio_output when others;
+
+ write_en <= SEL_I and STB_I and WE_I;
+
+ process (CLK_I, RST_I) is
+ begin
+ if rising_edge(CLK_I) then
+ if RST_I = '1' then
+ gpio_output <= (others => '0');
+ else
+ if write_en = '1' then
+ gpio_output <= gpio_output_new;
+ end if;
+ end if;
+ end if;
+ end process;
+
+end behavioral;
+