Add GPIO for Arty A7

Adds GPIO ports for all switches/leds/PMOD/ChipKit connectors
on the Arty A7

Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
pull/117/head
Alastair D'Silva 5 years ago
parent 9620a76281
commit 45f502112a

@ -55,7 +55,8 @@ simple_ram_behavioural_helpers.o:
simple_ram_behavioural_tb.o: wishbone_types.o simple_ram_behavioural.o
simple_ram_behavioural.o: wishbone_types.o simple_ram_behavioural_helpers.o
sim_uart.o: wishbone_types.o sim_console.o
soc.o: common.o wishbone_types.o core.o wishbone_arbiter.o sim_uart.o simple_ram_behavioural.o dmi_dtm_xilinx.o wishbone_debug_master.o
sim_gpio.o: wishbone_types.o sim_console.o
soc.o: common.o wishbone_types.o core.o wishbone_arbiter.o sim_uart.o sim_gpio.o simple_ram_behavioural.o dmi_dtm_xilinx.o wishbone_debug_master.o
wishbone_arbiter.o: wishbone_types.o
wishbone_types.o:
writeback.o: common.o crhelpers.o

@ -21,13 +21,17 @@ begin
SIM => true,
MEMORY_SIZE => 524288,
RAM_INIT_FILE => "simple_ram_behavioural.bin",
RESET_LOW => false
RESET_LOW => false,
GPIO0_PINS => 1,
GPIO1_PINS => 1
)
port map(
rst => rst,
system_clk => clk,
uart0_rxd => '0',
uart0_txd => open
uart0_txd => open,
gpio0 => open,
gpio1 => open
);

clk_process: process

@ -0,0 +1,82 @@
library ieee;
use ieee.std_logic_1164.all;

entity arty_a7 is
generic (
MEMORY_SIZE : positive := 524288;
RAM_INIT_FILE : string := "firmware.hex";
RESET_LOW : boolean := true;
CLK_INPUT : positive := 100000000;
CLK_FREQUENCY : positive := 100000000
);
port(
ext_clk : in std_ulogic;
ext_rst : in std_ulogic;

-- UART0 signals:
uart0_txd : out std_ulogic;
uart0_rxd : in std_ulogic;

-- GPIO signals:
gpio0 : inout std_logic_vector(55 downto 0);
gpio1 : inout std_logic_vector(36 downto 0)
);
end entity arty_a7;

architecture behaviour of arty_a7 is

-- Reset signals:
signal soc_rst : std_ulogic;
signal pll_rst : std_ulogic;

-- Internal clock signals:
signal system_clk : std_ulogic;
signal system_clk_locked : std_ulogic;

begin

reset_controller: entity work.soc_reset
generic map(
RESET_LOW => RESET_LOW
)
port map(
ext_clk => ext_clk,
pll_clk => system_clk,
pll_locked_in => system_clk_locked,
ext_rst_in => ext_rst,
pll_rst_out => pll_rst,
rst_out => soc_rst
);

clkgen: entity work.clock_generator
generic map(
CLK_INPUT_HZ => CLK_INPUT,
CLK_OUTPUT_HZ => CLK_FREQUENCY
)
port map(
ext_clk => ext_clk,
pll_rst_in => pll_rst,
pll_clk_out => system_clk,
pll_locked_out => system_clk_locked
);

-- Main SoC
soc0: entity work.soc
generic map(
MEMORY_SIZE => MEMORY_SIZE,
RAM_INIT_FILE => RAM_INIT_FILE,
RESET_LOW => RESET_LOW,
SIM => false,
GPIO0_PINS => 56,
GPIO1_PINS => 37
)
port map (
system_clk => system_clk,
rst => soc_rst,
uart0_txd => uart0_txd,
uart0_rxd => uart0_rxd,
gpio0 => gpio0,
gpio1 => gpio1
);

end architecture behaviour;

@ -6,5 +6,121 @@ set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { ext_rs
set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { uart0_txd }];
set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { uart0_rxd }];

# Buttons 0-3
set_property -dict { PACKAGE_PIN D9 IOSTANDARD LVCMOS33 } [get_ports { gpio0[0] }]; # BTN0
set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { gpio0[1] }]; # BTN1
set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { gpio0[2] }]; # BTN2
set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { gpio0[3] }]; # BTN3

# Slide switches 0-3
set_property -dict { PACKAGE_PIN A8 IOSTANDARD LVCMOS33 } [get_ports { gpio0[4] }]; # SW0
set_property -dict { PACKAGE_PIN C11 IOSTANDARD LVCMOS33 } [get_ports { gpio0[5] }]; # SW1
set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { gpio0[6] }]; # SW2
set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { gpio0[7] }]; # SW3

