1 |
3 |
uson |
-- --========================================================================--
|
2 |
|
|
--
|
3 |
|
|
-- CoreAHB2APB
|
4 |
|
|
--
|
5 |
|
|
-- ----------------------------------------------------------------------------
|
6 |
|
|
-- Purpose : Converts AHB peripheral transfers to APB transfers
|
7 |
|
|
-- --========================================================================--
|
8 |
|
|
|
9 |
|
|
library ieee;
|
10 |
|
|
use ieee.std_logic_1164.all;
|
11 |
|
|
|
12 |
|
|
entity CoreAHB2APB is
|
13 |
|
|
port(
|
14 |
|
|
-- Global signals ----------------------------------------------------------
|
15 |
|
|
HCLK : in std_logic; -- AHB Clock
|
16 |
|
|
HRESETn : in std_logic; -- AHB Reset
|
17 |
|
|
|
18 |
|
|
-- AHB Slave inputs --------------------------------------------------------
|
19 |
|
|
HADDR : in std_logic_vector(27 downto 0); -- Address bus
|
20 |
|
|
HTRANS : in std_logic_vector(1 downto 0); -- Transfer type
|
21 |
|
|
HWRITE : in std_logic; -- Transfer direction
|
22 |
|
|
HWDATA : in std_logic_vector(31 downto 0); -- Write data bus
|
23 |
|
|
HSEL : in std_logic; -- Bridge slave select
|
24 |
|
|
HREADY : in std_logic; -- Transfer done input
|
25 |
|
|
|
26 |
|
|
-- APB Master inputs -------------------------------------------------------
|
27 |
|
|
PRDATA : in std_logic_vector(31 downto 0); -- Read data bus
|
28 |
|
|
|
29 |
|
|
-- AHB Slave outputs -------------------------------------------------------
|
30 |
|
|
HRDATA : out std_logic_vector(31 downto 0); -- Read data bus
|
31 |
|
|
HREADYOUT : out std_logic; -- Transfer done output
|
32 |
|
|
HRESP : out std_logic_vector(1 downto 0); -- Transfer response
|
33 |
|
|
|
34 |
|
|
-- APB Master outputs ------------------------------------------------------
|
35 |
|
|
PWDATA : out std_logic_vector(31 downto 0); -- Write data bus
|
36 |
|
|
PENABLE : out std_logic; -- Data valid strobe
|
37 |
|
|
PSELECT : out std_logic_vector(15 downto 0); -- Select bus
|
38 |
|
|
PADDR : out std_logic_vector(23 downto 0); -- Address bus
|
39 |
|
|
PWRITE : out std_logic -- Transfer direction
|
40 |
|
|
);
|
41 |
|
|
end CoreAHB2APB;
|
42 |
|
|
|
43 |
|
|
|
44 |
|
|
|
45 |
|
|
architecture synth of CoreAHB2APB is
|
46 |
|
|
|
47 |
|
|
-- Block Overview
|
48 |
|
|
--
|
49 |
|
|
-- The 16-Slot APB Bridge provides an interface between the high-speed AHB
|
50 |
|
|
-- domain and the low-power APB domain. The Bridge appears as a slave on AHB,
|
51 |
|
|
-- whereas on APB, it is the master. Read and write transfers on the AHB are
|
52 |
|
|
-- converted into corresponding transfers on the APB. As the APB is not
|
53 |
|
|
-- pipelined, wait states are added during transfers to and from the APB when
|
54 |
|
|
-- the AHB is required to wait for the APB protocol.
|
55 |
|
|
--
|
56 |
|
|
-- The AHB to APB Bridge comprises of a state machine, which is used to control
|
57 |
|
|
-- the generation of the APB and AHB output signals, and the address decoding
|
58 |
|
|
-- logic which is used to generate the APB peripheral select lines.
|
59 |
|
|
-- All registers used in the system are clocked from the rising edge of the
|
60 |
|
|
-- system clock HCLK, and use the asynchronous reset HRESETn.
|
61 |
|
|
--
|
62 |
|
|
-- Ahb2Apb states:
|
63 |
|
|
-- ST_IDLE is APB bus idle state entered on reset
|
64 |
|
|
-- ST_READ is read setup
|
65 |
|
|
-- ST_RENABLE is read enable
|
66 |
|
|
-- ST_WWAIT is write wait state
|
67 |
|
|
-- ST_WRITE is write setup
|
68 |
|
|
-- ST_WENABLE is write enable
|
69 |
|
|
-- ST_WRITEP is write setup with pending transfer
|
70 |
|
|
-- ST_WENABLEP is write enable with pending transfer
|
71 |
|
|
|
72 |
|
|
--------------------------------------------------------------------------------
|
73 |
|
|
-- Constant declarations
|
74 |
|
|
--------------------------------------------------------------------------------
|
75 |
|
|
|
76 |
|
|
constant ST_IDLE : std_logic_vector(3 downto 0) := "0000";
|
77 |
|
|
constant ST_READ : std_logic_vector(3 downto 0) := "0001";
|
78 |
|
|
constant ST_RENABLE : std_logic_vector(3 downto 0) := "0100";
|
79 |
|
|
constant ST_WWAIT : std_logic_vector(3 downto 0) := "1001";
|
80 |
|
|
constant ST_WRITE : std_logic_vector(3 downto 0) := "1010";
|
81 |
|
|
constant ST_WENABLE : std_logic_vector(3 downto 0) := "1110";
|
82 |
|
|
constant ST_WRITEP : std_logic_vector(3 downto 0) := "1011";
|
83 |
|
|
constant ST_WENABLEP : std_logic_vector(3 downto 0) := "1111";
|
84 |
|
|
|
85 |
|
|
-- EASY Peripherals address decoding values:
|
86 |
|
|
constant S0BASE : std_logic_vector(27 downto 24) := "0000";
|
87 |
|
|
constant S1BASE : std_logic_vector(27 downto 24) := "0001";
|
88 |
|
|
constant S2BASE : std_logic_vector(27 downto 24) := "0010";
|
89 |
|
|
constant S3BASE : std_logic_vector(27 downto 24) := "0011";
|
90 |
|
|
constant S4BASE : std_logic_vector(27 downto 24) := "0100";
|
91 |
|
|
constant S5BASE : std_logic_vector(27 downto 24) := "0101";
|
92 |
|
|
constant S6BASE : std_logic_vector(27 downto 24) := "0110";
|
93 |
|
|
constant S7BASE : std_logic_vector(27 downto 24) := "0111";
|
94 |
|
|
constant S8BASE : std_logic_vector(27 downto 24) := "1000";
|
95 |
|
|
constant S9BASE : std_logic_vector(27 downto 24) := "1001";
|
96 |
|
|
constant S10BASE : std_logic_vector(27 downto 24) := "1010";
|
97 |
|
|
constant S11BASE : std_logic_vector(27 downto 24) := "1011";
|
98 |
|
|
constant S12BASE : std_logic_vector(27 downto 24) := "1100";
|
99 |
|
|
constant S13BASE : std_logic_vector(27 downto 24) := "1101";
|
100 |
|
|
constant S14BASE : std_logic_vector(27 downto 24) := "1110";
|
101 |
|
|
constant S15BASE : std_logic_vector(27 downto 24) := "1111";
|
102 |
|
|
|
103 |
|
|
-- HTRANS transfer type signal encoding:
|
104 |
|
|
constant TRN_IDLE : std_logic_vector(1 downto 0) := "00";
|
105 |
|
|
constant TRN_BUSY : std_logic_vector(1 downto 0) := "01";
|
106 |
|
|
constant TRN_NONSEQ : std_logic_vector(1 downto 0) := "10";
|
107 |
|
|
constant TRN_SEQ : std_logic_vector(1 downto 0) := "11";
|
108 |
|
|
|
109 |
|
|
-- HRESP transfer response signal encoding:
|
110 |
|
|
constant RSP_OKAY : std_logic_vector(1 downto 0) := "00";
|
111 |
|
|
constant RSP_ERROR : std_logic_vector(1 downto 0) := "01";
|
112 |
|
|
constant RSP_RETRY : std_logic_vector(1 downto 0) := "10";
|
113 |
|
|
constant RSP_SPLIT : std_logic_vector(1 downto 0) := "11";
|
114 |
|
|
|
115 |
|
|
|
116 |
|
|
--------------------------------------------------------------------------------
|
117 |
|
|
-- Signal declarations
|
118 |
|
|
--------------------------------------------------------------------------------
|
119 |
|
|
|
120 |
|
|
signal Valid : std_logic; -- Module is selected with valid transfer
|
121 |
|
|
signal ACRegEn : std_logic; -- Enable for address and control registers
|
122 |
|
|
signal HaddrReg : std_logic_vector(27 downto 0); -- HADDR register
|
123 |
|
|
signal HwriteReg : std_logic; -- HWRITE register
|
124 |
|
|
signal HaddrMux : std_logic_vector(27 downto 0); -- HADDR multiplexer
|
125 |
|
|
|
126 |
|
|
signal NextState : std_logic_vector(3 downto 0); -- State machine
|
127 |
|
|
signal CurrentState : std_logic_vector(3 downto 0);
|
128 |
|
|
|
129 |
|
|
signal HreadyNext : std_logic; -- HREADYOUT register input
|
130 |
|
|
signal iHREADYOUT : std_logic; -- HREADYOUT register
|
131 |
|
|
|
132 |
|
|
signal Psel0Int : std_logic; -- Internal PSEL0
|
133 |
|
|
signal Psel1Int : std_logic; -- Internal PSEL1
|
134 |
|
|
signal Psel2Int : std_logic; -- Internal PSEL2
|
135 |
|
|
signal Psel3Int : std_logic; -- Internal PSEL3
|
136 |
|
|
signal Psel4Int : std_logic; -- Internal PSEL4
|
137 |
|
|
signal Psel5Int : std_logic; -- Internal PSEL5
|
138 |
|
|
signal Psel6Int : std_logic; -- Internal PSEL6
|
139 |
|
|
signal Psel7Int : std_logic; -- Internal PSEL7
|
140 |
|
|
signal Psel8Int : std_logic; -- Internal PSEL8
|
141 |
|
|
signal Psel9Int : std_logic; -- Internal PSEL9
|
142 |
|
|
signal Psel10Int : std_logic; -- Internal PSEL10
|
143 |
|
|
signal Psel11Int : std_logic; -- Internal PSEL11
|
144 |
|
|
signal Psel12Int : std_logic; -- Internal PSEL12
|
145 |
|
|
signal Psel13Int : std_logic; -- Internal PSEL13
|
146 |
|
|
signal Psel14Int : std_logic; -- Internal PSEL14
|
147 |
|
|
signal Psel15Int : std_logic; -- Internal PSEL15
|
148 |
|
|
|
149 |
|
|
signal APBEn : std_logic; -- Enable for APB output registers
|
150 |
|
|
|
151 |
|
|
signal PWDATAEn : std_logic; -- PWDATA Register enable
|
152 |
|
|
signal PenableNext : std_logic; -- PENABLE register input
|
153 |
|
|
|
154 |
|
|
signal Psel0Mux : std_logic; -- PSEL multiplexer values
|
155 |
|
|
signal Psel1Mux : std_logic;
|
156 |
|
|
signal Psel2Mux : std_logic;
|
157 |
|
|
signal Psel3Mux : std_logic;
|
158 |
|
|
signal Psel4Mux : std_logic;
|
159 |
|
|
signal Psel5Mux : std_logic;
|
160 |
|
|
signal Psel6Mux : std_logic;
|
161 |
|
|
signal Psel7Mux : std_logic;
|
162 |
|
|
signal Psel8Mux : std_logic;
|
163 |
|
|
signal Psel9Mux : std_logic;
|
164 |
|
|
signal Psel10Mux : std_logic;
|
165 |
|
|
signal Psel11Mux : std_logic;
|
166 |
|
|
signal Psel12Mux : std_logic;
|
167 |
|
|
signal Psel13Mux : std_logic;
|
168 |
|
|
signal Psel14Mux : std_logic;
|
169 |
|
|
signal Psel15Mux : std_logic;
|
170 |
|
|
|
171 |
|
|
signal iPSEL0 : std_logic; -- Internal PSEL outputs
|
172 |
|
|
signal iPSEL1 : std_logic;
|
173 |
|
|
signal iPSEL2 : std_logic;
|
174 |
|
|
signal iPSEL3 : std_logic;
|
175 |
|
|
signal iPSEL4 : std_logic;
|
176 |
|
|
signal iPSEL5 : std_logic;
|
177 |
|
|
signal iPSEL6 : std_logic;
|
178 |
|
|
signal iPSEL7 : std_logic;
|
179 |
|
|
signal iPSEL8 : std_logic;
|
180 |
|
|
signal iPSEL9 : std_logic;
|
181 |
|
|
signal iPSEL10 : std_logic;
|
182 |
|
|
signal iPSEL11 : std_logic;
|
183 |
|
|
signal iPSEL12 : std_logic;
|
184 |
|
|
signal iPSEL13 : std_logic;
|
185 |
|
|
signal iPSEL14 : std_logic;
|
186 |
|
|
signal iPSEL15 : std_logic;
|
187 |
|
|
|
188 |
|
|
signal PwriteNext : std_logic; -- PWRITE register input
|
189 |
|
|
|
190 |
|
|
|
191 |
|
|
--------------------------------------------------------------------------------
|
192 |
|
|
-- Beginning of main code
|
193 |
|
|
--------------------------------------------------------------------------------
|
194 |
|
|
|
195 |
|
|
begin
|
196 |
|
|
|
197 |
|
|
--------------------------------------------------------------------------------
|
198 |
|
|
-- Valid transfer detection
|
199 |
|
|
--------------------------------------------------------------------------------
|
200 |
|
|
-- Valid AHB transfers only take place when a non-sequential or sequential
|
201 |
|
|
-- transfer is shown on HTRANS - an idle or busy transfer should be ignored.
|
202 |
|
|
|
203 |
|
|
Valid <= '1' when (HSEL = '1' and HREADY = '1' and
|
204 |
|
|
(HTRANS = TRN_NONSEQ or HTRANS = TRN_SEQ))
|
205 |
|
|
else '0';
|
206 |
|
|
|
207 |
|
|
--------------------------------------------------------------------------------
|
208 |
|
|
-- Address and control registers
|
209 |
|
|
--------------------------------------------------------------------------------
|
210 |
|
|
-- Registers are used to store the address and control signals from the address
|
211 |
|
|
-- phase for use in the data phase of the transfer.
|
212 |
|
|
-- Only enabled when the HREADY input is HIGH and the module is addressed.
|
213 |
|
|
|
214 |
|
|
ACRegEn <= HSEL and HREADY;
|
215 |
|
|
|
216 |
|
|
p_ACRegSeq : process (HRESETn, HCLK)
|
217 |
|
|
begin
|
218 |
|
|
if (HRESETn = '0') then
|
219 |
|
|
HaddrReg <= (others => '0');
|
220 |
|
|
HwriteReg <= '0';
|
221 |
|
|
elsif (HCLK'event and HCLK = '1') then
|
222 |
|
|
if ACRegEn = '1' then
|
223 |
|
|
HaddrReg <= HADDR;
|
224 |
|
|
HwriteReg <= HWRITE;
|
225 |
|
|
end if;
|
226 |
|
|
end if;
|
227 |
|
|
end process p_ACRegSeq;
|
228 |
|
|
|
229 |
|
|
-- The address source used depends on the source of the current APB transfer. If
|
230 |
|
|
-- the transfer is being generated from:
|
231 |
|
|
-- - the pipeline registers, then the address source is HaddrReg
|
232 |
|
|
-- - the AHB inputs, the the address source is HADDR.
|
233 |
|
|
--
|
234 |
|
|
-- The HaddrMux multiplexer is used to select the appropriate address source. A
|
235 |
|
|
-- new read, sequential read following another read, or a read following a
|
236 |
|
|
-- write with no pending transfer are the only transfers that are generated
|
237 |
|
|
-- directly from the AHB inputs. All other transfers are generated from the
|
238 |
|
|
-- pipeline registers.
|
239 |
|
|
|
240 |
|
|
HaddrMux <= HADDR when (NextState = ST_READ and (CurrentState = ST_IDLE or
|
241 |
|
|
CurrentState = ST_RENABLE or
|
242 |
|
|
CurrentState = ST_WENABLE))
|
243 |
|
|
else HaddrReg;
|
244 |
|
|
|
245 |
|
|
--------------------------------------------------------------------------------
|
246 |
|
|
-- Next state logic for APB state machine
|
247 |
|
|
--------------------------------------------------------------------------------
|
248 |
|
|
-- Generates next state from CurrentState and AHB inputs.
|
249 |
|
|
|
250 |
|
|
-- Due to write transfers having an extra setup state, the pending states are
|
251 |
|
|
-- used to indicate that there is a transfer in the pipeline that has not been
|
252 |
|
|
-- started on the APB.
|
253 |
|
|
-- Read transfers start immediately, so pending states are not needed.
|
254 |
|
|
|
255 |
|
|
p_NextStateComb : process (CurrentState, HWRITE, HwriteReg, Valid)
|
256 |
|
|
begin
|
257 |
|
|
case CurrentState is
|
258 |
|
|
|
259 |
|
|
when ST_IDLE => -- Idle state
|
260 |
|
|
if Valid = '1' then
|
261 |
|
|
if HWRITE = '1' then
|
262 |
|
|
NextState <= ST_WWAIT;
|
263 |
|
|
else
|
264 |
|
|
NextState <= ST_READ;
|
265 |
|
|
end if;
|
266 |
|
|
else
|
267 |
|
|
NextState <= ST_IDLE;
|
268 |
|
|
end if;
|
269 |
|
|
|
270 |
|
|
when ST_READ => -- Read setup
|
271 |
|
|
NextState <= ST_RENABLE;
|
272 |
|
|
|
273 |
|
|
when ST_WWAIT => -- Hold for one cycle before write
|
274 |
|
|
if Valid = '1' then
|
275 |
|
|
NextState <= ST_WRITEP;
|
276 |
|
|
else
|
277 |
|
|
NextState <= ST_WRITE;
|
278 |
|
|
end if;
|
279 |
|
|
|
280 |
|
|
when ST_WRITE => -- Write setup
|
281 |
|
|
if Valid = '1' then
|
282 |
|
|
NextState <= ST_WENABLEP;
|
283 |
|
|
else
|
284 |
|
|
NextState <= ST_WENABLE;
|
285 |
|
|
end if;
|
286 |
|
|
|
287 |
|
|
when ST_WRITEP => -- Write setup with pending transfer
|
288 |
|
|
NextState <= ST_WENABLEP;
|
289 |
|
|
|
290 |
|
|
when ST_RENABLE => -- Read enable
|
291 |
|
|
if Valid = '1' then
|
292 |
|
|
if HWRITE = '1' then
|
293 |
|
|
NextState <= ST_WWAIT;
|
294 |
|
|
else
|
295 |
|
|
NextState <= ST_READ;
|
296 |
|
|
end if;
|
297 |
|
|
else
|
298 |
|
|
NextState <= ST_IDLE;
|
299 |
|
|
end if;
|
300 |
|
|
|
301 |
|
|
when ST_WENABLE => -- Write enable
|
302 |
|
|
if Valid = '1' then
|
303 |
|
|
if HWRITE = '1' then
|
304 |
|
|
NextState <= ST_WWAIT;
|
305 |
|
|
else
|
306 |
|
|
NextState <= ST_READ;
|
307 |
|
|
end if;
|
308 |
|
|
else
|
309 |
|
|
NextState <= ST_IDLE;
|
310 |
|
|
end if;
|
311 |
|
|
|
312 |
|
|
when ST_WENABLEP => -- Write enable with pending transfer
|
313 |
|
|
if HwriteReg = '1' then
|
314 |
|
|
if Valid = '1' then
|
315 |
|
|
NextState <= ST_WRITEP;
|
316 |
|
|
else
|
317 |
|
|
NextState <= ST_WRITE;
|
318 |
|
|
end if;
|
319 |
|
|
else
|
320 |
|
|
NextState <= ST_READ;
|
321 |
|
|
end if;
|
322 |
|
|
|
323 |
|
|
when others =>
|
324 |
|
|
NextState <= ST_IDLE; -- Return to idle on FSM error
|
325 |
|
|
|
326 |
|
|
end case;
|
327 |
|
|
end process p_NextStateComb;
|
328 |
|
|
|
329 |
|
|
--------------------------------------------------------------------------------
|
330 |
|
|
-- State machine
|
331 |
|
|
--------------------------------------------------------------------------------
|
332 |
|
|
-- Changes state on rising edge of HCLK.
|
333 |
|
|
|
334 |
|
|
p_CurrentStateSeq : process (HRESETn, HCLK)
|
335 |
|
|
begin
|
336 |
|
|
if (HRESETn = '0') then
|
337 |
|
|
CurrentState <= ST_IDLE;
|
338 |
|
|
elsif (HCLK'event and HCLK = '1') then
|
339 |
|
|
CurrentState <= NextState;
|
340 |
|
|
end if;
|
341 |
|
|
end process p_CurrentStateSeq;
|
342 |
|
|
|
343 |
|
|
--------------------------------------------------------------------------------
|
344 |
|
|
-- HREADYOUT generation
|
345 |
|
|
--------------------------------------------------------------------------------
|
346 |
|
|
-- A registered version of HREADYOUT is used to improve output timing.
|
347 |
|
|
-- Wait states are inserted during:
|
348 |
|
|
-- ST_READ
|
349 |
|
|
-- ST_WRITEP
|
350 |
|
|
-- ST_WENABLEP when the currently pending transfer is a read, or
|
351 |
|
|
-- when the currently driven AHB transfer is a read and is
|
352 |
|
|
-- qualified by Valid.
|
353 |
|
|
|
354 |
|
|
HreadyNext <= '0' when (NextState = ST_READ or NextState = ST_WRITEP or
|
355 |
|
|
(NextState = ST_WENABLEP and
|
356 |
|
|
((HWRITE = '0' and Valid = '1') or
|
357 |
|
|
HwriteReg = '0')))
|
358 |
|
|
else '1';
|
359 |
|
|
|
360 |
|
|
p_iHREADYOUTSeq : process (HRESETn, HCLK)
|
361 |
|
|
begin
|
362 |
|
|
if (HRESETn = '0') then
|
363 |
|
|
iHREADYOUT <= '1';
|
364 |
|
|
elsif (HCLK'event and HCLK = '1') then
|
365 |
|
|
iHREADYOUT <= HreadyNext;
|
366 |
|
|
end if;
|
367 |
|
|
end process p_iHREADYOUTSeq;
|
368 |
|
|
|
369 |
|
|
--------------------------------------------------------------------------------
|
370 |
|
|
-- APB address decoding for slave devices
|
371 |
|
|
--------------------------------------------------------------------------------
|
372 |
|
|
-- Decodes the address from HaddrMux, which only changes during a read or write
|
373 |
|
|
-- cycle.
|
374 |
|
|
-- When an address is used that is not in any of the ranges specified,
|
375 |
|
|
-- operation of the system continues, but no PSEL lines are set, so no
|
376 |
|
|
-- peripherals are selected during the read/write transfer.
|
377 |
|
|
-- Operation of PWDATA, PWRITE, PENABLE and PADDR continues as normal.
|
378 |
|
|
|
379 |
|
|
p_AddressDecodeComb : process (HaddrMux)
|
380 |
|
|
begin
|
381 |
|
|
-- Default values
|
382 |
|
|
Psel0Int <= '0';
|
383 |
|
|
Psel1Int <= '0';
|
384 |
|
|
Psel2Int <= '0';
|
385 |
|
|
Psel3Int <= '0';
|
386 |
|
|
Psel4Int <= '0';
|
387 |
|
|
Psel5Int <= '0';
|
388 |
|
|
Psel6Int <= '0';
|
389 |
|
|
Psel7Int <= '0';
|
390 |
|
|
Psel8Int <= '0';
|
391 |
|
|
Psel9Int <= '0';
|
392 |
|
|
Psel10Int <= '0';
|
393 |
|
|
Psel11Int <= '0';
|
394 |
|
|
Psel12Int <= '0';
|
395 |
|
|
Psel13Int <= '0';
|
396 |
|
|
Psel14Int <= '0';
|
397 |
|
|
Psel15Int <= '0';
|
398 |
|
|
|
399 |
|
|
case HaddrMux(27 downto 24) is
|
400 |
|
|
when S0BASE =>
|
401 |
|
|
Psel0Int <= '1';
|
402 |
|
|
when S1BASE =>
|
403 |
|
|
Psel1Int <= '1';
|
404 |
|
|
when S2BASE =>
|
405 |
|
|
Psel2Int <= '1';
|
406 |
|
|
when S3BASE =>
|
407 |
|
|
Psel3Int <= '1';
|
408 |
|
|
when S4BASE =>
|
409 |
|
|
Psel4Int <= '1';
|
410 |
|
|
when S5BASE =>
|
411 |
|
|
Psel5Int <= '1';
|
412 |
|
|
when S6BASE =>
|
413 |
|
|
Psel6Int <= '1';
|
414 |
|
|
when S7BASE =>
|
415 |
|
|
Psel7Int <= '1';
|
416 |
|
|
when S8BASE =>
|
417 |
|
|
Psel8Int <= '1';
|
418 |
|
|
when S9BASE =>
|
419 |
|
|
Psel9Int <= '1';
|
420 |
|
|
when S10BASE =>
|
421 |
|
|
Psel10Int <= '1';
|
422 |
|
|
when S11BASE =>
|
423 |
|
|
Psel11Int <= '1';
|
424 |
|
|
when S12BASE =>
|
425 |
|
|
Psel12Int <= '1';
|
426 |
|
|
when S13BASE =>
|
427 |
|
|
Psel13Int <= '1';
|
428 |
|
|
when S14BASE =>
|
429 |
|
|
Psel14Int <= '1';
|
430 |
|
|
when S15BASE =>
|
431 |
|
|
Psel15Int <= '1';
|
432 |
|
|
when others =>
|
433 |
|
|
null;
|
434 |
|
|
end case;
|
435 |
|
|
end process p_AddressDecodeComb;
|
436 |
|
|
|
437 |
|
|
--------------------------------------------------------------------------------
|
438 |
|
|
-- APB enable generation
|
439 |
|
|
--------------------------------------------------------------------------------
|
440 |
|
|
-- APBEn is set when starting an access on the APB, and is used to enable the
|
441 |
|
|
-- PSEL, PWRITE and PADDR APB output registers.
|
442 |
|
|
|
443 |
|
|
APBEn <= '1' when (NextState = ST_READ or NextState = ST_WRITE or
|
444 |
|
|
NextState = ST_WRITEP)
|
445 |
|
|
else '0';
|
446 |
|
|
|
447 |
|
|
--------------------------------------------------------------------------------
|
448 |
|
|
-- Registered HWDATA for writes (PWDATA)
|
449 |
|
|
--------------------------------------------------------------------------------
|
450 |
|
|
-- Write wait state allows a register to be used to hold PWDATA.
|
451 |
|
|
-- Register enabled when PWRITE output is set HIGH.
|
452 |
|
|
|
453 |
|
|
PWDATAEn <= PwriteNext;
|
454 |
|
|
|
455 |
|
|
p_PWDATASeq : process (HRESETn, HCLK)
|
456 |
|
|
begin
|
457 |
|
|
if (HRESETn = '0') then
|
458 |
|
|
PWDATA <= (others => '0');
|
459 |
|
|
elsif (HCLK'event and HCLK = '1') then
|
460 |
|
|
if PWDATAEn = '1' then
|
461 |
|
|
PWDATA <= HWDATA;
|
462 |
|
|
end if;
|
463 |
|
|
end if;
|
464 |
|
|
end process p_PWDATASeq;
|
465 |
|
|
|
466 |
|
|
--------------------------------------------------------------------------------
|
467 |
|
|
-- PENABLE generation
|
468 |
|
|
--------------------------------------------------------------------------------
|
469 |
|
|
-- PENABLE output is set HIGH during any of the three ENABLE states.
|
470 |
|
|
|
471 |
|
|
PenableNext <= '1' when (NextState = ST_RENABLE or
|
472 |
|
|
NextState = ST_WENABLE or
|
473 |
|
|
NextState = ST_WENABLEP)
|
474 |
|
|
else '0';
|
475 |
|
|
|
476 |
|
|
p_PENABLESeq : process (HRESETn, HCLK)
|
477 |
|
|
begin
|
478 |
|
|
if (HRESETn = '0') then
|
479 |
|
|
PENABLE <= '0';
|
480 |
|
|
elsif (HCLK'event and HCLK = '1') then
|
481 |
|
|
PENABLE <= PenableNext;
|
482 |
|
|
end if;
|
483 |
|
|
end process p_PENABLESeq;
|
484 |
|
|
|
485 |
|
|
--------------------------------------------------------------------------------
|
486 |
|
|
-- iPSEL generation
|
487 |
|
|
--------------------------------------------------------------------------------
|
488 |
|
|
-- Set outputs with internal values when in READ or WRITE states (APBEn HIGH).
|
489 |
|
|
-- Reset outputs when APB transfer has ended.
|
490 |
|
|
-- Hold outputs at all other times.
|
491 |
|
|
|
492 |
|
|
p_PselMuxComb : process (APBEn, NextState, Psel0Int, Psel1Int, Psel2Int,
|
493 |
|
|
Psel3Int, Psel4Int, Psel5Int, Psel6Int,
|
494 |
|
|
Psel7Int, Psel8Int, Psel9Int, Psel10Int,
|
495 |
|
|
Psel11Int, Psel12Int, Psel13Int, Psel14Int,
|
496 |
|
|
Psel15Int, iPSEL0, iPSEL1, iPSEL2, iPSEL3,
|
497 |
|
|
iPSEL4, iPSEL5, iPSEL6, iPSEL7, iPSEL8,
|
498 |
|
|
iPSEL9, iPSEL10, iPSEL11, iPSEL12, iPSEL13,
|
499 |
|
|
iPSEL14, iPSEL15)
|
500 |
|
|
begin
|
501 |
|
|
if (APBEn = '1') then
|
502 |
|
|
Psel0Mux <= Psel0Int;
|
503 |
|
|
Psel1Mux <= Psel1Int;
|
504 |
|
|
Psel2Mux <= Psel2Int;
|
505 |
|
|
Psel3Mux <= Psel3Int;
|
506 |
|
|
Psel4Mux <= Psel4Int;
|
507 |
|
|
Psel5Mux <= Psel5Int;
|
508 |
|
|
Psel6Mux <= Psel6Int;
|
509 |
|
|
Psel7Mux <= Psel7Int;
|
510 |
|
|
Psel8Mux <= Psel8Int;
|
511 |
|
|
Psel9Mux <= Psel9Int;
|
512 |
|
|
Psel10Mux <= Psel10Int;
|
513 |
|
|
Psel11Mux <= Psel11Int;
|
514 |
|
|
Psel12Mux <= Psel12Int;
|
515 |
|
|
Psel13Mux <= Psel13Int;
|
516 |
|
|
Psel14Mux <= Psel14Int;
|
517 |
|
|
Psel15Mux <= Psel15Int;
|
518 |
|
|
elsif (NextState = ST_IDLE or NextState = ST_WWAIT) then
|
519 |
|
|
Psel0Mux <= '0';
|
520 |
|
|
Psel1Mux <= '0';
|
521 |
|
|
Psel2Mux <= '0';
|
522 |
|
|
Psel3Mux <= '0';
|
523 |
|
|
Psel4Mux <= '0';
|
524 |
|
|
Psel5Mux <= '0';
|
525 |
|
|
Psel6Mux <= '0';
|
526 |
|
|
Psel7Mux <= '0';
|
527 |
|
|
Psel8Mux <= '0';
|
528 |
|
|
Psel9Mux <= '0';
|
529 |
|
|
Psel10Mux <= '0';
|
530 |
|
|
Psel11Mux <= '0';
|
531 |
|
|
Psel12Mux <= '0';
|
532 |
|
|
Psel13Mux <= '0';
|
533 |
|
|
Psel14Mux <= '0';
|
534 |
|
|
Psel15Mux <= '0';
|
535 |
|
|
else
|
536 |
|
|
Psel0Mux <= iPSEL0;
|
537 |
|
|
Psel1Mux <= iPSEL1;
|
538 |
|
|
Psel2Mux <= iPSEL2;
|
539 |
|
|
Psel3Mux <= iPSEL3;
|
540 |
|
|
Psel4Mux <= iPSEL4;
|
541 |
|
|
Psel5Mux <= iPSEL5;
|
542 |
|
|
Psel6Mux <= iPSEL6;
|
543 |
|
|
Psel7Mux <= iPSEL7;
|
544 |
|
|
Psel8Mux <= iPSEL8;
|
545 |
|
|
Psel9Mux <= iPSEL9;
|
546 |
|
|
Psel10Mux <= iPSEL10;
|
547 |
|
|
Psel11Mux <= iPSEL11;
|
548 |
|
|
Psel12Mux <= iPSEL12;
|
549 |
|
|
Psel13Mux <= iPSEL13;
|
550 |
|
|
Psel14Mux <= iPSEL14;
|
551 |
|
|
Psel15Mux <= iPSEL15;
|
552 |
|
|
end if;
|
553 |
|
|
end process p_PselMuxComb;
|
554 |
|
|
|
555 |
|
|
-- Drives PSEL outputs with internal multiplexer versions.
|
556 |
|
|
|
557 |
|
|
p_PSELSeq : process (HRESETn, HCLK)
|
558 |
|
|
begin
|
559 |
|
|
if (HRESETn = '0') then
|
560 |
|
|
iPSEL0 <= '0';
|
561 |
|
|
iPSEL1 <= '0';
|
562 |
|
|
iPSEL2 <= '0';
|
563 |
|
|
iPSEL3 <= '0';
|
564 |
|
|
iPSEL4 <= '0';
|
565 |
|
|
iPSEL5 <= '0';
|
566 |
|
|
iPSEL6 <= '0';
|
567 |
|
|
iPSEL7 <= '0';
|
568 |
|
|
iPSEL8 <= '0';
|
569 |
|
|
iPSEL9 <= '0';
|
570 |
|
|
iPSEL10 <= '0';
|
571 |
|
|
iPSEL11 <= '0';
|
572 |
|
|
iPSEL12 <= '0';
|
573 |
|
|
iPSEL13 <= '0';
|
574 |
|
|
iPSEL14 <= '0';
|
575 |
|
|
iPSEL15 <= '0';
|
576 |
|
|
elsif (HCLK'event and HCLK = '1') then
|
577 |
|
|
iPSEL0 <= Psel0Mux;
|
578 |
|
|
iPSEL1 <= Psel1Mux;
|
579 |
|
|
iPSEL2 <= Psel2Mux;
|
580 |
|
|
iPSEL3 <= Psel3Mux;
|
581 |
|
|
iPSEL4 <= Psel4Mux;
|
582 |
|
|
iPSEL5 <= Psel5Mux;
|
583 |
|
|
iPSEL6 <= Psel6Mux;
|
584 |
|
|
iPSEL7 <= Psel7Mux;
|
585 |
|
|
iPSEL8 <= Psel8Mux;
|
586 |
|
|
iPSEL9 <= Psel9Mux;
|
587 |
|
|
iPSEL10 <= Psel10Mux;
|
588 |
|
|
iPSEL11 <= Psel11Mux;
|
589 |
|
|
iPSEL12 <= Psel12Mux;
|
590 |
|
|
iPSEL13 <= Psel13Mux;
|
591 |
|
|
iPSEL14 <= Psel14Mux;
|
592 |
|
|
iPSEL15 <= Psel15Mux;
|
593 |
|
|
end if;
|
594 |
|
|
end process p_PSELSeq;
|
595 |
|
|
|
596 |
|
|
--------------------------------------------------------------------------------
|
597 |
|
|
-- Registered HADDR for reads and writes (iPADDR)
|
598 |
|
|
--------------------------------------------------------------------------------
|
599 |
|
|
-- HaddrMux is used, as the generation time of the APB address is different for
|
600 |
|
|
-- reads and writes, so both the direct and registered HADDR input need to be
|
601 |
|
|
-- used.
|
602 |
|
|
-- HaddrMux is captured by an APBEn enabled register to generate iPADDR.
|
603 |
|
|
-- PADDR driven on State Machine change to READ or WRITE, with reset to zero.
|
604 |
|
|
|
605 |
|
|
p_iPADDRSeq : process (HRESETn, HCLK)
|
606 |
|
|
begin
|
607 |
|
|
if (HRESETn = '0') then
|
608 |
|
|
PADDR <= (others => '0');
|
609 |
|
|
elsif (HCLK'event and HCLK = '1') then
|
610 |
|
|
if (APBEn = '1') then
|
611 |
|
|
PADDR <= HaddrMux(23 downto 0);
|
612 |
|
|
end if;
|
613 |
|
|
end if;
|
614 |
|
|
end process p_iPADDRSeq;
|
615 |
|
|
|
616 |
|
|
--------------------------------------------------------------------------------
|
617 |
|
|
-- PWRITE generation
|
618 |
|
|
--------------------------------------------------------------------------------
|
619 |
|
|
-- PwriteNext is active when NextState is either ST_WRITE or ST_WRITEP. To avoid
|
620 |
|
|
-- a critical path through the main state machine this signal is generated
|
621 |
|
|
-- using CurrentState.
|
622 |
|
|
-- PwriteNext is captured by an APBEn enabled register to generate PWRITE, and
|
623 |
|
|
-- is generated from NextState (set HIGH during a write cycle).
|
624 |
|
|
-- PWRITE output only changes when APB is accessed.
|
625 |
|
|
|
626 |
|
|
p_PwriteNextComb : process (CurrentState, HwriteReg)
|
627 |
|
|
begin
|
628 |
|
|
case CurrentState is
|
629 |
|
|
|
630 |
|
|
when ST_WWAIT =>
|
631 |
|
|
PwriteNext <= '1';
|
632 |
|
|
|
633 |
|
|
when ST_WENABLEP =>
|
634 |
|
|
if HwriteReg = '1' then
|
635 |
|
|
PwriteNext <= '1';
|
636 |
|
|
else
|
637 |
|
|
PwriteNext <= '0';
|
638 |
|
|
end if;
|
639 |
|
|
|
640 |
|
|
when others =>
|
641 |
|
|
PwriteNext <= '0';
|
642 |
|
|
|
643 |
|
|
end case;
|
644 |
|
|
end process p_PwriteNextComb;
|
645 |
|
|
|
646 |
|
|
p_PWRITESeq : process (HRESETn, HCLK)
|
647 |
|
|
begin
|
648 |
|
|
if (HRESETn = '0') then
|
649 |
|
|
PWRITE <= '0';
|
650 |
|
|
elsif (HCLK'event and HCLK = '1') then
|
651 |
|
|
if (APBEn = '1') then
|
652 |
|
|
PWRITE <= PwriteNext;
|
653 |
|
|
end if;
|
654 |
|
|
end if;
|
655 |
|
|
end process p_PWRITESeq;
|
656 |
|
|
|
657 |
|
|
--------------------------------------------------------------------------------
|
658 |
|
|
-- APB output drivers
|
659 |
|
|
--------------------------------------------------------------------------------
|
660 |
|
|
-- Drive outputs with internal signals.
|
661 |
|
|
|
662 |
|
|
PSELECT(0) <= iPSEL0;
|
663 |
|
|
PSELECT(1) <= iPSEL1;
|
664 |
|
|
PSELECT(2) <= iPSEL2;
|
665 |
|
|
PSELECT(3) <= iPSEL3;
|
666 |
|
|
PSELECT(4) <= iPSEL4;
|
667 |
|
|
PSELECT(5) <= iPSEL5;
|
668 |
|
|
PSELECT(6) <= iPSEL6;
|
669 |
|
|
PSELECT(7) <= iPSEL7;
|
670 |
|
|
PSELECT(8) <= iPSEL8;
|
671 |
|
|
PSELECT(9) <= iPSEL9;
|
672 |
|
|
PSELECT(10) <= iPSEL10;
|
673 |
|
|
PSELECT(11) <= iPSEL11;
|
674 |
|
|
PSELECT(12) <= iPSEL12;
|
675 |
|
|
PSELECT(13) <= iPSEL13;
|
676 |
|
|
PSELECT(14) <= iPSEL14;
|
677 |
|
|
PSELECT(15) <= iPSEL15;
|
678 |
|
|
|
679 |
|
|
--------------------------------------------------------------------------------
|
680 |
|
|
-- AHB output drivers
|
681 |
|
|
--------------------------------------------------------------------------------
|
682 |
|
|
-- PRDATA is only ever driven during a read, so it can be directly copied to
|
683 |
|
|
-- HRDATA to reduce the output data delay onto the AHB.
|
684 |
|
|
|
685 |
|
|
HRDATA <= PRDATA;
|
686 |
|
|
|
687 |
|
|
-- Drives the output port with the internal version, and sets it LOW at all
|
688 |
|
|
-- other times when the module is not selected.
|
689 |
|
|
|
690 |
|
|
HREADYOUT <= iHREADYOUT;
|
691 |
|
|
|
692 |
|
|
-- The response will always be OKAY to show that the transfer has been performed
|
693 |
|
|
-- successfully.
|
694 |
|
|
|
695 |
|
|
HRESP <= RSP_OKAY;
|
696 |
|
|
|
697 |
|
|
|
698 |
|
|
end synth;
|
699 |
|
|
|
700 |
|
|
-- --================================= End ===================================--
|