From c883cd4a4e4fa1974e5d7d72a79240de88bd26da Mon Sep 17 00:00:00 2001 From: Bert Lange Date: Tue, 25 Oct 2011 23:26:36 +0200 Subject: add: GPIO module to zealot SoC --- zpu/hdl/zealot/devices/gpio.vhdl | 107 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 zpu/hdl/zealot/devices/gpio.vhdl (limited to 'zpu/hdl/zealot/devices/gpio.vhdl') diff --git a/zpu/hdl/zealot/devices/gpio.vhdl b/zpu/hdl/zealot/devices/gpio.vhdl new file mode 100644 index 0000000..fc66bde --- /dev/null +++ b/zpu/hdl/zealot/devices/gpio.vhdl @@ -0,0 +1,107 @@ +-- +-- this module desribes a simple GPIO interface +-- +-- data on port_in is synhronized to clk_i and can be read at +-- address 0 +-- +-- any write to address 0 is mapped to port_out +-- +-- at address 1 is a direction register (port_dir) +-- initialized with '1's, what mean direction = in +-- this register is useful for bidirectional pins, e.g. headers +-- +-- +-- some examples: +-- +-- to connect 4 buttons: +-- port_in( 3 downto 0) <= gpio_button; +-- +-- +-- to connect 8 LEDs: +-- gpio_led <= port_out(7 downto 0); +-- +-- +-- to connect 2 bidirectional header pins: +-- port_in(8) <= gpio_pin(0); +-- gpio_pin(0) <= port_out(8) when port_dir(8) = '0' else 'Z'; +-- +-- port_in(9) <= gpio_pin(1); +-- gpio_pin(1) <= port_out(9) when port_dir(9) = '0' else 'Z'; +-- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +entity gpio is + port( + clk_i : in std_logic; + reset_i : in std_logic; + -- + we_i : in std_logic; + data_i : in unsigned(31 downto 0); + addr_i : in unsigned( 0 downto 0); + data_o : out unsigned(31 downto 0); + -- + port_in : in std_logic_vector(31 downto 0); + port_out : out std_logic_vector(31 downto 0); + port_dir : out std_logic_vector(31 downto 0) + ); +end entity gpio; + + +architecture rtl of gpio is + + signal port_in_reg : std_logic_vector(31 downto 0); + signal port_in_sync : std_logic_vector(31 downto 0); + -- + signal direction : std_logic_vector(31 downto 0) := (others => '1'); + +begin + + process + begin + wait until rising_edge( clk_i); + + -- synchronize all inputs with two registers + -- to avoid metastability + port_in_reg <= port_in; + port_in_sync <= port_in_reg; + + -- write access to gpio + if we_i = '1' then + -- data + if addr_i = "0" then + port_out <= std_logic_vector( data_i); + end if; + -- direction + if addr_i = "1" then + direction <= std_logic_vector( data_i); + end if; + end if; + + -- read access to gpio + -- data + if addr_i = "0" then + data_o <= unsigned( port_in_sync); + end if; + -- direction + if addr_i = "1" then + data_o <= unsigned( direction); + end if; + + -- outputs + port_dir <= direction; + + -- sync reset + if reset_i = '1' then + direction <= (others => '1'); + port_in_reg <= (others => '0'); + port_in_sync <= (others => '0'); + end if; + + end process; + + +end architecture rtl; -- cgit v1.1