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

Subversion Repositories ata

[/] [ata/] [trunk/] [rtl/] [vhdl/] [ocidec3/] [atahost_dma_actrl.vhd] - Blame information for rev 35

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 rherveille
---------------------------------------------------------------------
2
----                                                             ----
3
----  OpenCores IDE Controller                                   ----
4
----  DMA (single- and multiword) mode access controller         ----
5
----                                                             ----
6
----  Author: Richard Herveille                                  ----
7
----          richard@asics.ws                                   ----
8
----          www.asics.ws                                       ----
9
----                                                             ----
10
---------------------------------------------------------------------
11
----                                                             ----
12
---- Copyright (C) 2001, 2002 Richard Herveille                  ----
13
----                          richard@asics.ws                   ----
14
----                                                             ----
15
---- This source file may be used and distributed without        ----
16
---- restriction provided that this copyright statement is not   ----
17
---- removed from the file and that any derivative work contains ----
18
---- the original copyright notice and the associated disclaimer.----
19
----                                                             ----
20
----     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ----
21
---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ----
22
---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ----
23
---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ----
24
---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ----
25
---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ----
26
---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ----
27
---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ----
28
---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ----
29
---- LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ----
30
---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ----
31
---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ----
32
---- POSSIBILITY OF SUCH DAMAGE.                                 ----
33
----                                                             ----
34
---------------------------------------------------------------------
35
 
36
-- rev.: 1.0 march 9th, 2001. Initial release
37
--
38
--  CVS Log
39
--
40
--  $Id: atahost_dma_actrl.vhd,v 1.1 2002-02-18 14:32:12 rherveille Exp $
41
--
42
--  $Date: 2002-02-18 14:32:12 $
43
--  $Revision: 1.1 $
44
--  $Author: rherveille $
45
--  $Locker:  $
46
--  $State: Exp $
47
--
48
-- Change History:
49
--               $Log: not supported by cvs2svn $
50
--
51
--
52
 
53
 
54
-- Host accesses to DMA ports are 32bit wide. Accesses are made by 2 consecutive 16bit accesses to the ATA
55
-- device's DataPort. The MSB HostData(31:16) is transfered first, then the LSB HostData(15:0) is transfered.
56
 
57
--
58
---------------------------
59
-- DMA Access Controller --
60
---------------------------
61
--
62
library ieee;
63
use ieee.std_logic_1164.all;
64
use ieee.std_logic_arith.all;
65
 
66
entity atahost_dma_actrl is
67
        generic(
68
                TWIDTH : natural := 8;                     -- counter width
69
 
70
                -- DMA mode 0 settings (@100MHz clock)
71
                DMA_mode0_Tm : natural := 4;               -- 50ns
72
                DMA_mode0_Td : natural := 21;              -- 215ns
73
                DMA_mode0_Teoc : natural := 21             -- 215ns ==> T0 - Td - Tm = 480 - 50 - 215 = 215
74
        );
75
        port(
76
                clk : in std_logic;                           -- master clock
77
                nReset : in std_logic;                        -- asynchronous active low reset
78
                rst : in std_logic;                           -- synchronous active high reset
79
 
80
                IDEctrl_rst : in std_logic;                   -- IDE control register bit0, 'rst'
81
 
82
                sel : in std_logic;                           -- DMA buffers selected
83
                we : in std_logic;                            -- write enable input
84
                ack : out std_logic;                                    -- acknowledge output
85
 
86
                dev0_Tm,
87
                dev0_Td,
88
                dev0_Teoc : in unsigned(7 downto 0);          -- DMA mode timing device 0
89
                dev1_Tm,
90
                dev1_Td,
91
                dev1_Teoc : in unsigned(7 downto 0);          -- DMA mode timing device 1
92
 
93
                DMActrl_DMAen,
94
                DMActrl_dir,
95
                DMActrl_BeLeC0,
96
                DMActrl_BeLeC1 : in std_logic;                -- control register settings
97
 
98
                TxD : in std_logic_vector(31 downto 0);       -- DMA transmit data
99
                TxFull : buffer std_logic;                    -- DMA transmit buffer full
100
                RxQ : out std_logic_vector(31 downto 0);      -- DMA receive data
101
                RxEmpty : buffer std_logic;                   -- DMA receive buffer empty
102
                RxFull : out std_logic;                       -- DMA receive buffer full
103
                DMA_req : out std_logic;                      -- DMA request to external DMA engine
104
                DMA_ack : in std_logic;                       -- DMA acknowledge from external DMA engine
105
 
106
                DMARQ : in std_logic;                         -- ATA devices request DMA transfer
107
 
108
                SelDev : in std_logic;                        -- Selected device        
109
 
110
                Go : in std_logic;                            -- Start transfer sequence
111
                Done : out std_logic;                         -- Transfer sequence done
112
 
113
                DDi : in std_logic_vector(15 downto 0);       -- Data from ATA DD bus
114
                DDo : out std_logic_vector(15 downto 0);      -- Data towards ATA DD bus
115
 
116
                DIOR,
117
                DIOW : buffer std_logic
118
        );
