forked from antonblanchard/microwatt
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgpio.vhdl
More file actions
99 lines (83 loc) · 3.32 KB
/
gpio.vhdl
File metadata and controls
99 lines (83 loc) · 3.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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);
signal reg_dirn : std_ulogic_vector(NGPIO - 1 downto 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;