OpenCores
URL https://opencores.org/ocsvn/mips_enhanced/mips_enhanced/trunk

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [gaisler/] [pci/] [dmactrl.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dimamali
------------------------------------------------------------------------------
2
--  This file is a part of the GRLIB VHDL IP LIBRARY
3
--  Copyright (C) 2003, Gaisler Research
4
--
5
--  This program is free software; you can redistribute it and/or modify
6
--  it under the terms of the GNU General Public License as published by
7
--  the Free Software Foundation; either version 2 of the License, or
8
--  (at your option) any later version.
9
--
10
--  This program is distributed in the hope that it will be useful,
11
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
--  GNU General Public License for more details.
14
--
15
--  You should have received a copy of the GNU General Public License
16
--  along with this program; if not, write to the Free Software
17
--  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
18
-----------------------------------------------------------------------------
19
-- Entity:  dmactrl
20
-- File:  dmactrl.vhd
21
-- Author:  Alf Vaerneus - Gaisler Research
22
-- Modified:  Nils-Johan Wessman - Gaisler Research
23
-- Description: Simple DMA controller
24
------------------------------------------------------------------------------
25
 
26
library ieee;
27
use ieee.std_logic_1164.all;
28
library grlib;
29
use grlib.amba.all;
30
use grlib.stdlib.all;
31
use grlib.devices.all;
32
library gaisler;
33
use gaisler.misc.all;
34
use gaisler.pci.all;
35
 
36
entity dmactrl is
37
  generic (
38
    hindex    : integer := 0;
39
    slvindex  : integer := 0;
40
    pindex    : integer := 0;
41
    paddr     : integer := 0;
42
    pmask     : integer := 16#fff#;
43
    blength   : integer := 4
44
  );
45
  port (
46
    rst       : in std_logic;
47
    clk       : in std_logic;
48
    apbi      : in apb_slv_in_type;
49
    apbo      : out apb_slv_out_type;
50
    ahbmi     : in ahb_mst_in_type;
51
    ahbmo     : out ahb_mst_out_type;
52
    ahbsi0    : in ahb_slv_in_type;
53
    ahbso0    : out ahb_slv_out_type;
54
    ahbsi1    : out ahb_slv_in_type;
55
    ahbso1    : in ahb_slv_out_type
56
  );
57
end;
58
 
59
architecture rtl of dmactrl is
60
 
61
constant BURST_LENGTH : integer := blength;
62
constant REVISION : integer := 0;
63
 
64
constant pconfig : apb_config_type := (
65
 
66
  1 => apb_iobar(paddr, pmask));
67
 
68
type state_type is(idle, read1, read2, read3, read4, read5, write1, write2, writeb, write3, write4, turn);
69
type rbuf_type is array (0 to 2) of std_logic_vector(31 downto 0);
70
type dmactrl_reg_type is record
71
  state     : state_type;
72
  addr0     : std_logic_vector(31 downto 2);
73
  addr1     : std_logic_vector(31 downto 2);
74
  hmbsel    : std_logic_vector(0 to NAHBAMR-1);
75
  htrans    : std_logic_vector(1 downto 0);
76
  rbuf      : rbuf_type;
77
  write     : std_logic;
78
  start_req : std_logic;
79
  start     : std_logic;
80
  ready     : std_logic;
81
  err       : std_logic;
82
  first0    : std_logic;
83
  first1    : std_logic;
84
  no_ws     : std_logic; -- no wait states
85
  blimit    : std_logic; -- 1k limit
86
  dmao_start: std_logic;
87
  two_in_buf: std_logic; -- two words in rbuf to be stored
88
  burstl_p  : std_logic_vector(BURST_LENGTH - 1 downto 0); -- pci access counter
89
  burstl_a  : std_logic_vector(BURST_LENGTH - 1 downto 0); -- amba access counter
90
  ahb0_htrans : std_logic_vector(1 downto 0);
91
  ahb0_hready : std_logic;
92
  ahb0_retry  : std_logic;
93
  ahb0_hsel   : std_logic;
94
  start_del   : std_logic;
95
end record;
96
 
97
signal r,rin : dmactrl_reg_type;
98
signal dmai : ahb_dma_in_type;
99
signal dmao : ahb_dma_out_type;
100
 
101
begin
102
 
103
   comb : process(rst,r,dmao,apbi,ahbsi0,ahbso1)
104
   variable v : dmactrl_reg_type;
105
   variable vdmai : ahb_dma_in_type;
106
   variable pdata : std_logic_vector(31 downto 0);
107
   variable slvbusy : ahb_slv_out_type;
108
   variable dma_done, pci_done : std_logic;
109
   variable bufloc : integer range 0 to 2;
110
   begin
111
 
112
   slvbusy := ahbso1; v := r;
113
   vdmai.burst := '1'; vdmai.address := r.addr0 & "00";
114
   vdmai.write := not r.write; vdmai.start := '0'; vdmai.size := "10";
115
   vdmai.wdata := r.rbuf(0); pdata := (others => '0');
116
   vdmai.busy := '0'; vdmai.irq := '0';
117
   bufloc := 0;
118
 
119
 
120
   v.start_del := r.start;
121
   slvbusy.hready := '1'; slvbusy.hindex := hindex; --slvbusy.hresp := "00"; 
122
   v.ahb0_htrans := ahbsi0.htrans; v.ahb0_retry := '0';
123
   v.ahb0_hsel := ahbsi0.hsel(slvindex); v.ahb0_hready := ahbsi0.hready;
124
 
125
   -- AMBA busy response when dma is running 
126
   if r.ahb0_retry = '1' then slvbusy.hresp := "10";
127
   else slvbusy.hresp := "00"; end if;
128
 
129
   if r.ahb0_htrans = "10" and (r.start = '1') and r.ahb0_hsel = '1' and r.ahb0_hready = '1' then
130
      slvbusy.hready := '0';
131
      slvbusy.hresp := "10";
132
      v.ahb0_retry := '1';
133
   end if;
134
 
135
   -- Done signals
136
   if (r.burstl_a(BURST_LENGTH - 1 downto 1) = zero32(BURST_LENGTH - 1 downto 1)) then -- AMBA access done
137
     dma_done := '1'; else dma_done := '0'; end if;
138
 
139
   if (r.burstl_p(BURST_LENGTH - 1 downto 1) = zero32(BURST_LENGTH - 1 downto 1)) then -- PCI access done
140
     pci_done := '1'; else pci_done := '0'; end if;
141
 
142
   -- APB interface
143
   if (apbi.psel(pindex) and apbi.penable) = '1' then
144
      case apbi.paddr(4 downto 2) is
145
      when "000" =>
146
         if apbi.pwrite = '1' then
147
            v.start_req := apbi.pwdata(0);
148
            v.write := apbi.pwdata(1);
149
            v.ready := r.ready and not apbi.pwdata(2);
150
            v.err := r.err and not apbi.pwdata(3);
151
            v.hmbsel := apbi.pwdata(7 downto 4);
152
         end if;
153
         pdata := zero32(31 downto 8) & r.hmbsel & r.err & r.ready & r.write & r.start_req;
154
      when "001" =>
155
         if apbi.pwrite = '1' then v.addr0 := apbi.pwdata(31 downto 2); end if;
156
         pdata := r.addr0 & "00";
157
      when "010" =>
158
         if apbi.pwrite = '1' then v.addr1 := apbi.pwdata(31 downto 2); end if;
159
         pdata := r.addr1 & "00";
160
      when "011" =>
161
         if apbi.pwrite = '1' then
162
            v.burstl_p := apbi.pwdata(BURST_LENGTH - 1 downto 0);
163
            v.burstl_a := apbi.pwdata(BURST_LENGTH - 1 downto 0);
164
         end if;
165
         pdata := zero32(31 downto BURST_LENGTH) & r.burstl_p;
166
      when others =>
167
      end case;
168
   end if;
169
 
170
   -- can't start dma until AMBA slave is idle
171
   if r.start_req = '1' and (ahbsi0.hready = '1' and (ahbsi0.htrans = "00" or ahbsi0.hsel(slvindex) = '0')) then
172
      v.start := '1';
173
   end if;
174
 
175
 
176
   case r.state is
177
   when idle =>
178
      v.htrans := "00";
179
      v.first0 := '1'; v.first1 := '1';
180
      v.no_ws := '0'; v.dmao_start := '0'; v.blimit := '0';
181
      if r.start = '1' then
182
         if r.write = '0' then v.state := read1;
183
         else v.state := write1; end if;
184
      end if;
185
   when read1 => -- Start PCI read
186
      bufloc := 0;
187
      v.htrans := "10";
188
      if ahbso1.hready = '1' and ahbso1.hresp = HRESP_OKAY then
189
         if r.htrans(1) = '1' then
190
            if pci_done = '1' then
191
               v.htrans := "00";
192
               v.state := read5;
193
            else
194
               v.htrans := "11";
195
               v.state := read2;
196
            end if;
197
         end if;
198
      elsif ahbso1.hready = '0' then
199
         v.htrans := "11";
200
      else
201
         v.htrans := "00";
202
      end if;
203
   when read2 => -- fill rbuf (3 words)
204
      if r.first1 = '1' then bufloc := 1; -- store 3 words
205
      else bufloc := 2; end if;
206
 
207
      if ahbso1.hready = '1' and ahbso1.hresp = HRESP_OKAY then
208
         if r.htrans = "11" then
209
            v.first1 := '0';
210
            if pci_done = '1' then
211
               v.htrans := "00";
212
               v.state := read5;
213
            elsif r.first1 = '0' then
214
               v.htrans := "01";
215
               v.state := read3;
216
               v.first0 := '1';
217
            end if;
218
         end if;
219
      end if;
220
   when read3 => -- write to AMBA and read from PCI
221
      vdmai.start := '1';
222
      bufloc := 1;
223
 
224
      if (dmao.ready and dmao.start) = '1' then bufloc := 1; v.no_ws := '1'; -- no wait state on AMBA ?
225
      else
226
         bufloc := 2;
227
         if dmao.active = '1' then v.no_ws := '0'; end if;
228
      end if;
229
 
230
      if dmao.active = '0' then v.blimit := '1';
231
      else v.blimit := '0'; end if;
232
 
233
      if dmao.ready = '1' then
234
         v.first0 := '0';
235
         v.htrans := "11";
236
      else
237
         v.htrans := "01";
238
      end if;
239
 
240
      if r.htrans(1) = '1' and ahbso1.hready = '1' and ahbso1.hresp = HRESP_OKAY and pci_done = '1' then
241
         v.state := read5;
242
         v.htrans := "00";
243
      elsif r.htrans(1) = '1' and ahbso1.hready = '0' and ahbso1.hresp = HRESP_RETRY then
244
         if dmao.active = '0' then v.two_in_buf := '1'; end if; -- two words in rbuf to store
245
         v.state := read4;
246
         v.htrans := "01";
247
      end if;
248
   when read4 => -- PCI retry
249
      bufloc := 1;
250
      if dmao.ready = '1' then v.two_in_buf := '0'; end if;
251
 
252
      if dmao.start = '1' and r.two_in_buf = '0' then v.dmao_start := '1'; end if;
253
 
254
      if r.no_ws = '1' and r.dmao_start = '1' then vdmai.start := '0';
255
      elsif dmao.start = '1' and r.two_in_buf = '0' then v.no_ws := '1'; vdmai.start := '0';
256
      else vdmai.start := '1'; end if;
257
 
258
      --if dmao.ready = '1' and r.no_ws = '1' and r.two_in_buf = '0' then -- handle change of waitstates (sdram refresh)
259
      if (dmao.ready = '1' or (dmao.active = '0' and r.dmao_start = '1')) and r.no_ws = '1' and r.two_in_buf = '0' then
260
         v.first0 := '1';
261
         v.first1 := '1';
262
         v.no_ws := '0';
263
         v.dmao_start := '0';
264
         v.state := read1;
265
      end if;
266
   when read5 => -- PCI read done
267
      if dmao.start = '1' then v.first0 := '0'; -- first amba access
268
      elsif dmao.active = '0' then v.first0 := '1'; end if; -- 1k limit
269
 
270
      if dma_done = '0' or (r.first0 = '1' and dmao.start = '0') then vdmai.start := '1'; end if;
271
 
272
      if (dmao.ready and dmao.start) = '1' then bufloc := 1; v.no_ws := '1'; -- no wait state on AMBA ?
273
      else bufloc := 2; end if;
274
 
275
      if dmao.ready = '1' and dma_done = '1' then
276
         v.state  := turn;
277
      end if;
278
   when write1 => -- Read first from AMBA
279
      bufloc := 0;
280
      v.first1 := '1'; v.no_ws := '0';
281
 
282
      if dmao.start = '1' then v.first0 := '0'; -- first amba access
283
      elsif dmao.active = '0' then v.first0 := '1'; end if; -- 1k limit
284
 
285
      if dma_done = '1' and (r.first0 = '0' or dmao.start = '1') then vdmai.start := '0';
286
      else vdmai.start := '1'; end if;
287
 
288
      if dmao.ready = '1' then
289
         if dma_done = '1' then v.state := write4;
290
         else v.state := write2; end if;
291
         v.htrans := "10"; -- start access to PCI
292
      end if;
293
   when write2 => -- Read from AMBA and write to PCI
294
      bufloc := 0;
295
      if (dmao.ready and dmao.start) = '1' then v.no_ws := '1'; end if; -- no wait state on AMBA ?
296
 
297
      if dmao.start = '1' then v.first0 := '0'; -- first amba access
298
      elsif dmao.active = '0' then v.first0 := '1'; end if; -- 1k limit
299
 
300
      if dmao.ready = '1' then -- Data ready write to PCI 
301
         v.htrans := "11";
302
         if dma_done = '1' then
303
            v.state := write4;
304
         end if;
305
      else v.htrans := "01"; end if;
306
 
307
      if ahbso1.hready = '0' then
308
         vdmai.start := '0';
309
         if v.no_ws = '1' then bufloc := 1; end if;
310
         if dmao.active = '0' then v.state := writeb; -- AMBA 1k limit
311
         else v.state := write3; end if;
312
      elsif dma_done = '0' or (r.first0 = '1' and dmao.start = '0') then
313
         vdmai.start := '1';
314
      end if;
315
   when writeb => -- AMBA 1k limit and PCI retry
316
      bufloc := 1;
317
      if dmao.active = '1' then vdmai.start := '0';
318
      else vdmai.start := '1'; end if;
319
 
320
      if dmao.ready = '1' then v.state := write3; end if;
321
   when write3 => -- Retry from PCI
322
      bufloc := 1;
323
      --if ahbso1.hready = '1' then v.htrans := "10"; -- wait for AMBA access to be done before retry 
324
      if (ahbso1.hready and (dmao.ready or not dmao.active)) = '1' then v.htrans := "10";
325
      else v.htrans := "01"; end if;
326
      if r.htrans(1) = '1' and ahbso1.hready = '1' and ahbso1.hresp = HRESP_OKAY then
327
         if pci_done = '1' then
328
            v.htrans := "00";
329
            v.state := turn;
330
         elsif dma_done = '1' and r.burstl_a(0) = '0' then
331
            v.htrans := "01";
332
            v.state := write4;
333
         else
334
            v.htrans := "11";
335
            v.first0 := '1';
336
            v.state := write2;
337
         end if;
338
      end if;
339
   when write4 => -- Done read AMBA
340
      v.htrans := "11";
341
      if pci_done = '1' and ahbso1.hready = '1' and r.htrans(1) = '1' then
342
         v.htrans := "00";
343
         v.state := turn;
344
      elsif ahbso1.hready = '0' then
345
         v.state := write3;
346
         v.htrans := "01";
347
      end if;
348
   when turn =>
349
      v.htrans := "00";
350
      -- can't switch off dma until AMBA slave is idle
351
      if (ahbsi0.hsel(slvindex) = '0' and r.ahb0_retry = '0' and ahbsi0.hready = '1')
352
          or (ahbsi0.htrans = "00" and ahbsi0.hready = '1') or r.ahb0_retry = '1' then
353
         v.ready := '1'; v.first1 := '1'; v.start_req := '0';
354
         v.start := '0'; v.state := idle;
355
      end if;
356
   end case;
357
 
358
   if ((r.htrans(1) and ahbso1.hready) = '1' and ahbso1.hresp = HRESP_OKAY) then -- PCI access done
359
      v.burstl_p := r.burstl_p - '1'; -- dec counter
360
      v.addr1 := r.addr1 + '1'; -- inc address (PCI)
361
      if (r.write = '0' or r.state = write4 or r.state = write3) then
362
         if r.state /= read1 and r.state /= read2 and (v.no_ws = '1' or r.state = write3) and v.blimit = '0' then
363
            v.rbuf(0) := r.rbuf(1);                                     -- dont update if wait states
364
            v.rbuf(1) := r.rbuf(2);                                     -- 
365
         end if;
366
         if r.write = '0' then v.rbuf(bufloc) := ahbso1.hrdata; end if; -- PCI to AMBA 
367
      end if;                                                           -- if wait states store in buf(2) else
368
   end if;                                                              -- in buf(1). Frist word in buf(0)    
369
 
370
   if dmao.ready = '1' then -- AMBA access done
371
      v.burstl_a := r.burstl_a - '1'; -- dec counter
372
      v.addr0 := r.addr0 + 1; -- inc address (AMBA master)
373
      if r.write = '1' then
374
         if r.state /= write3 and bufloc = 0 then -- dont update if retry from PCI
375
            v.rbuf(0) := r.rbuf(1);
376
            v.rbuf(1) := r.rbuf(2);
377
         end if;
378
         v.rbuf(bufloc) := dmao.rdata; -- AMBA to PCI
379
      elsif r.write = '0' and (r.first0 = '1' or v.state = read4 or r.state = read5 or (v.no_ws = '0' or r.blimit = '1')) then
380
         v.rbuf(0) := r.rbuf(1); -- update when data is written if wait states or PCI retry or PCI done
381
         v.rbuf(1) := r.rbuf(2);
382
      end if;
383
   end if;
384
 
385
   if (ahbso1.hresp = HRESP_ERROR or (dmao.mexc or dmao.retry) = '1') then
386
      v.err := '1'; v.state := turn; v.htrans := HTRANS_IDLE;
387
   end if;
388
 
389
   --cancel dma
390
   if r.start = '1' and r.start_req = '0' then
391
      v.state := turn;
392
   end if;
393
 
394
   if rst = '0' then
395
      v.state := idle;
396
      v.start := '0';
397
      v.start_req := '0';
398
      v.write := '0';
399
      v.err := '0';
400
      v.ready := '0';
401
      v.first1 := '1';
402
      v.two_in_buf := '0';
403
      v.hmbsel := (others => '0');
404
      v.addr1 := (others => '0');
405
   end if;
406
 
407
 
408
   if r.start = '1' then -- new *** ???
409
      ahbsi1.hsel <= (others => '1');
410
      ahbsi1.hmbsel(0 to 3) <= r.hmbsel;
411
      ahbsi1.hsize <= "010";
412
      ahbsi1.hwrite <= r.write;
413
      ahbsi1.htrans <= v.htrans;
414
--      ahbsi1.haddr <= r.addr1 & "00";
415
      ahbsi1.haddr <= v.addr1 & "00";
416
      ahbsi1.hburst <= "001";
417
      ahbsi1.hwdata <= r.rbuf(0);
418
      ahbsi1.hready <= ahbso1.hready;
419
      ahbsi1.hmaster <= conv_std_logic_vector(hindex,4);
420
      ahbso0 <= slvbusy;
421
   else
422
      ahbsi1.hsel <= ahbsi0.hsel;
423
      ahbsi1.hmbsel(0 to 3) <= ahbsi0.hmbsel(0 to 3);
424
      ahbsi1.hsize <= ahbsi0.hsize;
425
      ahbsi1.hwrite <= ahbsi0.hwrite;
426
      ahbsi1.htrans <= ahbsi0.htrans;
427
      ahbsi1.haddr <= ahbsi0.haddr;
428
      ahbsi1.hburst <= ahbsi0.hburst;
429
      ahbsi1.hwdata <= ahbsi0.hwdata;
430
      ahbsi1.hready <= ahbsi0.hready;
431
      ahbsi1.hmaster <= ahbsi0.hmaster;
432
      ahbso0 <= ahbso1;
433
 
434
      v.state := idle;
435
   end if;
436
 
437
   dmai <= vdmai;
438
   rin <= v;
439
   apbo.pconfig <= pconfig;
440
   apbo.prdata <= pdata;
441
   apbo.pirq <= (others => '0');
442
   apbo.pindex <= pindex;
443
   ahbsi1.hirq <= (others => '0');
444
   ahbsi1.hprot <= (others => '0');
445
   ahbsi1.hmastlock <= '0';
446
   ahbsi1.hcache <= '0';
447
 
448
   end process;
449
 
450
   cpur : process (clk)
451
   begin
452
      if rising_edge (clk) then
453
         r <= rin;
454
      end if;
455
   end process;
456
 
457
   ahbmst0 : pciahbmst generic map (hindex => hindex, devid => GAISLER_DMACTRL, incaddr => 1)
458
   port map (rst, clk, dmai, dmao, ahbmi, ahbmo);
459
 
460
-- pragma translate_off
461
    bootmsg : report_version
462
    generic map ("dmactrl" & tost(pindex) &
463
        ": 32-bit DMA controller & AHB/AHB bridge  rev " & tost(REVISION));
464
-- pragma translate_on
465
 
466
end;
467
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.