119
end entity atahost_dma_actrl;
120
 
121
architecture structural of atahost_dma_actrl is
122
        --
123
        -- component declarations
124
        --
125
        component atahost_dma_tctrl is
126
        generic(
127
                TWIDTH : natural := 8;            -- counter width
128
 
129
                -- DMA mode 0 settings (@100MHz clock)
130
                DMA_mode0_Tm : natural := 6;     -- 70ns
131
                DMA_mode0_Td : natural := 28;    -- 290ns
132
                DMA_mode0_Teoc : natural := 23   -- 240ns ==> T0 - T1 - T2 = 600 - 70 - 290 = 240
133
        );
134
        port(
135
                clk : in std_logic;                      -- master clock
136
                nReset : in std_logic;                   -- asynchronous active low reset
137
                rst : in std_logic;                      -- synchronous active high reset
138
 
139
                -- timing register settings
140
                Tm : in unsigned(TWIDTH -1 downto 0);    -- Tm time (in clk-ticks)
141
                Td : in unsigned(TWIDTH -1 downto 0);    -- Td time (in clk-ticks)
142
                Teoc : in unsigned(TWIDTH -1 downto 0);  -- end of cycle time
143
 
144
                -- control signals
145
                go : in std_logic;                       -- DMA controller selected (strobe signal)
146
                we : in std_logic;                       -- DMA direction '1' = write, '0' = read
147
 
148
                -- return signals
149
                done : out std_logic;                    -- finished cycle
150
                dstrb : out std_logic;                   -- data strobe
151
 
152
                -- ATA signals
153
                DIOR,                                    -- IOread signal, active high
154
                DIOW : buffer std_logic                  -- IOwrite signal, active high
155
        );
156
        end component atahost_dma_tctrl;
157
 
158
        component atahost_reg_buf is
159
        generic (
160
                WIDTH : natural := 8
161
        );
162
        port(
163
                clk : in std_logic;
164
                nReset : in std_logic;
165
                rst : in std_logic;
166
 
167
                D : in std_logic_vector(WIDTH -1 downto 0);
168
                Q : out std_logic_vector(WIDTH -1 downto 0);
169
                rd : in std_logic;
170
                wr : in std_logic;
171
                valid : buffer std_logic
172
        );
173
        end component atahost_reg_buf;
174
 
175
        component atahost_fifo is
176
        generic(
177
                DEPTH : natural := 32;                      -- fifo depth
178
                SIZE : natural := 32                        -- data width
179
        );
180
        port(
181
                clk : in std_logic;                         -- master clock in
182
                nReset : in std_logic := '1';               -- asynchronous active low reset
183
                rst : in std_logic := '0';                  -- synchronous active high reset
184
 
185
                rreq : in std_logic;                        -- read request
186
                wreq : in std_logic;                        -- write request
187
 
188
                empty : out std_logic;                      -- fifo empty
189
                full : out std_logic;                       -- fifo full
190
 
191
                D : in std_logic_vector(SIZE -1 downto 0);  -- data input
192
                Q : out std_logic_vector(SIZE -1 downto 0)  -- data output
193
        );
194
        end component atahost_fifo;
195
 
196
        signal Tdone, Tfw : std_logic;
197
        signal RxWr, TxRd : std_logic;
198
        signal dstrb, rd_dstrb, wr_dstrb : std_logic;
199
        signal TxbufQ, RxbufD : std_logic_vector(31 downto 0);
200
 
201
begin
202
 
203
        -- note: *fw = *first_word, *lw = *last_word
204
 
205
 
206
        --
207
        -- generate DDi/DDo controls
208
        --
209
        gen_DMA_sigs: block
210
                signal writeDfw, writeDlw : std_logic_vector(15 downto 0);
211
                signal readDfw, readDlw : std_logic_vector(15 downto 0);
212
                signal BeLeC : std_logic; -- BigEndian <-> LittleEndian conversion
213
        begin
214
                -- generate byte_swap signal
215
                BeLeC <=        (not SelDev and DMActrl_BeLeC0) or (SelDev and DMActrl_BeLeC1);
216
 
217
                -- generate Tfw (Transfering first word)
218
                gen_Tfw: process(clk, nReset)
219
                begin
220
                        if (nReset = '0') then
221
                                Tfw <= '0';
