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 |