# RGB LEDs 0-3
set_property -dict { PACKAGE_PIN G6 IOSTANDARD LVCMOS33 } [get_ports { gpio0[8] }]; # LD0 Red
set_property -dict { PACKAGE_PIN F6 IOSTANDARD LVCMOS33 } [get_ports { gpio0[9] }]; # LD0 Green
set_property -dict { PACKAGE_PIN U1 IOSTANDARD LVCMOS33 } [get_ports { gpio0[10] }]; # LD0 Blue

set_property -dict { PACKAGE_PIN G3 IOSTANDARD LVCMOS33 } [get_ports { gpio0[11] }]; # LD1 Red
set_property -dict { PACKAGE_PIN J4 IOSTANDARD LVCMOS33 } [get_ports { gpio0[12] }]; # LD1 Green
set_property -dict { PACKAGE_PIN G4 IOSTANDARD LVCMOS33 } [get_ports { gpio0[13] }]; # LD1 Blue

set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { gpio0[14] }]; # LD2 Red
set_property -dict { PACKAGE_PIN J3 IOSTANDARD LVCMOS33 } [get_ports { gpio0[15] }]; # LD2 Green
set_property -dict { PACKAGE_PIN H4 IOSTANDARD LVCMOS33 } [get_ports { gpio0[16] }]; # LD2 Blue

set_property -dict { PACKAGE_PIN K1 IOSTANDARD LVCMOS33 } [get_ports { gpio0[17] }]; # LD3 Red
set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { gpio0[18] }]; # LD3 Green
set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { gpio0[19] }]; # LD3 Blue

# LEDs 4-7
set_property -dict { PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports { gpio0[20] }]; # LD4
set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports { gpio0[21] }]; # LD5
set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { gpio0[22] }]; # LD6
set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { gpio0[23] }]; # LD7

# PMOD JA
set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports { gpio0[24] }]; # PMOD JA Pin 1
set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 } [get_ports { gpio0[25] }]; # PMOD JA Pin 2
set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 } [get_ports { gpio0[26] }]; # PMOD JA Pin 3
set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 } [get_ports { gpio0[27] }]; # PMOD JA Pin 4
set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 } [get_ports { gpio0[28] }]; # PMOD JA Pin 7
set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 } [get_ports { gpio0[29] }]; # PMOD JA Pin 8
set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { gpio0[30] }]; # PMOD JA Pin 9
set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { gpio0[31] }]; # PMOD JA Pin 10

# PMOD JB
set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 } [get_ports { gpio0[32] }]; # PMOD JB Pin 1
set_property -dict { PACKAGE_PIN E16 IOSTANDARD LVCMOS33 } [get_ports { gpio0[33] }]; # PMOD JB Pin 2
set_property -dict { PACKAGE_PIN D15 IOSTANDARD LVCMOS33 } [get_ports { gpio0[34] }]; # PMOD JB Pin 3
set_property -dict { PACKAGE_PIN C15 IOSTANDARD LVCMOS33 } [get_ports { gpio0[35] }]; # PMOD JB Pin 4
set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { gpio0[36] }]; # PMOD JB Pin 7
set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { gpio0[37] }]; # PMOD JB Pin 8
set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { gpio0[38] }]; # PMOD JB Pin 9
set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { gpio0[39] }]; # PMOD JB Pin 10

# PMOD JC
set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { gpio0[40] }]; # PMOD JC Pin 1
set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { gpio0[41] }]; # PMOD JC Pin 2
set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 } [get_ports { gpio0[42] }]; # PMOD JC Pin 3
set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { gpio0[43] }]; # PMOD JC Pin 4
set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { gpio0[44] }]; # PMOD JC Pin 7
set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { gpio0[45] }]; # PMOD JC Pin 8
set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { gpio0[46] }]; # PMOD JC Pin 9
set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { gpio0[47] }]; # PMOD JC Pin 10

# PMOD JD
set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { gpio0[48] }]; # PMOD JD Pin 1
set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { gpio0[49] }]; # PMOD JD Pin 2
set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { gpio0[50] }]; # PMOD JD Pin 3
set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { gpio0[51] }]; # PMOD JD Pin 4
set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { gpio0[52] }]; # PMOD JD Pin 7
set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { gpio0[53] }]; # PMOD JD Pin 8
set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { gpio0[54] }]; # PMOD JD Pin 9
set_property -dict { PACKAGE_PIN G2 IOSTANDARD LVCMOS33 } [get_ports { gpio0[55] }]; # PMOD JD Pin 10

