1 |
2 |
federico.a |
|
2 |
|
|
--*******************************************************************
|
3 |
|
|
--** ****
|
4 |
|
|
--** AHB system generator ****
|
5 |
|
|
--** ****
|
6 |
|
|
--** Author: Federico Aglietti ****
|
7 |
|
|
--** federico.aglietti\@opencores.org ****
|
8 |
|
|
--** ****
|
9 |
|
|
--*******************************************************************
|
10 |
|
|
--** ****
|
11 |
|
|
--** Copyright (C) 2004 Federico Aglietti ****
|
12 |
|
|
--** federico.aglietti\@opencores.org ****
|
13 |
|
|
--** ****
|
14 |
|
|
--** This source file may be used and distributed without ****
|
15 |
|
|
--** restriction provided that this copyright statement is not ****
|
16 |
|
|
--** removed from the file and that any derivative work contains ****
|
17 |
|
|
--** the original copyright notice and the associated disclaimer.****
|
18 |
|
|
--** ****
|
19 |
|
|
--** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ****
|
20 |
|
|
--** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ****
|
21 |
|
|
--** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ****
|
22 |
|
|
--** FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ****
|
23 |
|
|
--** OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ****
|
24 |
|
|
--** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ****
|
25 |
|
|
--** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ****
|
26 |
|
|
--** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ****
|
27 |
|
|
--** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ****
|
28 |
|
|
--** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ****
|
29 |
|
|
--** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ****
|
30 |
|
|
--** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ****
|
31 |
|
|
--** POSSIBILITY OF SUCH DAMAGE. ****
|
32 |
|
|
--** ****
|
33 |
|
|
--*******************************************************************
|
34 |
|
|
library ieee;
|
35 |
|
|
use ieee.std_logic_1164.all;
|
36 |
|
|
use ieee.std_logic_unsigned.all;
|
37 |
|
|
use ieee.std_logic_misc.all;
|
38 |
|
|
use ieee.std_logic_arith.all;
|
39 |
|
|
|
40 |
|
|
use work.ahb_funct.all;
|
41 |
|
|
use work.ahb_package.all;
|
42 |
|
|
|
43 |
|
|
entity ahb_master is
|
44 |
|
|
generic (
|
45 |
|
|
fifohempty_level: in integer:= 2;
|
46 |
|
|
fifohfull_level: in integer:= 6;
|
47 |
|
|
fifo_length: in integer:= 8);
|
48 |
|
|
port (
|
49 |
|
|
--***********************************************
|
50 |
|
|
--master ahb amba signals
|
51 |
|
|
--***********************************************
|
52 |
|
|
hresetn: in std_logic;
|
53 |
|
|
hclk: in std_logic;
|
54 |
|
|
mst_in: in mst_in_t;
|
55 |
|
|
mst_out: out mst_out_t;
|
56 |
|
|
|
57 |
|
|
--***********************************************
|
58 |
|
|
--master<=>core interface: conf registers
|
59 |
|
|
--***********************************************
|
60 |
|
|
dma_start: in start_type_t;
|
61 |
|
|
|
62 |
|
|
--***********************************************
|
63 |
|
|
--master<=>core interface: program/data memories
|
64 |
|
|
--***********************************************
|
65 |
|
|
m_wrap_out: out wrap_out_t;
|
66 |
|
|
m_wrap_in: in wrap_in_t;
|
67 |
|
|
|
68 |
|
|
--***********************************************
|
69 |
|
|
--master/slave/core signals
|
70 |
|
|
--***********************************************
|
71 |
|
|
slv_running: in std_logic;
|
72 |
|
|
mst_running: out std_logic;
|
73 |
|
|
eot_int: out std_logic
|
74 |
|
|
);
|
75 |
|
|
end ahb_master;
|
76 |
|
|
|
77 |
|
|
architecture rtl of ahb_master is
|
78 |
|
|
|
79 |
|
|
--***************************************************************
|
80 |
|
|
--component declaration
|
81 |
|
|
--***************************************************************
|
82 |
|
|
component fifo
|
83 |
|
|
generic (
|
84 |
|
|
fifohempty_level: in integer:= 1;
|
85 |
|
|
fifohfull_level: in integer:= 7;
|
86 |
|
|
fifo_length: in integer:= 8);
|
87 |
|
|
port (
|
88 |
|
|
hresetn: in std_logic;
|
89 |
|
|
clk: in std_logic;
|
90 |
|
|
fifo_reset: in std_logic;
|
91 |
|
|
fifo_write: in std_logic;
|
92 |
|
|
fifo_read: in std_logic;
|
93 |
|
|
fifo_count: out std_logic_vector(nb_bits(fifo_length)-1 downto 0);
|
94 |
|
|
fifo_full: out std_logic;
|
95 |
|
|
fifo_hfull: out std_logic;
|
96 |
|
|
fifo_empty: out std_logic;
|
97 |
|
|
fifo_hempty: out std_logic;
|
98 |
|
|
fifo_datain: in std_logic_vector(31 downto 0);
|
99 |
|
|
fifo_dataout: out std_logic_vector(31 downto 0)
|
100 |
|
|
);
|
101 |
|
|
end component;
|
102 |
|
|
|
103 |
|
|
|
104 |
|
|
|
105 |
|
|
--***************************************************************
|
106 |
|
|
--configuration registers
|
107 |
|
|
--***************************************************************
|
108 |
|
|
signal start_hprot: std_logic_vector(3 downto 0);
|
109 |
|
|
signal start_hsize: std_logic_Vector(2 downto 0);
|
110 |
|
|
signal start_hburst: std_logic_Vector(2 downto 0);
|
111 |
|
|
signal start_hwrite: std_logic;
|
112 |
|
|
signal start_hlocked: std_logic;
|
113 |
|
|
signal start_prior: std_logic;
|
114 |
|
|
|
115 |
|
|
signal hbusreq_t, hlock_t: std_logic;
|
116 |
|
|
--***************************************************************
|
117 |
|
|
--***************************************************************
|
118 |
|
|
signal r_mst_in, s_mst_in: mst_in_t;
|
119 |
|
|
signal r_mst_out, s_mst_out: mst_out_t;
|
120 |
|
|
|
121 |
|
|
|
122 |
|
|
type master_fsm is (
|
123 |
|
|
idle_phase,
|
124 |
|
|
wait_phase,
|
125 |
|
|
req_phase,
|
126 |
|
|
addr, --A
|
127 |
|
|
addr_data,--A+D
|
128 |
|
|
data, --D
|
129 |
|
|
retry_phase,
|
130 |
|
|
error_phase,
|
131 |
|
|
be_phase);
|
132 |
|
|
signal mst_state, s_mst_state: master_fsm;
|
133 |
|
|
|
134 |
|
|
|
135 |
|
|
signal fifo_full, fifo_hfull, fifo_empty, fifo_hempty: std_logic;
|
136 |
|
|
signal fifo_count: std_logic_vector(nb_bits(fifo_length)-1 downto 0);
|
137 |
|
|
signal fifo_datain, fifo_dataout: std_logic_vector (31 downto 0);
|
138 |
|
|
signal fifo_hread, fifo_hwrite: std_logic;
|
139 |
|
|
signal fifo_read, fifo_write: std_logic;
|
140 |
|
|
signal fifo_reset: std_logic;
|
141 |
|
|
signal next_fifo_empty: std_logic;
|
142 |
|
|
|
143 |
|
|
signal dma_count: std_logic_vector (15 downto 0);
|
144 |
|
|
signal dma_count_s : std_logic_vector (15 downto 0);
|
145 |
|
|
signal right_count: std_logic_vector(15 downto 0);
|
146 |
|
|
signal data_trx: std_logic;
|
147 |
|
|
signal tmp_htrans: std_logic_vector(1 downto 0);
|
148 |
|
|
|
149 |
|
|
|
150 |
|
|
signal next_fifo_full: std_logic;
|
151 |
|
|
signal next_fifo_he: std_logic;
|
152 |
|
|
signal next_fifo_hf: std_logic;
|
153 |
|
|
|
154 |
|
|
signal mst_running_t:std_logic;
|
155 |
|
|
signal dma_restart: std_logic;
|
156 |
|
|
signal mst_req: std_logic;
|
157 |
|
|
signal granted: std_logic;
|
158 |
|
|
|
159 |
|
|
signal eot_int_reg:std_logic;
|
160 |
|
|
signal prior_reg, prior_s: std_logic;
|
161 |
|
|
|
162 |
|
|
signal int_addr, int_addr_s, int_addr_t : std_logic_vector (31 downto 0);
|
163 |
|
|
signal int_mod, int_mod_s : std_logic_vector (15 downto 0);
|
164 |
|
|
signal int_page_fault: std_logic;
|
165 |
|
|
signal int_addr_incr: std_logic;
|
166 |
|
|
|
167 |
|
|
signal page_attention: std_logic;
|
168 |
|
|
signal page_fault: std_logic;
|
169 |
|
|
signal pf_incr, pf_wrap4, pf_wrap8, pf_wrap16: std_logic;
|
170 |
|
|
|
171 |
|
|
signal haddr_t : std_logic_vector (31 downto 0);
|
172 |
|
|
signal haddr_incr: std_logic;
|
173 |
|
|
|
174 |
|
|
signal old_page_attention: std_logic;
|
175 |
|
|
signal old_addr_incr: std_logic;
|
176 |
|
|
signal old_addr, old_addr_s: std_logic_vector (31 downto 0);
|
177 |
|
|
signal old_hburst, old_hburst_s: std_logic_Vector(2 downto 0);
|
178 |
|
|
|
179 |
|
|
begin
|
180 |
|
|
|
181 |
|
|
--***************************************************************
|
182 |
|
|
--component instantiation
|
183 |
|
|
--***************************************************************
|
184 |
|
|
fifo_inst: fifo
|
185 |
|
|
generic map(
|
186 |
|
|
fifohempty_level => fifohempty_level,
|
187 |
|
|
fifohfull_level => fifohfull_level,
|
188 |
|
|
fifo_length => fifo_length)
|
189 |
|
|
port map(
|
190 |
|
|
hresetn => hresetn,
|
191 |
|
|
clk => hclk,
|
192 |
|
|
fifo_reset => fifo_reset,
|
193 |
|
|
fifo_write => fifo_write,
|
194 |
|
|
fifo_read => fifo_read,
|
195 |
|
|
fifo_count => fifo_count,
|
196 |
|
|
fifo_full => fifo_full,
|
197 |
|
|
fifo_hfull => fifo_hfull,
|
198 |
|
|
fifo_empty => fifo_empty,
|
199 |
|
|
fifo_hempty => fifo_hempty,
|
200 |
|
|
fifo_datain => fifo_datain,
|
201 |
|
|
fifo_dataout => fifo_dataout
|
202 |
|
|
);
|
203 |
|
|
|
204 |
|
|
|
205 |
|
|
--***************************
|
206 |
|
|
--****** master state *******
|
207 |
|
|
--***************************
|
208 |
|
|
master_pr:process(
|
209 |
|
|
mst_state,
|
210 |
|
|
mst_req,
|
211 |
|
|
slv_running,
|
212 |
|
|
prior_reg,
|
213 |
|
|
dma_count,
|
214 |
|
|
hbusreq_t,
|
215 |
|
|
fifo_empty,
|
216 |
|
|
page_fault,
|
217 |
|
|
r_mst_out,
|
218 |
|
|
mst_in
|
219 |
|
|
)
|
220 |
|
|
begin
|
221 |
|
|
s_mst_state <= mst_state;
|
222 |
|
|
case mst_state is
|
223 |
|
|
when idle_phase =>
|
224 |
|
|
if (dma_count>0 and (slv_running='0' or prior_reg=master)) then
|
225 |
|
|
s_mst_state <= wait_phase;
|
226 |
|
|
end if;
|
227 |
|
|
when wait_phase =>
|
228 |
|
|
if mst_req='1' then
|
229 |
|
|
s_mst_state <= req_phase;
|
230 |
|
|
end if;
|
231 |
|
|
when req_phase =>
|
232 |
|
|
if (hbusreq_t='1' and mst_in.hgrant='1' and mst_in.hready='1') then--master take bus ownership
|
233 |
|
|
s_mst_state <= addr;
|
234 |
|
|
end if;
|
235 |
|
|
when addr =>
|
236 |
|
|
if (mst_in.hready='1') then
|
237 |
|
|
if (page_fault='1' or mst_in.hgrant='0' or dma_count=1) then
|
238 |
|
|
s_mst_state <= data;
|
239 |
|
|
else
|
240 |
|
|
s_mst_state <= addr_data;
|
241 |
|
|
end if;
|
242 |
|
|
end if;
|
243 |
|
|
when addr_data =>
|
244 |
|
|
--end of transfer: ready+ok+no_busy_reg+count=1(idle/preidle or burstend)
|
245 |
|
|
--page fault:ready+ok+no_busy_reg+count>1 (page_fault)
|
246 |
|
|
--no_grant:ready+ok+busy+no_grant (page_fault)
|
247 |
|
|
--retry/split:no_ready+retry/split (retry)
|
248 |
|
|
--error:no_ready+error (error)
|
249 |
|
|
if (mst_in.hready='1') then
|
250 |
|
|
if (mst_in.hresp=ok_resp) then
|
251 |
|
|
if (r_mst_out.htrans/=busy) then
|
252 |
|
|
if (dma_count=1) then
|
253 |
|
|
if (r_mst_out.hwrite='1') then
|
254 |
|
|
s_mst_state <= data;
|
255 |
|
|
else --r_mst_out.hwrite='0', count>1
|
256 |
|
|
s_mst_state <= data;--be_phase;
|
257 |
|
|
end if;
|
258 |
|
|
elsif (page_fault='1' or mst_in.hgrant='0') then
|
259 |
|
|
s_mst_state <= data;
|
260 |
|
|
end if;
|
261 |
|
|
else -- r_mst_out.htrans=busy
|
262 |
|
|
if (mst_in.hgrant='0') then
|
263 |
|
|
assert false report "Protocol error: GRANT deasserted during BUSY!!!" severity error;
|
264 |
|
|
s_mst_state <= data;
|
265 |
|
|
end if;
|
266 |
|
|
end if;
|
267 |
|
|
end if;
|
268 |
|
|
else--hready='0'
|
269 |
|
|
case mst_in.hresp is
|
270 |
|
|
when retry_resp|split_resp =>
|
271 |
|
|
s_mst_state <= retry_phase;
|
272 |
|
|
when error_resp =>
|
273 |
|
|
s_mst_state <= error_phase;
|
274 |
|
|
when others =>
|
275 |
|
|
s_mst_state <= addr_data;
|
276 |
|
|
end case;
|
277 |
|
|
end if;
|
278 |
|
|
when data=>
|
279 |
|
|
if (mst_in.hready='1') then
|
280 |
|
|
if (mst_in.hresp=ok_resp and r_mst_out.htrans/=busy) then
|
281 |
|
|
if (dma_count=0) then
|
282 |
|
|
if (r_mst_out.hwrite='1') then
|
283 |
|
|
s_mst_state <= idle_phase;
|
284 |
|
|
else --r_mst_out.hwrite='0', count>1
|
285 |
|
|
s_mst_state <= be_phase;
|
286 |
|
|
end if;
|
287 |
|
|
else--collapse all this 'if-else'
|
288 |
|
|
if (r_mst_out.hwrite='1') then
|
289 |
|
|
s_mst_state <= idle_phase;
|
290 |
|
|
else
|
291 |
|
|
s_mst_state <= be_phase;
|
292 |
|
|
end if;
|
293 |
|
|
end if;
|
294 |
|
|
end if;
|
295 |
|
|
else
|
296 |
|
|
case mst_in.hresp is
|
297 |
|
|
when retry_resp|split_resp =>
|
298 |
|
|
s_mst_state <= retry_phase;--pay attention: grant removed and retry issued!!!!!!
|
299 |
|
|
when error_resp =>
|
300 |
|
|
s_mst_state <= error_phase;
|
301 |
|
|
when others =>
|
302 |
|
|
s_mst_state <= data;
|
303 |
|
|
end case;
|
304 |
|
|
end if;
|
305 |
|
|
when retry_phase =>
|
306 |
|
|
if (mst_in.hready='1') then
|
307 |
|
|
s_mst_state <= idle_phase;
|
308 |
|
|
end if;
|
309 |
|
|
when error_phase =>
|
310 |
|
|
if mst_in.hready='1' then
|
311 |
|
|
s_mst_state <= idle_phase;
|
312 |
|
|
end if;
|
313 |
|
|
when be_phase =>--one of more cycle to empty fifo, settling core internal state
|
314 |
|
|
if (fifo_empty ='1') then
|
315 |
|
|
s_mst_state <= idle_phase;
|
316 |
|
|
end if;
|
317 |
|
|
when others => null;
|
318 |
|
|
end case;
|
319 |
|
|
end process;
|
320 |
|
|
|
321 |
|
|
--synopsys translate_off
|
322 |
|
|
assert not (hclk'event and hclk='1' and (mst_state=addr_data or mst_state=data) and (mst_in.hready='1' and mst_in.hresp/=ok_resp))
|
323 |
|
|
report "####PROTOCOL ERROR: in addr_data error/retry/split&&ready!!!!!"
|
324 |
|
|
severity error;
|
325 |
|
|
--synopsys translate_on
|
326 |
|
|
|
327 |
|
|
process(hresetn, hclk)
|
328 |
|
|
begin
|
329 |
|
|
if hresetn='0' then
|
330 |
|
|
mst_state <= idle_phase;
|
331 |
|
|
elsif hclk'event and hclk='1' then
|
332 |
|
|
mst_state <= s_mst_state after 1 ns;
|
333 |
|
|
end if;
|
334 |
|
|
end process;
|
335 |
|
|
|
336 |
|
|
|
337 |
|
|
start_hlocked <= dma_start.hparams(0);
|
338 |
|
|
start_hwrite <= dma_start.hparams(1);
|
339 |
|
|
start_hprot <= dma_start.hparams(5 downto 2);
|
340 |
|
|
start_hburst <= dma_start.hparams(8 downto 6);
|
341 |
|
|
start_hsize <= dma_start.hparams(11 downto 9);
|
342 |
|
|
start_prior <= dma_start.hparams(12);
|
343 |
|
|
|
344 |
|
|
--***************************
|
345 |
|
|
--********** htrans *********
|
346 |
|
|
--***************************
|
347 |
|
|
--busy if:
|
348 |
|
|
--write:
|
349 |
|
|
--count>1 and fifo=1 and trans_reg/=busy and addr_data
|
350 |
|
|
--count=1 and fifo_empty and addr_data
|
351 |
|
|
--read:
|
352 |
|
|
--fifo_hfull and addr_data
|
353 |
|
|
s_mst_out.htrans <= tmp_htrans;
|
354 |
|
|
|
355 |
|
|
tmp_htrans <=
|
356 |
|
|
--busy when (mst_state=addr_data and granted='1' and page_fault='0' and dma_count>=2 and ((next_fifo_he='1' and r_mst_out.hwrite='1') or (next_fifo_hf='1' and r_mst_out.hwrite='0'))) else
|
357 |
|
|
busy when (mst_state=addr_data and (
|
358 |
|
|
(dma_count>=2 and ((fifo_count<=1 and r_mst_out.hwrite='1') or (fifo_count>=fifo_length-1 and r_mst_out.hwrite='0'))) or
|
359 |
|
|
(dma_count=1 and ((fifo_count<=1 and r_mst_out.hwrite='1') or (fifo_count=fifo_length and r_mst_out.hwrite='0'))))) else
|
360 |
|
|
nonseq when (mst_state=addr) else
|
361 |
|
|
seq when (mst_state=addr_data) else
|
362 |
|
|
idle;
|
363 |
|
|
|
364 |
|
|
--***************************
|
365 |
|
|
--******** granted bus ******
|
366 |
|
|
--***************************
|
367 |
|
|
process(hclk, hresetn)
|
368 |
|
|
begin
|
369 |
|
|
if hresetn='0' then
|
370 |
|
|
granted <= '0';
|
371 |
|
|
elsif hclk'event and hclk='1' then
|
372 |
|
|
granted <= '0' after 1 ns;
|
373 |
|
|
if (mst_in.hready='1' and mst_in.hgrant='1') then
|
374 |
|
|
granted <= '1' after 1 ns;
|
375 |
|
|
end if;
|
376 |
|
|
end if;
|
377 |
|
|
end process;
|
378 |
|
|
|
379 |
|
|
next_fifo_empty <= '1' when ((fifo_count=0 and (fifo_write='0' or (fifo_write=fifo_read))) or (fifo_count=1 and fifo_read='1' and fifo_write='0')) else '0';
|
380 |
|
|
next_fifo_full <= '1' when ((fifo_count=fifo_length and (fifo_read='0' or (fifo_write=fifo_read))) or (fifo_count=fifo_length-1 and fifo_read='0' and fifo_write='1')) else '0';
|
381 |
|
|
next_fifo_he <= '1' when ((fifo_count<=1 and (fifo_write='0' or (fifo_write=fifo_read))) or (fifo_count=2 and fifo_read='1' and fifo_write='0')) else '0';
|
382 |
|
|
next_fifo_hf <= '1' when ((fifo_count>=fifo_length-1 and (fifo_read='0' or (fifo_write=fifo_read))) or (fifo_count=fifo_length-2 and fifo_read='0' and fifo_write='1')) else '0';
|
383 |
|
|
--next_count_ge2 <= '1' when ((dma_count_ge2='1' and fifo_hwrite='0' and fifo_hread='0') or (dma_count_ge3='1' and (fifo_hwrite='1' or fifo_hread='1'))) else '0';
|
384 |
|
|
|
385 |
|
|
--***************************
|
386 |
|
|
--********* old_hburst ******
|
387 |
|
|
--***************************
|
388 |
|
|
process(hclk, hresetn)
|
389 |
|
|
begin
|
390 |
|
|
if hresetn='0' then
|
391 |
|
|
old_hburst <= incr;
|
392 |
|
|
prior_reg <= slave;
|
393 |
|
|
elsif hclk'event and hclk='1' then
|
394 |
|
|
old_hburst <= old_hburst_s after 1 ns;
|
395 |
|
|
prior_reg <= prior_s after 1 ns;
|
396 |
|
|
end if;
|
397 |
|
|
end process;
|
398 |
|
|
old_hburst_s <= start_hburst when (dma_start.start='1') else old_hburst;
|
399 |
|
|
prior_s <= start_prior when (dma_start.start='1') else prior_reg;
|
400 |
|
|
|
401 |
|
|
--***************************
|
402 |
|
|
--***************************
|
403 |
|
|
process(hclk,hresetn)
|
404 |
|
|
begin
|
405 |
|
|
if hresetn='0' then
|
406 |
|
|
r_mst_out.haddr <= (others => '0');
|
407 |
|
|
r_mst_out.htrans <= "00";
|
408 |
|
|
r_mst_out.hlock <= '0';
|
409 |
|
|
r_mst_out.hwrite <= '0';
|
410 |
|
|
r_mst_out.hsize <= bits32;
|
411 |
|
|
r_mst_out.hburst <= incr;
|
412 |
|
|
r_mst_out.hprot <= "0011";
|
413 |
|
|
elsif hclk'event and hclk='1' then
|
414 |
|
|
r_mst_out.haddr <= s_mst_out.haddr after 1 ns;
|
415 |
|
|
r_mst_out.htrans <= s_mst_out.htrans after 1 ns;
|
416 |
|
|
r_mst_out.hlock <= s_mst_out.hlock after 1 ns;
|
417 |
|
|
r_mst_out.hwrite <= s_mst_out.hwrite after 1 ns;
|
418 |
|
|
r_mst_out.hsize <= s_mst_out.hsize after 1 ns;
|
419 |
|
|
r_mst_out.hburst <= s_mst_out.hburst after 1 ns;
|
420 |
|
|
r_mst_out.hprot <= s_mst_out.hprot after 1 ns;
|
421 |
|
|
end if;
|
422 |
|
|
end process;
|
423 |
|
|
|
424 |
|
|
|
425 |
|
|
s_mst_out.hlock <= start_hlocked when (dma_start.start='1') else r_mst_out.hlock;
|
426 |
|
|
s_mst_out.hwrite <= start_hwrite when (dma_start.start='1') else r_mst_out.hwrite;
|
427 |
|
|
s_mst_out.hsize <= start_hsize when (dma_start.start='1') else r_mst_out.hsize;
|
428 |
|
|
s_mst_out.hburst <= start_hburst when (dma_start.start='1') else incr when (dma_restart='1') else r_mst_out.hburst;
|
429 |
|
|
s_mst_out.hprot <= start_hprot when (dma_start.start='1') else r_mst_out.hprot;
|
430 |
|
|
|
431 |
|
|
mst_out.hlock <= hlock_t;
|
432 |
|
|
mst_out.hwrite <= r_mst_out.hwrite;
|
433 |
|
|
mst_out.hsize <= r_mst_out.hsize;
|
434 |
|
|
mst_out.hburst <= r_mst_out.hburst;
|
435 |
|
|
mst_out.hprot <= r_mst_out.hprot;
|
436 |
|
|
|
437 |
|
|
mst_out.haddr <= r_mst_out.haddr;
|
438 |
|
|
mst_out.hwdata <= fifo_dataout;--not retimed!
|
439 |
|
|
mst_out.hbusreq <= hbusreq_t;
|
440 |
|
|
mst_out.htrans <= s_mst_out.htrans;
|
441 |
|
|
|
442 |
|
|
|
443 |
|
|
--***************************
|
444 |
|
|
--********** haddr **********
|
445 |
|
|
--***************************
|
446 |
|
|
old_addr_pr:process(hclk, hresetn)
|
447 |
|
|
begin
|
448 |
|
|
if hresetn='0' then
|
449 |
|
|
old_addr <= (others => '0');
|
450 |
|
|
elsif hclk'event and hclk='1' then
|
451 |
|
|
old_addr <= old_addr_s after 1 ns;
|
452 |
|
|
end if;
|
453 |
|
|
end process;
|
454 |
|
|
|
455 |
|
|
old_addr_move:process(mst_state, mst_in, tmp_htrans, r_mst_out)
|
456 |
|
|
begin
|
457 |
|
|
if ((mst_state=addr or mst_state=addr_data or mst_state=data) and mst_in.hready='1' and tmp_htrans/=busy and r_mst_out.htrans/=busy) then
|
458 |
|
|
old_addr_incr <= '1';
|
459 |
|
|
else
|
460 |
|
|
old_addr_incr <= '0';
|
461 |
|
|
end if;
|
462 |
|
|
end process;
|
463 |
|
|
|
464 |
|
|
old_addr_s <= r_mst_out.haddr when (old_addr_incr='1') else
|
465 |
|
|
dma_start.extaddr when (dma_start.start='1') else
|
466 |
|
|
old_addr;
|
467 |
|
|
|
468 |
|
|
page_fault <= '1' when (page_attention='1' and (pf_incr='1' or pf_wrap4='1' or pf_wrap8='1' or pf_wrap16='1')) else '0';
|
469 |
|
|
|
470 |
|
|
pf_incr <= '1' when (haddr_t(9 downto 2)=0) else '0';
|
471 |
|
|
pf_wrap4 <= '1' when (haddr_t(3 downto 2)=0 and old_hburst=wrap4) else '0';
|
472 |
|
|
pf_wrap8 <= '1' when (haddr_t(4 downto 2)=0 and old_hburst=wrap8) else '0';
|
473 |
|
|
pf_wrap16 <= '1' when (haddr_t(5 downto 2)=0 and old_hburst=wrap16) else '0';
|
474 |
|
|
|
475 |
|
|
with r_mst_out.hburst select
|
476 |
|
|
page_attention <=
|
477 |
|
|
'1' when incr|incr4|incr8|incr16,
|
478 |
|
|
'0' when others;
|
479 |
|
|
|
480 |
|
|
with old_hburst select
|
481 |
|
|
old_page_attention <=
|
482 |
|
|
'1' when incr|incr4|incr8|incr16,
|
483 |
|
|
'0' when others;
|
484 |
|
|
|
485 |
|
|
with r_mst_out.hburst select
|
486 |
|
|
haddr_t(9 downto 2) <=
|
487 |
|
|
r_mst_out.haddr(9 downto 2)+1 when incr|incr4|incr8|incr16,
|
488 |
|
|
r_mst_out.haddr(9 downto 4)&(r_mst_out.haddr(3 downto 2)+"01") when wrap4,
|
489 |
|
|
r_mst_out.haddr(9 downto 5)&(r_mst_out.haddr(4 downto 2)+"001") when wrap8,
|
490 |
|
|
r_mst_out.haddr(9 downto 6)&(r_mst_out.haddr(5 downto 2)+"0001") when wrap16,
|
491 |
|
|
r_mst_out.haddr(9 downto 2) when others;--"000",
|
492 |
|
|
|
493 |
|
|
--page increment if:
|
494 |
|
|
--page fault and incr/incr4/incr8/incr16 and old_burst incr/incr4/incr8/incr16
|
495 |
|
|
s_mst_out.haddr(31 downto 10) <=
|
496 |
|
|
dma_start.extaddr(31 downto 10) when (dma_start.start='1') else
|
497 |
|
|
old_addr(31 downto 10) when (mst_state=retry_phase or mst_state=idle_phase) else
|
498 |
|
|
(r_mst_out.haddr(31 downto 10)+1) when (page_attention='1' and old_page_attention='1' and pf_incr='1' and haddr_incr='1') else
|
499 |
|
|
r_mst_out.haddr(31 downto 10);
|
500 |
|
|
|
501 |
|
|
s_mst_out.haddr(1 downto 0) <= dma_start.extaddr(1 downto 0) when (dma_start.start='1') else r_mst_out.haddr(1 downto 0);
|
502 |
|
|
|
503 |
|
|
s_mst_out.haddr(9 downto 2) <=
|
504 |
|
|
dma_start.extaddr(9 downto 2) when (dma_start.start='1') else
|
505 |
|
|
old_addr(9 downto 2) when (mst_state=retry_phase or mst_state=idle_phase) else
|
506 |
|
|
r_mst_out.haddr(9 downto 4)&"00" when (page_fault='1' and pf_wrap4='1' and haddr_incr='1') else
|
507 |
|
|
r_mst_out.haddr(9 downto 5)&"000" when (page_fault='1' and pf_wrap8='1' and haddr_incr='1') else
|
508 |
|
|
r_mst_out.haddr(9 downto 6)&"0000" when (page_fault='1' and pf_wrap16='1' and haddr_incr='1') else
|
509 |
|
|
haddr_t(9 downto 2) when (haddr_incr='1') else
|
510 |
|
|
r_mst_out.haddr(9 downto 2);
|
511 |
|
|
|
512 |
|
|
--haddr_incr_pr:process(mst_state, mst_in, tmp_htrans, r_mst_out)
|
513 |
|
|
--begin
|
514 |
|
|
-- if ((mst_state=addr or mst_state=addr_data) and mst_in.hready='1' and tmp_htrans/=busy and r_mst_out.htrans/=busy) then-- or mst_state=data
|
515 |
|
|
-- haddr_incr <= '1';
|
516 |
|
|
-- else
|
517 |
|
|
-- haddr_incr <= '0';
|
518 |
|
|
-- end if;
|
519 |
|
|
--end process;
|
520 |
|
|
|
521 |
|
|
--haddr_incr <= '1' when
|
522 |
|
|
--(mst_in.hready='1' and
|
523 |
|
|
--(tmp_htrans=nonseq or
|
524 |
|
|
--((tmp_htrans=seq or tmp_htrans=busy) and r_mst_out.htrans/=busy))) else '0';
|
525 |
|
|
haddr_incr <= '1' when
|
526 |
|
|
(mst_in.hready='1' and (tmp_htrans=nonseq or tmp_htrans=seq or tmp_htrans=busy) and r_mst_out.htrans/=busy) else '0';
|
527 |
|
|
|
528 |
|
|
--***************************
|
529 |
|
|
--********* hbusreq *********
|
530 |
|
|
--***************************
|
531 |
|
|
|
532 |
|
|
hbusreq_t <= '1' when
|
533 |
|
|
(
|
534 |
|
|
(dma_count>0 and mst_state=req_phase) or
|
535 |
|
|
(dma_count>1 and (mst_state=addr or mst_state=addr_data))
|
536 |
|
|
) else '0';
|
537 |
|
|
|
538 |
|
|
mst_req <= '1' when (r_mst_out.hwrite='0' or fifo_empty='0') else '0';
|
539 |
|
|
--start new master if:
|
540 |
|
|
--read or
|
541 |
|
|
--write and fifo_count>=2 or
|
542 |
|
|
--write and fifo_count=1 and dma_count=1
|
543 |
|
|
|
544 |
|
|
--***************************
|
545 |
|
|
--********** hlock *********
|
546 |
|
|
--***************************
|
547 |
|
|
hlock_t <= hbusreq_t and r_mst_out.hlock;--for hlock behaviour different wrt hbusreq change ONLY here!!
|
548 |
|
|
|
549 |
|
|
|
550 |
|
|
--***************************
|
551 |
|
|
--********* eot_int *********
|
552 |
|
|
--***************************
|
553 |
|
|
int_gen:process(hclk, hresetn)
|
554 |
|
|
begin
|
555 |
|
|
if hresetn='0' then
|
556 |
|
|
eot_int_reg <= '0';
|
557 |
|
|
elsif hclk'event and hclk='1' then
|
558 |
|
|
if (mst_state=idle_phase) then
|
559 |
|
|
eot_int_reg <= '0' after 1 ns;
|
560 |
|
|
elsif
|
561 |
|
|
(s_mst_state=idle_phase and mst_running_t='1' and dma_count_s=0) then
|
562 |
|
|
eot_int_reg <= '1' after 1 ns;
|
563 |
|
|
end if;
|
564 |
|
|
end if;
|
565 |
|
|
end process;
|
566 |
|
|
|
567 |
|
|
eot_int <= eot_int_reg;
|
568 |
|
|
|
569 |
|
|
|
570 |
|
|
--***************************
|
571 |
|
|
--****** mst_running *****
|
572 |
|
|
--***************************
|
573 |
|
|
mst_running_t <= '0' when (mst_state=idle_phase or mst_state=wait_phase or mst_state=req_phase) else '1';
|
574 |
|
|
mst_running <= mst_running_t;
|
575 |
|
|
|
576 |
|
|
|
577 |
|
|
--***************************
|
578 |
|
|
--******** dma_count ********
|
579 |
|
|
--***************************
|
580 |
|
|
dma_count_pr:process(hclk, hresetn)
|
581 |
|
|
begin
|
582 |
|
|
if hresetn='0' then
|
583 |
|
|
dma_count <= (others => '0');
|
584 |
|
|
elsif hclk'event and hclk='1' then
|
585 |
|
|
dma_count <= dma_count_s after 1 ns;
|
586 |
|
|
end if;
|
587 |
|
|
end process;
|
588 |
|
|
|
589 |
|
|
process(dma_start, start_hburst)
|
590 |
|
|
begin
|
591 |
|
|
if dma_start.start='1' then
|
592 |
|
|
case start_hburst is
|
593 |
|
|
when single =>
|
594 |
|
|
right_count(15 downto 0) <= "0000000000000001";
|
595 |
|
|
when incr =>
|
596 |
|
|
right_count(15 downto 0) <= dma_start.count;
|
597 |
|
|
when wrap4|incr4 =>
|
598 |
|
|
right_count(15 downto 0) <= "0000000000000100";
|
599 |
|
|
when wrap8|incr8 =>
|
600 |
|
|
right_count(15 downto 0) <= "0000000000001000" ;
|
601 |
|
|
when others =>--wrap16|incr16
|
602 |
|
|
right_count(15 downto 0) <= "0000000000010000";
|
603 |
|
|
end case;
|
604 |
|
|
else
|
605 |
|
|
right_count(15 downto 0) <= (others => '-');
|
606 |
|
|
end if;
|
607 |
|
|
end process;
|
608 |
|
|
|
609 |
|
|
dma_count_s <=
|
610 |
|
|
(others=>'0') when fifo_reset='1' else
|
611 |
|
|
-- dma_count-1 when (r_mst_out.hwrite='1' and fifo_hread='1') or (r_mst_out.hwrite='0' and fifo_hwrite='1') else
|
612 |
|
|
dma_count-1 when ((mst_state=addr or mst_state=addr_data) and haddr_incr='1') else
|
613 |
|
|
dma_count+1 when (mst_state=retry_phase and mst_in.hready='1') else
|
614 |
|
|
right_count when (dma_start.start='1') else
|
615 |
|
|
dma_count;
|
616 |
|
|
|
617 |
|
|
dma_restart <= '1' when (mst_state=retry_phase or mst_state=data) else '0';
|
618 |
|
|
|
619 |
|
|
fifo_reset <= '1' when (
|
620 |
|
|
(mst_state=error_phase) or
|
621 |
|
|
(mst_in.hresp=ok_resp and r_mst_out.htrans/=busy and r_mst_out.hwrite='1' and mst_in.hready='1' and mst_state=data and dma_count=0)
|
622 |
|
|
) else '0';
|
623 |
|
|
|
624 |
|
|
|
625 |
|
|
--***************************
|
626 |
|
|
--***** fifo interface ******
|
627 |
|
|
--***************************
|
628 |
|
|
fifo_write <= fifo_hwrite or m_wrap_in.ask_ok;
|
629 |
|
|
fifo_read <= fifo_hread or m_wrap_in.take_ok;
|
630 |
|
|
|
631 |
|
|
fifo_datain <= mst_in.hrdata when (fifo_hwrite='1') else m_wrap_in.rdata;
|
632 |
|
|
m_wrap_out.wdata <= fifo_dataout;
|
633 |
|
|
|
634 |
|
|
--transfer master => fifo
|
635 |
|
|
fifo_hwrite <= '1' when (r_mst_out.hwrite='0' and data_trx='1' and fifo_full='0') else '0';
|
636 |
|
|
|
637 |
|
|
--transfer fifo => master
|
638 |
|
|
fifo_hread <= '1' when (r_mst_out.hwrite='1' and data_trx='1' and fifo_empty='0') else '0';
|
639 |
|
|
|
640 |
|
|
|
641 |
|
|
data_trx <= '1' when (mst_in.hready='1' and mst_in.hresp=ok_resp and r_mst_out.htrans/=busy and (mst_state=addr_data or mst_state=data)) else '0';
|
642 |
|
|
|
643 |
|
|
--***********************************************
|
644 |
|
|
--master<=>core interface: program/data memories
|
645 |
|
|
--***********************************************
|
646 |
|
|
|
647 |
|
|
--transfer fifo => core
|
648 |
|
|
m_wrap_out.take <= '1' when (r_mst_out.hwrite='0' and fifo_empty='0') else '0';
|
649 |
|
|
|
650 |
|
|
--transfer core => fifo
|
651 |
|
|
m_wrap_out.ask <= '1' when (r_mst_out.hwrite='1' and fifo_full='0' and (mst_running_t='1' or dma_count/=0)) else '0';
|
652 |
|
|
|
653 |
|
|
m_wrap_out.addr <= int_addr;
|
654 |
|
|
|
655 |
|
|
|
656 |
|
|
process(hclk, hresetn)
|
657 |
|
|
begin
|
658 |
|
|
if hresetn='0' then
|
659 |
|
|
int_addr <= (others => '0');
|
660 |
|
|
int_mod <= (others => '0');
|
661 |
|
|
elsif hclk'event and hclk='1' then
|
662 |
|
|
int_addr <= int_addr_s after 1 ns;
|
663 |
|
|
int_mod <= int_mod_s after 1 ns;
|
664 |
|
|
end if;
|
665 |
|
|
end process;
|
666 |
|
|
|
667 |
|
|
int_mod_s <= dma_start.intmod when (dma_start.start='1') else int_mod;
|
668 |
|
|
|
669 |
|
|
int_page_fault <= '1' when (int_addr_t(9 downto 2)=0 and page_attention='1') else '0';
|
670 |
|
|
|
671 |
|
|
with r_mst_out.hburst select
|
672 |
|
|
int_addr_t(9 downto 2) <=
|
673 |
|
|
int_addr(9 downto 2)+int_mod(9 downto 2) when incr|incr4|incr8|incr16,
|
674 |
|
|
int_addr(9 downto 4)&(int_addr(3 downto 2)+"01") when wrap4,
|
675 |
|
|
int_addr(9 downto 5)&(int_addr(4 downto 2)+"001") when wrap8,
|
676 |
|
|
int_addr(9 downto 6)&(int_addr(5 downto 2)+"0001") when wrap16,
|
677 |
|
|
int_addr(9 downto 2) when others;--"000",
|
678 |
|
|
|
679 |
|
|
int_addr_incr <= '1' when ((r_mst_out.hwrite='0' and m_wrap_in.take_ok='1') or (r_mst_out.hwrite='1' and m_wrap_in.ask_ok='1')) else '0';
|
680 |
|
|
|
681 |
|
|
int_addr_s(31 downto 16) <= (others => '0');
|
682 |
|
|
int_addr_s(15 downto 10) <= (int_addr(15 downto 10)+1) when (int_page_fault='1' and int_addr_incr='1') else dma_start.intaddr(15 downto 10) when (dma_start.start='1') else int_addr(15 downto 10);
|
683 |
|
|
int_addr_s(1 downto 0) <= dma_start.intaddr(1 downto 0) when (dma_start.start='1') else int_addr(1 downto 0);
|
684 |
|
|
int_addr_s(9 downto 2) <= int_addr_t(9 downto 2) when (int_addr_incr='1') else dma_start.intaddr(9 downto 2) when (dma_start.start='1') else int_addr(9 downto 2);
|
685 |
|
|
|
686 |
|
|
|
687 |
|
|
end rtl;
|