212 lines
4.7 KiB
VHDL
212 lines
4.7 KiB
VHDL
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;
|