# Chipkit
set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { gpio1[0] }]; # Chipkit IO0
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { gpio1[1] }]; # Chipkit IO1
set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { gpio1[2] }]; # Chipkit IO2
set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { gpio1[3] }]; # Chipkit IO3
set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { gpio1[4] }]; # Chipkit IO4
set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { gpio1[5] }]; # Chipkit IO5
set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { gpio1[6] }]; # Chipkit IO6
set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { gpio1[7] }]; # Chipkit IO7
set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 } [get_ports { gpio1[8] }]; # Chipkit IO8
set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { gpio1[9] }]; # Chipkit IO9
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { gpio1[10] }]; # Chipkit IO10
set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { gpio1[11] }]; # Chipkit IO11
set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { gpio1[12] }]; # Chipkit IO12
set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 } [get_ports { gpio1[13] }]; # Chipkit IO13

set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { gpio1[14] }]; # Chipkit IO26
set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { gpio1[15] }]; # Chipkit IO27
set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { gpio1[16] }]; # Chipkit IO28
set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { gpio1[17] }]; # Chipkit IO29
set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { gpio1[18] }]; # Chipkit IO30
set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { gpio1[19] }]; # Chipkit IO31
set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { gpio1[20] }]; # Chipkit IO32
set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { gpio1[21] }]; # Chipkit IO33
set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { gpio1[22] }]; # Chipkit IO34
set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { gpio1[23] }]; # Chipkit IO35
set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { gpio1[24] }]; # Chipkit IO36
set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { gpio1[25] }]; # Chipkit IO37
set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { gpio1[26] }]; # Chipkit IO38
set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { gpio1[27] }]; # Chipkit IO39
set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { gpio1[28] }]; # Chipkit IO40
set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports { gpio1[29] }]; # Chipkit IO41
set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 } [get_ports { gpio1[30] }]; # Chipkit IO42

set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { gpio1[31] }]; # Chipkit I2C SCL
set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 } [get_ports { gpio1[32] }]; # Chipkit I2C SDA
set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { gpio1[33] }]; # Chipkit SPI SS
set_property -dict { PACKAGE_PIN F1 IOSTANDARD LVCMOS33 } [get_ports { gpio1[34] }]; # Chipkit SPI CLK
set_property -dict { PACKAGE_PIN H1 IOSTANDARD LVCMOS33 } [get_ports { gpio1[35] }]; # Chipkit SPI MOSI
set_property -dict { PACKAGE_PIN G1 IOSTANDARD LVCMOS33 } [get_ports { gpio1[36] }]; # Chipkit SPI MISO

set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property CFGBVS VCCO [current_design]

@ -0,0 +1,200 @@
-- Sim GPIO, based on potato GPIO by
-- Kristian Klomsten Skordal.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.sim_console.all;


--! @brief Generic Wishbone GPIO Module.
--!
--! The following registers are defined:
--! |---------|------------------------------------------------------------------|
--! | Address | Description |
--! |---------|------------------------------------------------------------------|
--! | 0x00 | Describes the port: (read-only) |
--! | | bits 0-5: The number of pins |
--! | 0x08 | Input values, one bit per pin (read/write), |
--! | | If the pin is set to output, writing 1 will toggle the pin |
--! | 0x10 | Output values, one bit per pin (read/write) |
--! | 0x18 | Set register, Output = Output | set register (write-only) |
--! | 0x20 | Clear register, Output = Output & ~(clear register) (write-only) |
--! | 0x28 | Type, 4 bits per pin (read/write), pins 0-15 |
--! | 0x30 | Type, 4 bits per pin (read/write), pins 16-31 |
--! | 0x38 | Type, 4 bits per pin (read/write), pins 32-47 |
--! | 0x40 | Type, 4 bits per pin (read/write), pins 48-63 |
--! | | Types: MSB LSB |
--! | | 0 0 0 0 Input, Interrupt disabled |
--! | | 0 0 1 0 Input, Interrupt when low |
--! | | 0 0 1 1 Input, Interrupt when high |
--! | | 0 1 0 0 Input, Interrupt when falling |
--! | | 0 1 0 1 Input, Interrupt when rising |
--! | | 0 1 1 1 Output |
--! | | others Undefined |
--! | 0x48 | Interrupt Triggered, one bit per pin (read/write) |
--! |---------|------------------------------------------------------------------|
--!
--! Writes to the output register for input pins are ignored.
entity pp_soc_gpio is
generic(
NUM_GPIOS : natural := 64
);
port(
clk : in std_logic;
reset : in std_logic;
irq : out std_logic;

-- GPIO interface:
gpio : inout std_logic_vector(NUM_GPIOS - 1 downto 0);

-- Wishbone interface:
wb_adr_in : in std_logic_vector(7 downto 0);
wb_dat_in : in std_logic_vector(63 downto 0);
wb_dat_out : out std_logic_vector(63 downto 0);
wb_cyc_in : in std_logic;
wb_stb_in : in std_logic;
wb_we_in : in std_logic;
wb_ack_out : out std_logic
);
end entity pp_soc_gpio;

