Subversion Repositories ngs

Rev

Rev 99 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
98 lvd 1
// part of NeoGS project
2
//
3
// (c) NedoPC 2013
4
//
5
// mp3 data dma controller
6
 
7
module dma_mp3
8
(
9
        input  wire clk,
10
        input  wire rst_n,
11
 
12
        output wire [ 7:0] md_din,   // mp3 data interface
13
        output wire        md_start, //
14
        input  wire        md_rdy,   //
15
        input  wire        md_dreq,  //
16
 
17
 
18
        // signals for ports.v
19
        //
20
        input  wire [7:0] din,  // input and output from ports.v
21
        output reg  [7:0] dout,
22
        //
23
        input  wire       module_select, // =1 - module selected for read-write operations from ports.v
24
        input  wire       write_strobe,  // one-cycle positive write strobe - writes to the selected registers from din
25
        //
26
        input  wire [1:0] regsel, // 2'b00 - high address, 2'b01 - middle address, 2'b10 - low address, 2'b11 - control register
27
 
28
 
29
        // signals for DMA controller/DMA sequencer
30
        //
31
        output reg  [21:0] dma_addr,
99 lvd 32
        input  wire  [7:0] dma_rd,   // data read from DMA
98 lvd 33
        output wire        dma_rnw,
34
        //
35
        output reg         dma_req,
36
        input  wire        dma_ack,
37
        input  wire        dma_end,
38
 
39
        output wire        int_req
40
);
41
        reg dma_on;
42
 
43
        wire dma_finish;
44
 
45
        wire w511;
99 lvd 46
        wire rdone;
98 lvd 47
 
48
        reg [3:0] state,next_state;
49
 
50
 
51
        assign int_req = dma_finish;
52
 
53
        assign dma_rnw = 1'b1;
54
 
55
 
56
 
57
 
58
 
59
        localparam _HAD = 2'b00; // high address
60
        localparam _MAD = 2'b01; // mid address
61
        localparam _LAD = 2'b10; // low address
62
        localparam _CST = 2'b11; // control and status
63
 
64
        // control dout bus
65
        always @*
66
        case( regsel[1:0] )
67
                _HAD: dout = { 2'b00,  dma_addr[21:16] };
68
                _MAD: dout =           dma_addr[15:8];
69
                _LAD: dout =           dma_addr[7:0];
70
                _CST: dout = { dma_on, 7'bXXX_XXXX };
71
        endcase
72
 
73
        // dma_on control
74
        always @(posedge clk, negedge rst_n)
75
        if( !rst_n )
76
                dma_on <= 1'b0;
77
        else if( dma_finish )
78
                dma_on <= 1'b0;
79
        else if( module_select && write_strobe && (regsel==_CST) )
80
                dma_on <= din[7];
81
 
82
        // dma_addr control
83
        always @(posedge clk)
84
        if( dma_req && dma_ack && dma_on )
85
                dma_addr <= dma_addr + 22'd1; // increment on successfull DMA transfer
86
        else if( module_select && write_strobe )
87
        begin
88
                if( regsel==_HAD )
89
                        dma_addr[21:16] <= din[5:0];
90
                else if( regsel==_MAD )
91
                        dma_addr[15:8]  <= din[7:0];
92
                else if( regsel==_LAD )
93
                        dma_addr[7:0]   <= din[7:0];
94
        end
95
 
96
 
97
 
98
 
99
        localparam _IDLE  = 4'd0;
100
        localparam _START = 4'd1;
101
        localparam _DMARD = 4'd2;
102
        localparam _MP3W1 = 4'd3;
103
        localparam _MP3W2 = 4'd4;
104
        localparam _MP3W3 = 4'd5;
105
        localparam _STOP  = 4'd6;
106
 
107
 
108
        always @(posedge clk, negedge dma_on)
109
        if( !dma_on )
110
                state <= _IDLE;
111
        else
112
                state <= next_state;
113
 
114
        always @*
115
        case( state )
116
        _IDLE: next_state = _START;
117
 
118
        _START: next_state = _DMARD;
119
 
120
        _DMARD:begin
121
                if( dma_req )
122
                        next_state = _DMARD;
123
                else
124
                        next_state = _MP3W1;
125
        end
126
 
127
        _MP3W1: next_state = _MP3W2;
128
 
129
        _MP3W2:begin
130
                if( md_rdy && md_dreq )
131
                        next_state = _MP3W3;
132
                else
133
                        next_state = _MP3W2;
134
        end
135
 
101 lvd 136
        _MP3W3:begin
137
                if( rdone )
138
                        next_state = _STOP;
139
                else
140
                        next_state = _MP3W2;
141
        end
98 lvd 142
 
143
        _STOP: next_state = _STOP;
144
 
145
        endcase
146
 
147
 
148
        assign md_start = ( state==_MP3W3 );
149
 
150
        assign dma_finish = ( state==_STOP );
151
 
152
 
153
 
154
        always @(posedge clk, negedge dma_on)
155
        if( !dma_on )
156
                dma_req <= 1'b0;
157
        else if( state==_START )
158
                dma_req <= 1'b1;
159
        else if( dma_ack && w511 )
160
                dma_req <= 1'b0;
161
 
162
 
163
 
164
 
165
        dma_fifo_oneshot dma_fifo_oneshot
166
        (
167
                .clk  (clk   ),
168
                .rst_n(dma_on),
169
 
170
                .wr_stb( dma_end  ),
171
                .rd_stb( md_start || state==_MP3W1 ),
172
 
99 lvd 173
                .wdone(     ),
98 lvd 174
                .rdone(rdone),
175
                .empty(     ),
176
                .w511 (w511 ),
177
 
178
                .wd(dma_rd),
179
                .rd(md_din)
180
        );
181
 
182
 
183
endmodule
184