-
Notifications
You must be signed in to change notification settings - Fork 0
/
buttons_controller.vhd
95 lines (83 loc) · 2.93 KB
/
buttons_controller.vhd
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
--
-- Physical buttons controller
-- An Avalon slave to interface with human interactions through buttons and switches
--
-- file: buttons_controller.vhd
-- author: Alexandre CHAU & Loïc DROZ
-- date: 11/06/2020
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity buttons_controller is
port (
clk : in std_logic;
reset_n : in std_logic;
-- Avalon slave
as_address : in std_logic_vector(1 downto 0);
as_read : in std_logic;
as_readdata : out std_logic_vector(31 downto 0);
as_write : in std_logic;
as_writedata : in std_logic_vector(31 downto 0);
-- Interrupt line
irq : out std_logic;
-- Lines to physical buttons
switch : in std_logic_vector(9 downto 0);
buttons : in std_logic_vector(2 downto 0)
);
end entity buttons_controller;
architecture rtl of buttons_controller is
-- register map
constant REG_STATUS_OFFSET : std_logic_vector(as_address'length - 1 downto 0) := "00";
constant REG_IRQ_OFFSET : std_logic_vector(as_address'length - 1 downto 0) := "01";
-- internal registers
signal reg_status : std_logic_vector(switch'length + buttons'length - 1 downto 0);
signal reg_irq : std_logic;
-- falling edges dectectors
signal prevs : std_logic_vector(buttons'length - 1 downto 0);
signal currs : std_logic_vector(buttons'length - 1 downto 0);
begin
-- Assign IRQ line
irq <= reg_irq;
-- Avalon read process
as_read_process : process (clk, reset_n)
begin
if rising_edge(clk) then
if as_read = '1' then
case as_address is
when REG_STATUS_OFFSET => as_readdata <= (31 downto reg_status'length => '0') & reg_status;
when others => null;
end case;
end if;
end if;
end process as_read_process;
-- Avalon write process
as_write_process : process (clk, reset_n)
begin
if reset_n = '0' then
reg_status <= (others => '0');
reg_irq <= '0';
prevs <= (others => '0');
currs <= (others => '0');
elsif rising_edge(clk) then
if as_write = '1' then
case as_address is
when REG_IRQ_OFFSET =>
reg_irq <= '0';
when others =>
null;
end case;
else
-- detect button presses
for i in 0 to (buttons'length - 1) loop
currs(i) <= buttons(i);
prevs(i) <= currs(i);
if prevs(i) = '1' and currs(i) = '0' then
reg_irq <= '1';
reg_status <= switch & buttons;
end if;
end loop;
end if;
end if;
end process as_write_process;
end architecture rtl;