architecture behaviour of pp_soc_gpio is

type type_array is array (natural range 0 to NUM_GPIOS - 1) of
std_logic_vector(3 downto 0);

signal input_buffer : std_logic_vector(NUM_GPIOS - 1 downto 0);
signal input_register_prev : std_logic_vector(NUM_GPIOS - 1 downto 0);
signal input_register : std_logic_vector(NUM_GPIOS - 1 downto 0);
signal output_register : std_logic_vector(NUM_GPIOS - 1 downto 0);
signal type_register : type_array;
signal irq_triggered_register : std_logic_vector(NUM_GPIOS - 1 downto 0);

signal ack : std_logic := '0';

begin

assert NUM_GPIOS > 0 and NUM_GPIOS <= 64
report "Only a number between 1 and 64 (inclusive) GPIOs are supported!"
severity FAILURE;

wb_ack_out <= ack and wb_cyc_in and wb_stb_in;

wishbone: process(clk)
begin
if rising_edge(clk) then
for i in 0 to NUM_GPIOS - 1 loop
gpio(i) <= output_register(i) when type_register(i) = b"0111" else 'Z';
input_register_prev(i) <= input_register(i);
input_register(i) <= input_buffer(i);
input_buffer(i) <= gpio(i) when type_register(i) /= b"0111";

case type_register(i) is
when b"0010" =>
if gpio(i) = '0' then
irq_triggered_register(i) <= '1';
irq <= '1';
end if;
when b"0011" =>
if gpio(i) = '1' then
irq_triggered_register(i) <= '1';
irq <= '1';
end if;
when b"0100" =>
if input_register(i) = '0' and input_register_prev(i) = '1' then
irq_triggered_register(i) <= '1';
irq <= '1';
end if;
when b"0101" =>
if input_register(i) = '1' and input_register_prev(i) = '0' then
irq_triggered_register(i) <= '1';
irq <= '1';
end if;
when others =>
end case;
end loop;

