From: Paul Mackerras Date: Tue, 23 Feb 2021 10:44:04 +0000 (+1100) Subject: Add a GPIO controller and use it to drive the shield I/O pins on the Arty X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f06ffcf9b7715f5537c1bfed985c322ec629f413;p=microwatt.git Add a GPIO controller and use it to drive the shield I/O pins on the Arty This adds a GPIO controller which provides 32 bits of I/O. The registers are modelled on the set used by the gpio-ftgpio010.c driver in the Linux kernel. Currently there is no interrupt capability implemented, though an interrupt line from the GPIO subsystem to the XICS has been connected. For the Arty A7 board, GPIO lines 0 to 13 are connected to the pins labelled IO0 to IO13 on the "shield" connector, GPIO lines 14 to 29 connect to IO26 to IO41, GPIO line 30 connects to the pin labelled A (aka IO42), and GPIO line 31 is connected to LED 7. Signed-off-by: Paul Mackerras --- diff --git a/Makefile b/Makefile index 678bbfa..05eff4a 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ core_files = decode_types.vhdl common.vhdl wishbone_types.vhdl fetch1.vhdl \ core.vhdl fpu.vhdl soc_files = $(core_files) wishbone_arbiter.vhdl wishbone_bram_wrapper.vhdl sync_fifo.vhdl \ - wishbone_debug_master.vhdl xics.vhdl syscon.vhdl soc.vhdl \ + wishbone_debug_master.vhdl xics.vhdl syscon.vhdl gpio.vhdl soc.vhdl \ spi_rxtx.vhdl spi_flash_ctrl.vhdl uart_files = $(wildcard uart16550/*.v) diff --git a/fpga/arty_a7.xdc b/fpga/arty_a7.xdc index 7cdad8d..81c7cf9 100644 --- a/fpga/arty_a7.xdc +++ b/fpga/arty_a7.xdc @@ -115,39 +115,39 @@ set_property IOB true [get_cells -hierarchical -filter {NAME =~*/spi_rxtx/input_ # Arduino/chipKIT shield connector ################################################################################ -#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { shield_io0 }]; -#set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { shield_io1 }]; -#set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { shield_io2 }]; -#set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { shield_io3 }]; -#set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { shield_io4 }]; -#set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { shield_io5 }]; -#set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { shield_io6 }]; -#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { shield_io7 }]; -#set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { shield_io8 }]; -#set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { shield_io9 }]; -#set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { shield_io10 }]; -#set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { shield_io11 }]; -#set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { shield_io12 }]; -#set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { shield_io13 }]; -#set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { shield_io26 }]; -#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { shield_io27 }]; -#set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { shield_io28 }]; -#set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { shield_io29 }]; -#set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { shield_io30 }]; -#set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { shield_io31 }]; -#set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { shield_io32 }]; -#set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { shield_io33 }]; -#set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { shield_io34 }]; -#set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { shield_io35 }]; -#set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { shield_io36 }]; -#set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { shield_io37 }]; -#set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { shield_io38 }]; -#set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { shield_io39 }]; -#set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { shield_io40 }]; -#set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { shield_io41 }]; -#set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { shield_ioa }]; -#set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { shield_scl }]; -#set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { shield_sda }]; +set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { shield_io[0] }]; +set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { shield_io[1] }]; +set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { shield_io[2] }]; +set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { shield_io[3] }]; +set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { shield_io[4] }]; +set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { shield_io[5] }]; +set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { shield_io[6] }]; +set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { shield_io[7] }]; +set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { shield_io[8] }]; +set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { shield_io[9] }]; +set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { shield_io[10] }]; +set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { shield_io[11] }]; +set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { shield_io[12] }]; +set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { shield_io[13] }]; +set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { shield_io[26] }]; +set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { shield_io[27] }]; +set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { shield_io[28] }]; +set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { shield_io[29] }]; +set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { shield_io[30] }]; +set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { shield_io[31] }]; +set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { shield_io[32] }]; +set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { shield_io[33] }]; +set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { shield_io[34] }]; +set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { shield_io[35] }]; +set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { shield_io[36] }]; +set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { shield_io[37] }]; +set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { shield_io[38] }]; +set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { shield_io[39] }]; +set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { shield_io[40] }]; +set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { shield_io[41] }]; +set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { shield_io[42] }]; # A +set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { shield_io[43] }]; # SCL +set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { shield_io[44] }]; # SDA #set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { shield_rst }]; #set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { spi_hdr_ss }]; diff --git a/fpga/top-arty.vhdl b/fpga/top-arty.vhdl index 68d1e89..a6117d8 100644 --- a/fpga/top-arty.vhdl +++ b/fpga/top-arty.vhdl @@ -26,7 +26,8 @@ entity toplevel is LOG_LENGTH : natural := 512; USE_LITEETH : boolean := false; UART_IS_16550 : boolean := false; - HAS_UART1 : boolean := true + HAS_UART1 : boolean := true; + NGPIO : natural := 32 ); port( ext_clk : in std_ulogic; @@ -59,6 +60,9 @@ entity toplevel is spi_flash_wp_n : inout std_ulogic; spi_flash_hold_n : inout std_ulogic; + -- GPIO + shield_io : inout std_ulogic_vector(44 downto 0); + -- Ethernet eth_ref_clk : out std_ulogic; eth_clocks_tx : in std_ulogic; @@ -140,6 +144,11 @@ architecture behaviour of toplevel is signal spi_sdat_oe : std_ulogic_vector(3 downto 0); signal spi_sdat_i : std_ulogic_vector(3 downto 0); + -- GPIO + signal gpio_in : std_ulogic_vector(NGPIO - 1 downto 0); + signal gpio_out : std_ulogic_vector(NGPIO - 1 downto 0); + signal gpio_dir : std_ulogic_vector(NGPIO - 1 downto 0); + -- Fixup various memory sizes based on generics function get_bram_size return natural is begin @@ -184,7 +193,8 @@ begin LOG_LENGTH => LOG_LENGTH, HAS_LITEETH => USE_LITEETH, UART0_IS_16550 => UART_IS_16550, - HAS_UART1 => HAS_UART1 + HAS_UART1 => HAS_UART1, + NGPIO => NGPIO ) port map ( -- System signals @@ -206,6 +216,11 @@ begin spi_flash_sdat_oe => spi_sdat_oe, spi_flash_sdat_i => spi_sdat_i, + -- GPIO signals + gpio_in => gpio_in, + gpio_out => gpio_out, + gpio_dir => gpio_dir, + -- External interrupts ext_irq_eth => ext_irq_eth, @@ -545,6 +560,72 @@ begin led4 <= system_clk_locked; led5 <= eth_clk_locked; led6 <= not soc_rst; - led7 <= not spi_flash_cs_n; + + -- GPIO + gpio_in(0) <= shield_io(0); + gpio_in(1) <= shield_io(1); + gpio_in(2) <= shield_io(2); + gpio_in(3) <= shield_io(3); + gpio_in(4) <= shield_io(4); + gpio_in(5) <= shield_io(5); + gpio_in(6) <= shield_io(6); + gpio_in(7) <= shield_io(7); + gpio_in(8) <= shield_io(8); + gpio_in(9) <= shield_io(9); + gpio_in(10) <= shield_io(10); + gpio_in(11) <= shield_io(11); + gpio_in(12) <= shield_io(12); + gpio_in(13) <= shield_io(13); + gpio_in(14) <= shield_io(26); + gpio_in(15) <= shield_io(27); + gpio_in(16) <= shield_io(28); + gpio_in(17) <= shield_io(29); + gpio_in(18) <= shield_io(30); + gpio_in(19) <= shield_io(31); + gpio_in(20) <= shield_io(32); + gpio_in(21) <= shield_io(33); + gpio_in(22) <= shield_io(34); + gpio_in(23) <= shield_io(35); + gpio_in(24) <= shield_io(36); + gpio_in(25) <= shield_io(37); + gpio_in(26) <= shield_io(38); + gpio_in(27) <= shield_io(39); + gpio_in(28) <= shield_io(40); + gpio_in(29) <= shield_io(41); + gpio_in(30) <= shield_io(42); + gpio_in(31) <= gpio_out(31); + + shield_io(0) <= gpio_out(0) when gpio_dir(0) = '1' else 'Z'; + shield_io(1) <= gpio_out(1) when gpio_dir(1) = '1' else 'Z'; + shield_io(2) <= gpio_out(2) when gpio_dir(2) = '1' else 'Z'; + shield_io(3) <= gpio_out(3) when gpio_dir(3) = '1' else 'Z'; + shield_io(4) <= gpio_out(4) when gpio_dir(4) = '1' else 'Z'; + shield_io(5) <= gpio_out(5) when gpio_dir(5) = '1' else 'Z'; + shield_io(6) <= gpio_out(6) when gpio_dir(6) = '1' else 'Z'; + shield_io(7) <= gpio_out(7) when gpio_dir(7) = '1' else 'Z'; + shield_io(8) <= gpio_out(8) when gpio_dir(8) = '1' else 'Z'; + shield_io(9) <= gpio_out(9) when gpio_dir(9) = '1' else 'Z'; + shield_io(10) <= gpio_out(10) when gpio_dir(10) = '1' else 'Z'; + shield_io(11) <= gpio_out(11) when gpio_dir(11) = '1' else 'Z'; + shield_io(12) <= gpio_out(12) when gpio_dir(12) = '1' else 'Z'; + shield_io(13) <= gpio_out(13) when gpio_dir(13) = '1' else 'Z'; + shield_io(26) <= gpio_out(14) when gpio_dir(14) = '1' else 'Z'; + shield_io(27) <= gpio_out(15) when gpio_dir(15) = '1' else 'Z'; + shield_io(28) <= gpio_out(16) when gpio_dir(16) = '1' else 'Z'; + shield_io(29) <= gpio_out(17) when gpio_dir(17) = '1' else 'Z'; + shield_io(30) <= gpio_out(18) when gpio_dir(18) = '1' else 'Z'; + shield_io(31) <= gpio_out(19) when gpio_dir(19) = '1' else 'Z'; + shield_io(32) <= gpio_out(20) when gpio_dir(20) = '1' else 'Z'; + shield_io(33) <= gpio_out(21) when gpio_dir(21) = '1' else 'Z'; + shield_io(34) <= gpio_out(22) when gpio_dir(22) = '1' else 'Z'; + shield_io(35) <= gpio_out(23) when gpio_dir(23) = '1' else 'Z'; + shield_io(36) <= gpio_out(24) when gpio_dir(24) = '1' else 'Z'; + shield_io(37) <= gpio_out(25) when gpio_dir(25) = '1' else 'Z'; + shield_io(38) <= gpio_out(26) when gpio_dir(26) = '1' else 'Z'; + shield_io(39) <= gpio_out(27) when gpio_dir(27) = '1' else 'Z'; + shield_io(40) <= gpio_out(28) when gpio_dir(28) = '1' else 'Z'; + shield_io(41) <= gpio_out(29) when gpio_dir(29) = '1' else 'Z'; + shield_io(42) <= gpio_out(30) when gpio_dir(30) = '1' else 'Z'; + led7 <= gpio_out(31) and gpio_dir(31); end architecture behaviour; diff --git a/gpio.vhdl b/gpio.vhdl new file mode 100644 index 0000000..bdce519 --- /dev/null +++ b/gpio.vhdl @@ -0,0 +1,99 @@ +-- GPIO module for microwatt +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.wishbone_types.all; + +entity gpio is + generic ( + NGPIO : integer := 32 + ); + port ( + clk : in std_ulogic; + rst : in std_ulogic; + + -- Wishbone + wb_in : in wb_io_master_out; + wb_out : out wb_io_slave_out; + + -- GPIO lines + gpio_in : in std_ulogic_vector(NGPIO - 1 downto 0); + gpio_out : out std_ulogic_vector(NGPIO - 1 downto 0); + -- 1 = output, 0 = input + gpio_dir : out std_ulogic_vector(NGPIO - 1 downto 0); + + -- Interrupt + intr : out std_ulogic + ); +end entity gpio; + +architecture behaviour of gpio is + constant GPIO_REG_BITS : positive := 5; + + -- Register addresses, matching addr downto 2, so 4 bytes per reg + constant GPIO_REG_DATA_OUT : std_ulogic_vector(GPIO_REG_BITS-1 downto 0) := "00000"; + constant GPIO_REG_DATA_IN : std_ulogic_vector(GPIO_REG_BITS-1 downto 0) := "00001"; + constant GPIO_REG_DIR : std_ulogic_vector(GPIO_REG_BITS-1 downto 0) := "00010"; + constant GPIO_REG_DATA_SET : std_ulogic_vector(GPIO_REG_BITS-1 downto 0) := "00100"; + constant GPIO_REG_DATA_CLR : std_ulogic_vector(GPIO_REG_BITS-1 downto 0) := "00101"; + + -- Current output value and direction + signal reg_data : std_ulogic_vector(NGPIO - 1 downto 0) := (others => '0'); + signal reg_dirn : std_ulogic_vector(NGPIO - 1 downto 0) := (others => '0'); + signal reg_in1 : std_ulogic_vector(NGPIO - 1 downto 0); + signal reg_in2 : std_ulogic_vector(NGPIO - 1 downto 0); + + signal wb_rsp : wb_io_slave_out; + signal reg_out : std_ulogic_vector(NGPIO - 1 downto 0); + +begin + + -- No interrupt facility for now + intr <= '0'; + + gpio_out <= reg_data; + gpio_dir <= reg_dirn; + + -- Wishbone response + wb_rsp.ack <= wb_in.cyc and wb_in.stb; + with wb_in.adr(GPIO_REG_BITS + 1 downto 2) select reg_out <= + reg_data when GPIO_REG_DATA_OUT, + reg_in2 when GPIO_REG_DATA_IN, + reg_dirn when GPIO_REG_DIR, + (others => '0') when others; + wb_rsp.dat(wb_rsp.dat'left downto NGPIO) <= (others => '0'); + wb_rsp.dat(NGPIO - 1 downto 0) <= reg_out; + wb_rsp.stall <= '0'; + + regs_rw: process(clk) + begin + if rising_edge(clk) then + wb_out <= wb_rsp; + reg_in2 <= reg_in1; + reg_in1 <= gpio_in; + if rst = '1' then + reg_data <= (others => '0'); + reg_dirn <= (others => '0'); + wb_out.ack <= '0'; + else + if wb_in.cyc = '1' and wb_in.stb = '1' and wb_in.we = '1' then + case wb_in.adr(GPIO_REG_BITS + 1 downto 2) is + when GPIO_REG_DATA_OUT => + reg_data <= wb_in.dat(NGPIO - 1 downto 0); + when GPIO_REG_DIR => + reg_dirn <= wb_in.dat(NGPIO - 1 downto 0); + when GPIO_REG_DATA_SET => + reg_data <= reg_data or wb_in.dat(NGPIO - 1 downto 0); + when GPIO_REG_DATA_CLR => + reg_data <= reg_data and not wb_in.dat(NGPIO - 1 downto 0); + when others => + end case; + end if; + end if; + end if; + end process; + +end architecture behaviour; + diff --git a/microwatt.core b/microwatt.core index 79af3c1..9da8313 100644 --- a/microwatt.core +++ b/microwatt.core @@ -44,6 +44,7 @@ filesets: - wishbone_bram_wrapper.vhdl - soc.vhdl - xics.vhdl + - gpio.vhdl - syscon.vhdl - sync_fifo.vhdl - spi_rxtx.vhdl diff --git a/soc.vhdl b/soc.vhdl index 88249bf..2bf3b72 100644 --- a/soc.vhdl +++ b/soc.vhdl @@ -24,6 +24,7 @@ use work.wishbone_types.all; -- 0xc0004000: XICS ICP -- 0xc0005000: XICS ICS -- 0xc0006000: SPI Flash controller +-- 0xc0007000: GPIO controller -- 0xc8nnnnnn: External IO bus -- 0xf0000000: Flash "ROM" mapping -- 0xff000000: DRAM init code (if any) or flash ROM (**) @@ -66,7 +67,8 @@ entity soc is LOG_LENGTH : natural := 512; HAS_LITEETH : boolean := false; UART0_IS_16550 : boolean := true; - HAS_UART1 : boolean := false + HAS_UART1 : boolean := false; + NGPIO : natural := 0 ); port( rst : in std_ulogic; @@ -101,6 +103,11 @@ entity soc is spi_flash_sdat_oe : out std_ulogic_vector(SPI_FLASH_DLINES-1 downto 0); spi_flash_sdat_i : in std_ulogic_vector(SPI_FLASH_DLINES-1 downto 0) := (others => '1'); + -- GPIO signals + gpio_out : out std_ulogic_vector(NGPIO - 1 downto 0); + gpio_dir : out std_ulogic_vector(NGPIO - 1 downto 0); + gpio_in : in std_ulogic_vector(NGPIO - 1 downto 0) := (others => '0'); + -- DRAM controller signals alt_reset : in std_ulogic := '0' ); @@ -167,6 +174,11 @@ architecture behaviour of soc is signal ics_to_icp : ics_to_icp_t; signal core_ext_irq : std_ulogic; + -- GPIO signals: + signal wb_gpio_in : wb_io_master_out; + signal wb_gpio_out : wb_io_slave_out; + signal gpio_intr : std_ulogic := '0'; + -- Main memory signals: signal wb_bram_in : wishbone_master_out; signal wb_bram_out : wishbone_slave_out; @@ -192,6 +204,7 @@ architecture behaviour of soc is signal rst_uart : std_ulogic := '1'; signal rst_xics : std_ulogic := '1'; signal rst_spi : std_ulogic := '1'; + signal rst_gpio : std_ulogic := '1'; signal rst_bram : std_ulogic := '1'; signal rst_dtm : std_ulogic := '1'; signal rst_wbar : std_ulogic := '1'; @@ -206,6 +219,7 @@ architecture behaviour of soc is SLAVE_IO_UART1, SLAVE_IO_SPI_FLASH_REG, SLAVE_IO_SPI_FLASH_MAP, + SLAVE_IO_GPIO, SLAVE_IO_EXTERNAL, SLAVE_IO_NONE); signal slave_io_dbg : slave_io_type; @@ -243,6 +257,7 @@ begin rst_uart <= rst; rst_spi <= rst; rst_xics <= rst; + rst_gpio <= rst; rst_bram <= rst; rst_dtm <= rst; rst_wbar <= rst; @@ -530,6 +545,8 @@ begin slave_io := SLAVE_IO_ICS; elsif std_match(match, x"C0006") then slave_io := SLAVE_IO_SPI_FLASH_REG; + elsif std_match(match, x"C0007") then + slave_io := SLAVE_IO_GPIO; end if; slave_io_dbg <= slave_io; wb_uart0_in <= wb_sio_out; @@ -540,6 +557,8 @@ begin wb_spiflash_in.cyc <= '0'; wb_spiflash_is_reg <= '0'; wb_spiflash_is_map <= '0'; + wb_gpio_in <= wb_sio_out; + wb_gpio_in.cyc <= '0'; -- Only give xics 8 bits of wb addr (for now...) wb_xics_icp_in <= wb_sio_out; @@ -619,6 +638,9 @@ begin wb_spiflash_in.cyc <= wb_sio_out.cyc; wb_sio_in <= wb_spiflash_out; wb_spiflash_is_reg <= '1'; + when SLAVE_IO_GPIO => + wb_gpio_in.cyc <= wb_sio_out.cyc; + wb_sio_in <= wb_gpio_out; when others => end case; @@ -811,6 +833,21 @@ begin icp_out => ics_to_icp ); + gpio : entity work.gpio + generic map( + NGPIO => NGPIO + ) + port map( + clk => system_clk, + rst => rst_gpio, + wb_in => wb_gpio_in, + wb_out => wb_gpio_out, + gpio_in => gpio_in, + gpio_out => gpio_out, + gpio_dir => gpio_dir, + intr => gpio_intr + ); + -- Assign external interrupts interrupts: process(all) begin @@ -818,6 +855,7 @@ begin int_level_in(0) <= uart0_irq; int_level_in(1) <= ext_irq_eth; int_level_in(2) <= uart1_irq; + int_level_in(3) <= gpio_intr; end process; -- BRAM Memory slave