-
Notifications
You must be signed in to change notification settings - Fork 0
/
TIMER.vhd
184 lines (160 loc) · 6.41 KB
/
TIMER.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
-- ######################################################
-- # < STORM SoC by Stephan Nolting > #
-- # ************************************************** #
-- # Multi purpose timer #
-- # ************************************************** #
-- # Last modified 01.03.2012 #
-- ######################################################
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity TIMER is
port (
-- Wishbone Bus --
WB_CLK_I : in STD_LOGIC; -- memory master clock
WB_RST_I : in STD_LOGIC; -- high active sync reset
WB_CTI_I : in STD_LOGIC_VECTOR(02 downto 0); -- cycle indentifier
WB_TGC_I : in STD_LOGIC_VECTOR(06 downto 0); -- cycle tag
WB_ADR_I : in STD_LOGIC_VECTOR(01 downto 0); -- adr in
WB_DATA_I : in STD_LOGIC_VECTOR(31 downto 0); -- write data
WB_DATA_O : out STD_LOGIC_VECTOR(31 downto 0); -- read data
WB_SEL_I : in STD_LOGIC_VECTOR(03 downto 0); -- data quantity
WB_WE_I : in STD_LOGIC; -- write enable
WB_STB_I : in STD_LOGIC; -- valid cycle
WB_ACK_O : out STD_LOGIC; -- acknowledge
WB_HALT_O : out STD_LOGIC; -- throttle master
WB_ERR_O : out STD_LOGIC; -- abnormal termination
-- Overflow Interrupt --
INT_O : out STD_LOGIC
);
end TIMER;
architecture Structure of TIMER is
-- Internal Registers --
signal COUNT_REG : STD_LOGIC_VECTOR(31 downto 0);
signal VALUE_REG : STD_LOGIC_VECTOR(31 downto 0);
signal CONFIG_REG : STD_LOGIC_VECTOR(31 downto 0);
signal SCRATCH_REG : STD_LOGIC_VECTOR(31 downto 0);
signal PRSC_REG : STD_LOGIC_VECTOR(15 downto 0);
signal WB_ACK_O_INT : STD_LOGIC;
-- Memory Map (word boundary!!!) --
-----------------------------------
-- ADR_I = 00 : COUNT register
-- ADR_I = 01 : VALUE register
-- ADR_I = 10 : Control register
-- ADR_I = 11 : Scratch register
-- Config Register --
constant TIMER_EN : natural := 0; -- timer enable
constant AUTO_RST : natural := 1; -- auto reset
constant INT_EN : natural := 2; -- interrupt enable
constant PRSC_LSB : natural := 16; -- prescaler LSB
constant PRSC_MSB : natural := 31; -- prescaler MSB
begin
-- Timer sync config -----------------------------------------------------------------------------------
-- --------------------------------------------------------------------------------------------------------
TIMER_SYNC: process(WB_CLK_I)
begin
if rising_edge(WB_CLK_I) then
if (WB_RST_I = '1') then
COUNT_REG <= (others => '0');
VALUE_REG <= (others => '0');
CONFIG_REG <= (others => '0');
SCRATCH_REG <= (others => '0');
PRSC_REG <= (others => '0');
else
-- WB write access --
if (WB_STB_I = '1') and (WB_WE_I = '1')then
case (WB_ADR_I) is
when "00" => -- Counter register
for i in 0 to 3 loop
if (WB_SEL_I(i) = '1') then
COUNT_REG(8*i+7 downto 8*i) <= WB_DATA_I(8*i+7 downto 8*i);
end if;
end loop;
when "01" => -- Threshold register
for i in 0 to 3 loop
if (WB_SEL_I(i) = '1') then
VALUE_REG(8*i+7 downto 8*i) <= WB_DATA_I(8*i+7 downto 8*i);
end if;
end loop;
when "10" => -- Config register
for i in 0 to 3 loop
if (WB_SEL_I(i) = '1') then
CONFIG_REG(8*i+7 downto 8*i) <= WB_DATA_I(8*i+7 downto 8*i);
end if;
end loop;
when others => -- Scratch register
for i in 0 to 3 loop
if (WB_SEL_I(i) = '1') then
SCRATCH_REG(8*i+7 downto 8*i) <= WB_DATA_I(8*i+7 downto 8*i);
end if;
end loop;
end case;
end if;
-- Counter increment --
if (VALUE_REG /= x"00000000") and (COUNT_REG = VALUE_REG) and (CONFIG_REG(AUTO_RST) = '1') then
COUNT_REG <= (others => '0');
elsif (VALUE_REG /= x"00000000") and (COUNT_REG /= VALUE_REG) and (CONFIG_REG(TIMER_EN) = '1') and (PRSC_REG = CONFIG_REG(PRSC_MSB downto PRSC_LSB)) then
COUNT_REG <= STD_LOGIC_VECTOR(unsigned(COUNT_REG) + 1);
end if;
-- Prescaler increment --
if (PRSC_REG = CONFIG_REG(PRSC_MSB downto PRSC_LSB)) then
PRSC_REG <= (others => '0');
elsif (VALUE_REG /= x"00000000") and (CONFIG_REG(TIMER_EN) = '1') then
PRSC_REG <= STD_LOGIC_VECTOR(unsigned(PRSC_REG) + 1);
end if;
end if;
end if;
end process TIMER_SYNC;
-- Interrupt Generator ---------------------------------------------------------------------------------
-- --------------------------------------------------------------------------------------------------------
INT_TOGGLE: process(WB_CLK_I)
begin
if rising_edge(WB_CLK_I) then
if (WB_RST_I = '1') then
INT_O <= '0';
elsif (COUNT_REG = VALUE_REG) and (CONFIG_REG(TIMER_EN) = '1') and (CONFIG_REG(INT_EN) = '1') then
INT_O <= '1';
else
INT_O <= '0';
end if;
end if;
end process INT_TOGGLE;
-- Wishbone Output Interface ---------------------------------------------------------------------------
-- --------------------------------------------------------------------------------------------------------
WB_R_ACCESS: process(WB_CLK_I)
begin
--- Sync Write ---
if rising_edge(WB_CLK_I) then
if (WB_RST_I = '1') then
WB_DATA_O <= (others => '0');
WB_ACK_O_INT <= '0';
else
if (WB_STB_I = '1') and (WB_WE_I = '0') then -- valid read request
case (WB_ADR_I) is
when "00" => -- Counter regitser
WB_DATA_O <= COUNT_REG;
when "01" => -- Threshold register
WB_DATA_O <= VALUE_REG;
when "10" => -- Configuration register
WB_DATA_O <= CONFIG_REG;
when others => -- Scratch register
WB_DATA_O <= SCRATCH_REG;
end case;
else
WB_DATA_O <= (others => '0');
end if;
if (WB_CTI_I = "000") or (WB_CTI_I = "111") then
WB_ACK_O_INT <= WB_STB_I and (not WB_ACK_O_INT);
else
WB_ACK_O_INT <= WB_STB_I; -- data is valid one cycle later
end if;
end if;
end if;
end process WB_R_ACCESS;
--- ACK Signal ---
WB_ACK_O <= WB_ACK_O_INT;
--- Throttle ---
WB_HALT_O <= '0'; -- yeay, we're at full speed!
--- Error ---
WB_ERR_O <= '0'; -- nothing can go wrong ;)
end Structure;