LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; ENTITY gpio_wb IS Port ( CLK_I : in STD_LOGIC; RST_I : in STD_LOGIC; CYC_I : in STD_LOGIC; STB_I : in STD_LOGIC; SEL_I : in unsigned(3 downto 0); WE_I : in STD_LOGIC; ACK_O : out STD_LOGIC; SRDY_O : out STD_LOGIC; MRDY_I : in STD_LOGIC; ADDR_I : in unsigned(31 downto 0); DAT_I : in unsigned(31 downto 0); DAT_O : out unsigned(31 downto 0); sys_gpo0 : out unsigned(31 downto 0); sys_gpo1 : out unsigned(31 downto 0); sys_gpi0 : in unsigned(31 downto 0); sys_gpi1 : in unsigned(31 downto 0) ); END gpio_wb; ARCHITECTURE behavior OF gpio_wb IS signal gpo0_reg : unsigned(31 downto 0); signal gpo1_reg : unsigned(31 downto 0); signal gpi0_reg : unsigned(31 downto 0); signal gpi1_reg : unsigned(31 downto 0); -- Signals to form an timer generating an interrupt every microsecond subtype tick_usec_t is natural range 0 to 99; signal tick_usec : tick_usec_t; signal cnt_usec : unsigned(31 downto 0); signal cnt_sec : unsigned(31 downto 0); signal cnt_usec_preset : unsigned(31 downto 0); signal cnt_sec_preset : unsigned(31 downto 0); signal cnt_usec_en : std_logic; signal cnt_usec_we : std_logic; signal cnt_sec_en : std_logic; signal cnt_sec_we : std_logic; begin SRDY_O <= CYC_I; ------------------------------------------------------------------ led_out: process(CLK_I) begin if rising_edge(CLK_I) then sys_gpo0 <= gpo0_reg; sys_gpo1 <= gpo1_reg; end if; end process; ------------------------------------------------------------------ btn_ps2_in: process(CLK_I) begin if rising_edge(CLK_I) then gpi0_reg <= sys_gpi0; gpi1_reg <= sys_gpi1; end if; end process; ------------------------------------------------------------------ registers_write: process(CLK_I) begin if rising_edge(CLK_I) then cnt_usec_we <= '0'; cnt_sec_we <= '0'; if RST_I = '1' then gpo0_reg <= (others => '0'); gpo1_reg <= (others => '0'); elsif (STB_I and CYC_I and WE_I) = '1' then case ADDR_I(5 downto 2) is when "0000" => if SEL_I(0) = '1' then gpo0_reg(7 downto 0) <= DAT_I(7 downto 0); end if; if SEL_I(1) = '1' then gpo0_reg(15 downto 8) <= DAT_I(15 downto 8); end if; if SEL_I(2) = '1' then gpo0_reg(23 downto 16) <= DAT_I(23 downto 16); end if; if SEL_I(3) = '1' then gpo0_reg(31 downto 24) <= DAT_I(31 downto 24); end if; when "0001" => if SEL_I(0) = '1' then gpo1_reg(7 downto 0) <= DAT_I(7 downto 0); end if; if SEL_I(1) = '1' then gpo1_reg(15 downto 8) <= DAT_I(15 downto 8); end if; if SEL_I(2) = '1' then gpo1_reg(23 downto 16) <= DAT_I(23 downto 16); end if; if SEL_I(3) = '1' then gpo1_reg(31 downto 24) <= DAT_I(31 downto 24); end if; when "0010" => if SEL_I(3) = '1' then cnt_usec_we <= '1'; cnt_usec_preset <= DAT_I; end if; when "0011" => if SEL_I(3) = '1' then cnt_sec_we <= '1'; cnt_sec_preset <= DAT_I; end if; when others => null; end case; end if; end if; end process; registers_read: process(CLK_I) begin if rising_edge(CLK_I) then ACK_O <= '0'; if (STB_I and CYC_I) = '1' then ACK_O <= not WE_I; DAT_O <= (others => '0'); case ADDR_I(5 downto 2) is when "0000" => DAT_O <= gpi0_reg; when "0001" => DAT_O <= gpi1_reg; when "0010" => DAT_O <= cnt_usec; when "0011" => DAT_O <= cnt_sec; when others => null; end case; end if; end if; end process; tick_usec_timer: process(CLK_I) begin if rising_edge(CLK_I) then cnt_usec_en <= '0'; if RST_I = '1' then tick_usec <= 0; cnt_usec_en <= '0'; elsif tick_usec = tick_usec_t'high then tick_usec <= 0; cnt_usec_en <= '1'; else tick_usec <= tick_usec + 1; end if; end if; end process; cnt_usec_timer: process(CLK_I) begin if rising_edge(CLK_I) then cnt_sec_en <= '0'; if RST_I = '1' then cnt_usec <= (others => '0'); cnt_sec_en <= '0'; elsif cnt_usec_we = '1' then cnt_usec <= cnt_usec_preset; elsif cnt_usec_en = '1' then if cnt_usec = to_unsigned(1E6 - 1, 32) then cnt_usec <= (others => '0'); cnt_sec_en <= '1'; else cnt_usec <= cnt_usec + 1; end if; end if; end if; end process; cnt_sec_timer: process(CLK_I) begin if rising_edge(CLK_I) then if RST_I = '1' then cnt_sec <= (others => '0'); elsif cnt_sec_we = '1' then cnt_sec <= cnt_sec_preset; elsif cnt_sec_en = '1' then cnt_sec <= cnt_sec + 1; end if; end if; end process; ------------------------------------------------------------------ end behavior;