if reset = '1' then
input_register <= (others => '0');
output_register <= (others => '0');
wb_dat_out <= (others => '0');
for i in 0 to NUM_GPIOS - 1 loop
type_register(i) <= (others => '0');
end loop;
irq_triggered_register <= (others => '0');
ack <= '0';
else
if wb_cyc_in = '1' and wb_stb_in = '1' and ack = '0' then
if wb_we_in = '1' then
case wb_adr_in is
when x"08" => --! Input Value
output_register <= output_register xor wb_dat_in(NUM_GPIOS - 1 downto 0);
when x"10" => --! Output Value
output_register <= wb_dat_in(NUM_GPIOS - 1 downto 0);
when x"18" => --! Set
output_register <= output_register OR wb_dat_in(NUM_GPIOS - 1 downto 0);
when x"20" => --! Clear
output_register <= output_register AND NOT(wb_dat_in(NUM_GPIOS - 1 downto 0));
when x"28" => --! Type Pins 0-15
for i in 0 to MINIMUM(NUM_GPIOS - 1, 15) loop
type_register(i) <= (wb_dat_in((i + 1) * 4 - 1 downto i * 4));
end loop;
when x"30" => --! Type Pins 16-31
for i in 16 to MINIMUM(NUM_GPIOS - 1, 31) loop
type_register(i) <= (wb_dat_in((i - 16 + 1) * 4 - 1 downto (i - 16) * 4));
end loop;
when x"38" => --! Type Pins 32-47
for i in 32 to MINIMUM(NUM_GPIOS - 1, 47) loop
type_register(i) <= (wb_dat_in((i - 32 + 1) * 4 - 1 downto (i - 32) * 4));
end loop;
when x"40" => --! Type Pins 48-63
for i in 48 to MINIMUM(NUM_GPIOS - 1, 63) loop
type_register(i) <= (wb_dat_in((i - 48 + 1) * 4 - 1 downto (i - 48) * 4));
end loop;
when others =>
end case;
ack <= '1';
else
case wb_adr_in is
when x"00" => --! Description
wb_dat_out <= std_logic_vector(to_unsigned(NUM_GPIOS, wb_dat_out'length));
when x"08" => --! Input Value
wb_dat_out <= std_logic_vector(resize(unsigned(input_register), wb_dat_out'length));
when x"10" => --! Output value
wb_dat_out <= std_logic_vector(resize(unsigned(output_register), wb_dat_out'length));
when x"28" => --! Type Pins 0-15
for i in 0 to MINIMUM(NUM_GPIOS - 1, 15) loop
wb_dat_out((i + 1) * 4 - 1 downto i * 4) <= type_register(i);
end loop;
when x"30" => --! Type Pins 16-31
for i in 21 to MINIMUM(NUM_GPIOS - 1, 31) loop
wb_dat_out((i - 16 + 1) * 4 - 1 downto (i - 16) * 4) <= type_register(i);
end loop;
when x"38" => --! Type Pins 32-47
for i in 32 to MINIMUM(NUM_GPIOS - 1, 47) loop
wb_dat_out((i - 32 + 1) * 4 - 1 downto (i - 32) * 4) <= type_register(i);
end loop;
when x"40" => --! Type Pins 32-47
for i in 32 to MINIMUM(NUM_GPIOS - 1, 47) loop
wb_dat_out((i - 32 + 1) * 4 - 1 downto (i - 32) * 4) <= type_register(i);
end loop;
when x"48" => --! Interrupts triggered
wb_dat_out <= std_logic_vector(resize(unsigned(irq_triggered_register), wb_dat_out'length));
irq_triggered_register <= (others => '0');
irq <= '0';
when others =>
end case;
report "ack";
ack <= '1';
end if;
elsif wb_stb_in = '0' then
ack <= '0';
end if;
end if;
end if;
end process wishbone;

end architecture behaviour;

@ -1,7 +1,7 @@
library ieee;
use ieee.std_logic_1164.all;

entity toplevel is
entity toplevel_nogpio is
generic (
MEMORY_SIZE : positive := 524288;
RAM_INIT_FILE : string := "firmware.hex";
@ -17,9 +17,9 @@ entity toplevel is
uart0_txd : out std_ulogic;
uart0_rxd : in std_ulogic
);
end entity toplevel;
end entity toplevel_nogpio;

architecture behaviour of toplevel is
architecture behaviour of toplevel_nogpio is

-- Reset signals:
signal soc_rst : std_ulogic;
@ -62,7 +62,9 @@ begin
MEMORY_SIZE => MEMORY_SIZE,
RAM_INIT_FILE => RAM_INIT_FILE,
RESET_LOW => RESET_LOW,
SIM => false
SIM => false,
GPIO0_PINS => 0,
GPIO1_PINS => 0
)
port map (
system_clk => system_clk,

@ -51,11 +51,25 @@ filesets:
- fpga/mw_soc_memory.vhdl
- fpga/soc_reset.vhdl
- fpga/pp_soc_uart.vhd
- fpga/pp_soc_gpio.vhdl
- fpga/pp_utilities.vhd
- fpga/toplevel.vhdl
- fpga/firmware.hex : {copyto : firmware.hex, file_type : user}
file_type : vhdlSource-2008

fpga:
files:
- fpga/pp_fifo.vhd
- fpga/mw_soc_memory.vhdl
- fpga/soc_reset.vhdl
- fpga/pp_soc_uart.vhd
- fpga/pp_soc_gpio.vhdl
- fpga/pp_utilities.vhd
- fpga/toplevel_nogpio.vhdl
- fpga/arty_a7.vhdl
- fpga/firmware.hex : {copyto : firmware.hex, file_type : user}
file_type : vhdlSource-2008

debug_xilinx:
files:
- dmi_dtm_xilinx.vhdl : {file_type : vhdlSource-2008}
@ -95,7 +109,7 @@ targets:
- clk_frequency
tools:
vivado: {part : xc7a100tcsg324-1}
toplevel : toplevel
toplevel : toplevel_nogpio

nexys_video:
default_tool: vivado
@ -107,7 +121,7 @@ targets:
- clk_frequency
tools:
vivado: {part : xc7a200tsbg484-1}
toplevel : toplevel
toplevel : toplevel_nogpio

arty_a7-35:
default_tool: vivado
@ -119,7 +133,7 @@ targets:
- clk_frequency
tools:
vivado: {part : xc7a35ticsg324-1L}
toplevel : toplevel
toplevel : arty_a7

arty_a7-100:
default_tool: vivado
@ -131,7 +145,7 @@ targets:
- clk_frequency
tools:
vivado: {part : xc7a100ticsg324-1L}
toplevel : toplevel
toplevel : arty_a7

cmod_a7-35:
default_tool: vivado
@ -144,7 +158,7 @@ targets:
- clk_frequency
tools:
vivado: {part : xc7a35tcpg236-1}
toplevel : toplevel
toplevel : toplevel_nogpio

synth:
filesets: [core, soc]

@ -0,0 +1,205 @@
-- Sim GPIO, based on potato GPIO by
-- Kristian Klomsten Skordal.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library work;
use work.sim_console.all;


--! @brief Generic Wishbone GPIO Module.
--!
--! The following registers are defined:
--! |---------|------------------------------------------------------------------|
--! | Address | Description |
--! |---------|------------------------------------------------------------------|
--! | 0x00 | Describes the port: (read-only) |
--! | | bits 0-5: The number of pins |
--! | 0x08 | Input values, one bit per pin (read/write), |
--! | | If the pin is set to output, writing 1 will toggle the pin |
--! | 0x10 | Output values, one bit per pin (read/write) |
--! | 0x18 | Set register, Output = Output | set register (write-only) |
--! | 0x20 | Clear register, Output = Output & ~(clear register) (write-only) |
--! | 0x28 | Type, three bits per pin (read/write), pins 0-20 |
--! | 0x30 | Type, three bits per pin (read/write), pins 21-41 |
--! | 0x38 | Type, three bits per pin (read/write), pins 42-63 |
--! | | Types: MSB LSB |
--! | | 0 0 0 Input, Interrupt disabled |
--! | | 0 1 0 Input, Interrupt when low |
--! | | 0 1 1 Input, Interrupt when high |
--! | | 1 0 0 Input, Interrupt when falling |
--! | | 1 0 1 Input, Interrupt when rising |
--! | | 1 1 1 Output |
--! | | others Undefined |
--! | 0x40 | Interrupt Triggered, one bit per pin (read/write) |
--! |---------|------------------------------------------------------------------|
--!
--! Writes to the output register for input pins are ignored.
entity pp_soc_gpio is
generic(
NUM_GPIOS : natural := 64
);
port(
clk : in std_logic;
reset : in std_logic;
irq : out std_logic;

-- GPIO interface:
gpio : inout std_logic_vector(NUM_GPIOS - 1 downto 0);

-- Wishbone interface:
wb_adr_in : in std_logic_vector(7 downto 0);
wb_dat_in : in std_logic_vector(63 downto 0);
wb_dat_out : out std_logic_vector(63 downto 0);
wb_cyc_in : in std_logic;
wb_stb_in : in std_logic;
wb_we_in : in std_logic;
wb_ack_out : out std_logic
);
end entity pp_soc_gpio;

architecture behaviour of pp_soc_gpio is

type type_array is array (natural range 0 to NUM_GPIOS - 1) of
std_logic_vector(2 downto 0);

signal input_buffer : std_logic_vector(NUM_GPIOS - 1 downto 0);
signal input_register_prev : std_logic_vector(NUM_GPIOS - 1 downto 0);
signal input_register : std_logic_vector(NUM_GPIOS - 1 downto 0);
signal output_register : std_logic_vector(NUM_GPIOS - 1 downto 0);
signal type_register : type_array;
signal irq_triggered_register : std_logic_vector(NUM_GPIOS - 1 downto 0);

signal ack : std_logic := '0';

begin

assert NUM_GPIOS >= 0 and NUM_GPIOS <= 64
report "Only a number between 0 and 64 (inclusive) GPIOs are supported!"
severity FAILURE;

wb_ack_out <= ack and wb_cyc_in and wb_stb_in;

wishbone: process(clk)
begin
if rising_edge(clk) then
for i in 0 to NUM_GPIOS - 1 loop
gpio(i) <= output_register(i) when type_register(i) = b"111" else 'Z';
input_register_prev(i) <= input_register(i);
input_register(i) <= input_buffer(i);
input_buffer(i) <= gpio(i) when type_register(i) /= b"111";

case type_register(i) is
when b"010" =>
if gpio(i) = '0' then
irq_triggered_register(i) <= '1';
irq <= '1';
end if;
when b"011" =>
if gpio(i) = '1' then
irq_triggered_register(i) <= '1';
irq <= '1';
end if;
when b"100" =>
if input_register(i) = '0' and input_register_prev(i) = '1' then
irq_triggered_register(i) <= '1';
irq <= '1';
end if;
when b"101" =>
if input_register(i) = '1' and input_register_prev(i) = '0' then
irq_triggered_register(i) <= '1';
irq <= '1';
end if;
when others =>
end case;
end loop;

if reset = '1' then
input_register <= (others => '0');
output_register <= (others => '0');
wb_dat_out <= (others => '0');
for i in 0 to NUM_GPIOS - 1 loop
type_register(i) <= (others => '0');
end loop;
irq_triggered_register <= (others => '0');
ack <= '0';
else
if wb_cyc_in = '1' and wb_stb_in = '1' and ack = '0' then
if wb_we_in = '1' then
case wb_adr_in is
when x"08" => --! Input Value
output_register <= output_register xor wb_dat_in(NUM_GPIOS - 1 downto 0);
report "GPIO output " & to_hstring(output_register);
when x"10" => --! Output Value
output_register <= wb_dat_in(NUM_GPIOS - 1 downto 0);
report "GPIO output " & to_hstring(output_register);
when x"18" => --! Set
output_register <= output_register OR wb_dat_in(NUM_GPIOS - 1 downto 0);
report "GPIO output " & to_hstring(output_register);
when x"20" => --! Clear
output_register <= output_register AND NOT(wb_dat_in(NUM_GPIOS - 1 downto 0));
report "GPIO output " & to_hstring(output_register);
when x"28" => --! Type Pins 0-20
for i in 0 to MINIMUM(NUM_GPIOS - 1, 20) loop
type_register(i) <= (wb_dat_in((i + 1) * 3 - 1 downto i * 3));
report "GPIO type for pin " & integer'image(i) & " is " & to_hstring((wb_dat_in((i + 1) * 3 - 1 downto i * 3)));
end loop;
when x"30" => --! Type Pins 21-41
for i in 21 to MINIMUM(NUM_GPIOS - 1, 41) loop
type_register(i) <= (wb_dat_in((i - 21 + 1) * 3 - 1 downto (i - 21) * 3));
report "GPIO type for pin " & integer'image(i) & " is " & to_hstring((wb_dat_in((i - 21 + 1) * 3 - 1 downto (i- 21) * 3)));
end loop;
when x"38" => --! Type Pins 42-63
for i in 42 to MINIMUM(NUM_GPIOS - 1, 63) loop
type_register(i) <= (wb_dat_in((i - 42 + 1) * 3 - 1 downto (i - 42) * 3));
report "GPIO type for pin " & integer'image(i) & " is " & to_hstring((wb_dat_in((i - 42 + 1) * 3 - 1 downto (i- 21) * 3)));
end loop;
when others =>
end case;
ack <= '1';
else
case wb_adr_in is
when x"00" => --! Description
wb_dat_out <= std_logic_vector(to_unsigned(NUM_GPIOS, wb_dat_out'length));
report "Read GPIO Description register as " & to_hstring(wb_dat_out);
when x"08" => --! Input Value
wb_dat_out <= std_logic_vector(resize(unsigned(input_register), wb_dat_out'length));
report "Read GPIO Input value as " & to_hstring(wb_dat_out);
when x"10" => --! Output value
wb_dat_out <= std_logic_vector(resize(unsigned(output_register), wb_dat_out'length));
report "Read GPIO Output register as " & to_hstring(wb_dat_out);
when x"28" => --! Type Pins 0-20
for i in 0 to MINIMUM(NUM_GPIOS - 1, 20) loop
wb_dat_out((i + 1) * 3 - 1 downto i * 3) <= type_register(i);
end loop;
report "Read GPIO Type register 0 as " & to_hstring(wb_dat_out);
when x"30" => --! Type Pins 21-41
for i in 21 to MINIMUM(NUM_GPIOS - 1, 41) loop
wb_dat_out((i - 21 + 1) * 3 - 1 downto (i - 21) * 3) <= type_register(i);
end loop;
report "Read GPIO Type register 1 as " & to_hstring(wb_dat_out);
when x"38" => --! Type Pins 42-63
for i in 21 to MINIMUM(NUM_GPIOS - 1, 41) loop
wb_dat_out((i - 21 + 1) * 3 - 1 downto (i - 21) * 3) <= type_register(i);
end loop;
report "Read GPIO Type register 2 as " & to_hstring(wb_dat_out);
when x"40" => --! Interrupts triggered
wb_dat_out <= std_logic_vector(resize(unsigned(irq_triggered_register), wb_dat_out'length));
irq_triggered_register <= (others => '0');
irq <= '0';
report "Read IRQ Triggered register as " & to_hstring(wb_dat_out);
when others =>
end case;
report "ack";
ack <= '1';
end if;
elsif wb_stb_in = '0' then
ack <= '0';
end if;
end if;
end if;
end process wishbone;

end architecture behaviour;

@ -17,7 +17,9 @@ entity soc is
MEMORY_SIZE : positive;
RAM_INIT_FILE : string;
RESET_LOW : boolean;
SIM : boolean
SIM : boolean;
GPIO0_PINS : natural;
GPIO1_PINS : natural
);
port(
rst : in std_ulogic;
@ -28,6 +30,8 @@ entity soc is
uart0_rxd : in std_ulogic;

-- Misc (to use for things like LEDs)
gpio0 : inout std_logic_vector(GPIO0_PINS - 1 downto 0);
gpio1 : inout std_logic_vector(GPIO1_PINS - 1 downto 0);
core_terminated : out std_ulogic
);
end entity soc;
@ -51,6 +55,14 @@ architecture behaviour of soc is
signal wb_uart0_out : wishbone_slave_out;
signal uart_dat8 : std_ulogic_vector(7 downto 0);

-- GPIO0 signals:
signal wb_gpio0_in : wishbone_master_out;
signal wb_gpio0_out : wishbone_slave_out;

-- GPIO1 signals:
signal wb_gpio1_in : wishbone_master_out;
signal wb_gpio1_out : wishbone_slave_out;

-- Main memory signals:
signal wb_bram_in : wishbone_master_out;
signal wb_bram_out : wishbone_slave_out;
@ -104,28 +116,46 @@ begin
);

-- Wishbone slaves address decoder & mux
slave_intercon: process(wb_master_out, wb_bram_out, wb_uart0_out)
slave_intercon: process(wb_master_out, wb_bram_out, wb_uart0_out, wb_gpio0_out, wb_gpio1_out)
-- Selected slave
type slave_type is (SLAVE_UART_0,
SLAVE_GPIO_0,
SLAVE_GPIO_1,
SLAVE_MEMORY,
SLAVE_NONE);
variable slave : slave_type;
begin
-- Simple address decoder.
slave := SLAVE_NONE;
if wb_master_out.adr(31 downto 24) = x"00" then
-- Simple address decoder
case wb_master_out.adr(31 downto 24) is
when x"00" =>
slave := SLAVE_MEMORY;
elsif wb_master_out.adr(31 downto 24) = x"c0" then
if wb_master_out.adr(23 downto 12) = x"002" then
when x"c0" =>
case wb_master_out.adr(23 downto 8) is
when x"0020" =>
slave := SLAVE_UART_0;
end if;
end if;
when others =>
slave := SLAVE_NONE;
end case;
when x"c1" =>
case wb_master_out.adr(23 downto 8) is
when x"0000" =>
slave := SLAVE_GPIO_0;
when x"0001" =>
slave := SLAVE_GPIO_1;
when others =>
slave := SLAVE_NONE;
end case;
when others =>
slave := SLAVE_NONE;
end case;

-- Wishbone muxing. Defaults:
wb_bram_in <= wb_master_out;
wb_bram_in.cyc <= '0';
wb_uart0_in <= wb_master_out;
wb_uart0_in.cyc <= '0';
wb_gpio0_in <= wb_master_out;
wb_gpio0_in.cyc <= '0';
case slave is
when SLAVE_MEMORY =>
wb_bram_in.cyc <= wb_master_out.cyc;
@ -133,6 +163,12 @@ begin
when SLAVE_UART_0 =>
wb_uart0_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_uart0_out;
when SLAVE_GPIO_0 =>
wb_gpio0_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_gpio0_out;
when SLAVE_GPIO_1 =>
wb_gpio1_in.cyc <= wb_master_out.cyc;
wb_master_in <= wb_gpio1_out;
when others =>
wb_master_in.dat <= (others => '1');
wb_master_in.ack <= wb_master_out.stb and wb_master_out.cyc;
@ -165,6 +201,41 @@ begin
);
wb_uart0_out.dat <= x"00000000000000" & uart_dat8;

-- GPIO
gpio_0: entity work.pp_soc_gpio
generic map(
NUM_GPIOS => GPIO0_PINS
)
port map(
clk => system_clk,
reset => rst,
gpio => gpio0,
wb_adr_in => wb_gpio0_in.adr(7 downto 0),
wb_dat_in => wb_gpio0_in.dat(63 downto 0),
wb_dat_out => wb_gpio0_out.dat,
wb_cyc_in => wb_gpio0_in.cyc,
wb_stb_in => wb_gpio0_in.stb,
wb_we_in => wb_gpio0_in.we,
wb_ack_out => wb_gpio0_out.ack
);

gpio_1: entity work.pp_soc_gpio
generic map(
NUM_GPIOS => GPIO1_PINS
)
port map(
clk => system_clk,
reset => rst,
gpio => gpio1,
wb_adr_in => wb_gpio1_in.adr(7 downto 0),
wb_dat_in => wb_gpio1_in.dat(63 downto 0),
wb_dat_out => wb_gpio1_out.dat,
wb_cyc_in => wb_gpio1_in.cyc,
wb_stb_in => wb_gpio1_in.stb,
wb_we_in => wb_gpio1_in.we,
wb_ack_out => wb_gpio1_out.ack
);

-- BRAM Memory slave
bram0: entity work.mw_soc_memory
generic map(

Loading…
Cancel
Save