mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-03-03 01:57:45 +00:00
This makes the 64-bit wishbone buses have the address expressed in units of doublewords (64 bits), and similarly for the 32-bit buses the address is in units of words (32 bits). This is to comply with the wishbone spec. Previously the addresses on the wishbone buses were in units of bytes regardless of the bus data width, which is not correct and caused problems with interfacing with externally-generated logic. Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
100 lines
3.4 KiB
VHDL
100 lines
3.4 KiB
VHDL
-- 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 0) 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 0) 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;
|
|
|