222
                        elsif (clk'event and clk = '1') then
223
                                if (rst = '1') then
224
                                        Tfw <= '0';
225
                                else
226
                                        Tfw <= go or (Tfw and not Tdone);
227
                                end if;
228
                        end if;
229
                end process gen_Tfw;
230
 
231
                -- transmit data part
232
                gen_writed_pipe:process(clk)
233
                begin
234
                        if (clk'event and clk = '1') then
235
                                if (TxRd = '1') then                              -- reload registers
236
                                        if (BeLeC = '1') then                           -- Do big<->little endian conversion
237
                                                writeDfw(15 downto 8) <= TxbufQ( 7 downto  0); -- TxbufQ = data from transmit buffer
238
                                                writeDfw( 7 downto 0) <= TxbufQ(15 downto  8);
239
                                                writeDlw(15 downto 8) <= TxbufQ(23 downto 16);
240
                                                writeDlw( 7 downto 0) <= TxbufQ(31 downto 24);
241
                                        else                                              -- don't do big<->little endian conversion
242
                                                writeDfw <= TxbufQ(31 downto 16);
243
                                                writeDlw <= TxbufQ(15 downto 0);
244
                                        end if;
245
                                elsif (wr_dstrb = '1') then                          -- next word to transfer
246
                                        writeDfw <= writeDlw;
247
                                end if;
248
                        end if;
249
                end process gen_writed_pipe;
250
                DDo <= writeDfw;                                       -- assign DMA data out
251
 
252
                -- generate transmit register read request
253
                gen_Tx_rreq: process(clk, nReset)
254
                begin
255
                        if (nReset = '0') then
256
                                TxRd <= '0';
257
                        elsif (clk'event and clk = '1') then
258
                                if (rst = '1') then
259
                                        TxRd <= '0';
260
                                else
261
                                        TxRd <= go and DMActrl_dir;
262
                                end if;
263
                        end if;
264
                end process gen_Tx_rreq;
265
 
266
                -- receive
267
                gen_readd_pipe:process(clk)
268
                begin
269
                        if (clk'event and clk = '1') then
270
                                if (rd_dstrb = '1') then
271
 
272
                                        readDfw <= readDlw;                   -- shift previous read word to msb
273
                                        if (BeLeC = '1') then                 -- swap bytes
274
                                                readDlw(15 downto 8) <= DDi( 7 downto 0);
275
                                                readDlw( 7 downto 0) <= DDi(15 downto 8);
276
                                        else                                  -- don't swap bytes
277
                                                readDlw <= DDi;
278
                                        end if;
279
                                end if;
280
                        end if;
281
                end process gen_readd_pipe;
282
                -- RxD = data to receive buffer
283
                RxbufD <= (readDfw & readDlw) when (BeLeC = '0') else (readDlw & readDfw);
284
 
285
                -- generate receive register write request
286
                gen_Rx_wreq: process(clk, nReset)
287
                begin
288
                        if (nReset = '0') then
289
                                RxWr <= '0';
290
                        elsif (clk'event and clk = '1') then
291
                                if (rst = '1') then
292
                                        RxWr <= '0';
293
                                else
294
                                        RxWr <= not Tfw and rd_dstrb;
295
                                end if;
296
                        end if;
297
                end process gen_Rx_wreq;
298
        end block gen_DMA_sigs;
299
 
300
 
301
        --
302
        -- Hookup DMA read / write buffers
303
        --
304
        gen_DMAbuf: block
305
                signal DMArst : std_logic;
306
                signal RxRd, TxWr : std_logic;
307
                signal iRxEmpty : std_logic;
308
        begin
309
                -- generate DMA reset signal
310
                DMArst <= rst or IDEctrl_rst;
311
 
312
                Txbuf: atahost_reg_buf
313
                        generic map (WIDTH => 32)
314
                        port map (
315
                                clk    => clk,
316
                                nReset => nReset,
317
                                rst    => DMArst,
318
                                D      => TxD,
319
                                Q      => TxbufQ,
320
                                rd     => TxRd,
321
                                wr     => TxWr,
322
                                valid  =>       TxFull
323
                        );
324
 
325
                Rxbuf: atahost_fifo
326
                        generic map (DEPTH => 7, SIZE => 32)
327
                        port map (
328
                                clk    => clk,
329
                                nReset => nReset,
330
                                rst    => DMArst,
331
                                D      => RxbufD,
332
                                Q      => RxQ,
333
                                rreq   => RxRd,
334
                                wreq   => RxWr,
335
                                empty  =>       iRxEmpty,
336
                                full   => RxFull
337
                        );
338
 
339
                RxEmpty <= iRxEmpty; -- avoid 'cannot associate OUT port with BUFFER port' error
340
 
341
                --
342
                -- generate DMA buffer access signals
343
                --
344
                RxRd <= sel and not we and not RxEmpty;
345
                TxWr <= sel and     we and not TxFull;
346
 
347
                ack  <= RxRd or TxWr; -- DMA buffer access acknowledge
348
        end block gen_DMAbuf;
349
 
350
        --
351
        -- generate request signal for external DMA engine
352
        --
353
        gen_DMA_req: block
354
                signal hgo : std_logic;
355
                signal iDMA_req : std_logic;
356
                signal request : std_logic;
357
        begin
358
                -- generate hold-go
359
                gen_hgo : process(clk, nReset)
360
                begin
361
                        if (nReset = '0') then
362
                                hgo <= '0';
363
                        elsif (clk'event and clk = '1') then
364
                                if (rst = '1') then
365
                                        hgo <= '0';
366
                                else
367
                                        hgo <= go or (hgo and not (wr_dstrb and not Tfw) and DMActrl_dir);
368
                                end if;
369
                        end if;
370
                end process gen_hgo;
371
 
372
                request <= (DMActrl_dir and DMARQ and not TxFull and not hgo) or not RxEmpty;
373
                process(clk, nReset)
374
                begin
375
                        if (nReset = '0') then
376
                                iDMA_req <= '0';
377
                        elsif (clk'event and clk = '1') then
378
                                if (rst = '1') then
379
                                        iDMA_req <= '0';
380
                                else
381
                                        iDMA_req <= DMActrl_DMAen and not DMA_ack and (request or iDMA_req);
382
--                              DMA_req <= (DMActrl_DMAen and DMActrl_dir and DMARQ and not TxFull and not hgo) or not RxEmpty;
383
                                end if;
384
                        end if;
385
                end process;
386
                DMA_req <= iDMA_req;
387
        end block gen_DMA_req;
388
 
389
 
390
        --
391
        -- DMA timing controller
392
        --
393
        DMA_timing_ctrl: block
394
                signal Tm, Td, Teoc, Tdmack_ext : unsigned(TWIDTH -1 downto 0);
395
                signal dTfw, igo : std_logic;
396
        begin
397
                --
398
                -- generate internal GO signal
399
                --
400
                gen_igo : process(clk, nReset)
401
                begin
402
                        if (nReset = '0') then
403
                                igo  <= '0';
404
                                dTfw <= '0';
405
                        elsif (clk'event and clk = '1') then
406
                                if (rst = '1') then
407
                                        igo  <= '0';
408
                                        dTfw <= '0';
409
                                else
410
                                        igo  <= go or (not Tfw and dTfw);
411
                                        dTfw <= Tfw;
412
                                end if;
413
                        end if;
414
                end process gen_igo;
415
 
416
                --
417
                -- select timing settings for the addressed device
418
                --
419
                sel_dev_t: process(clk)
420
                begin
421
                        if (clk'event and clk = '1') then
422
                                if (SelDev = '1') then                      -- device1 selected
423
                                        Tm   <= dev1_Tm;
424
                                        Td   <= dev1_Td;
425
                                        Teoc <= dev1_Teoc;
426
                                else                                        -- device0 selected
427
                                        Tm   <= dev0_Tm;
428
                                        Td   <= dev0_Td;
429
                                        Teoc <= dev0_Teoc;
430
                                end if;
431
                        end if;
432
                end process sel_dev_t;
433
 
434
                --
435
                -- hookup timing controller
436
                --
437
                DMA_timing_ctrl: atahost_dma_tctrl
438
                        generic map (
439
                                TWIDTH => TWIDTH,
440
                                DMA_mode0_Tm   => DMA_mode0_Tm,
441
                                DMA_mode0_Td   => DMA_mode0_Td,
442
                                DMA_mode0_Teoc => DMA_mode0_Teoc
443
                        )
444
                        port map (
445
                                clk    => clk,
446
                                nReset => nReset,
447
                                rst    => rst,
448
                                Tm     => Tm,
449
                                Td     => Td,
450
                                Teoc   => Teoc,
451
                                go     => igo,
452
                                we     => DMActrl_dir,
453
                                done   => Tdone,
454
                                dstrb  => dstrb,
455
                                DIOR   => dior,
456
                                DIOW   => diow
457
                        );
458
 
459
                done <= Tdone and not Tfw;             -- done transfering last word
460
                rd_dstrb <= dstrb and not DMActrl_dir; -- read data strobe
461
                wr_dstrb <= dstrb and     DMActrl_dir; -- write data strobe
462
        end block DMA_timing_ctrl;
463
 
464
end architecture structural;
465
 

powered by: WebSVN 2.1.0

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