1 |
2 |
fukuchi |
/////////////////////////////////////////////////////////////////////
|
2 |
|
|
//// ////
|
3 |
|
|
//// WISHBONE DMA DMA Engine Core ////
|
4 |
|
|
//// ////
|
5 |
|
|
//// ////
|
6 |
|
|
//// Author: Rudolf Usselmann ////
|
7 |
|
|
//// rudi@asics.ws ////
|
8 |
|
|
//// ////
|
9 |
|
|
//// ////
|
10 |
|
|
//// Downloaded from: http://www.opencores.org/cores/wb_dma/ ////
|
11 |
|
|
//// ////
|
12 |
|
|
/////////////////////////////////////////////////////////////////////
|
13 |
|
|
//// ////
|
14 |
|
|
//// Copyright (C) 2000-2002 Rudolf Usselmann ////
|
15 |
|
|
//// www.asics.ws ////
|
16 |
|
|
//// rudi@asics.ws ////
|
17 |
|
|
//// ////
|
18 |
|
|
//// This source file may be used and distributed without ////
|
19 |
|
|
//// restriction provided that this copyright statement is not ////
|
20 |
|
|
//// removed from the file and that any derivative work contains ////
|
21 |
|
|
//// the original copyright notice and the associated disclaimer.////
|
22 |
|
|
//// ////
|
23 |
|
|
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
|
24 |
|
|
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
|
25 |
|
|
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
|
26 |
|
|
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
|
27 |
|
|
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
|
28 |
|
|
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
|
29 |
|
|
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
|
30 |
|
|
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
|
31 |
|
|
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
|
32 |
|
|
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
|
33 |
|
|
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
|
34 |
|
|
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
|
35 |
|
|
//// POSSIBILITY OF SUCH DAMAGE. ////
|
36 |
|
|
//// ////
|
37 |
|
|
/////////////////////////////////////////////////////////////////////
|
38 |
|
|
|
39 |
|
|
// CVS Log
|
40 |
|
|
//
|
41 |
|
|
// $Id: wb_dma_de.v,v 1.1.1.1 2006-05-29 13:45:18 fukuchi Exp $
|
42 |
|
|
//
|
43 |
|
|
// $Date: 2006-05-29 13:45:18 $
|
44 |
|
|
// $Revision: 1.1.1.1 $
|
45 |
|
|
// $Author: fukuchi $
|
46 |
|
|
// $Locker: $
|
47 |
|
|
// $State: Exp $
|
48 |
|
|
//
|
49 |
|
|
// Change History:
|
50 |
|
|
// $Log: not supported by cvs2svn $
|
51 |
|
|
// Revision 1.3 2002/02/01 01:54:45 rudi
|
52 |
|
|
//
|
53 |
|
|
// - Minor cleanup
|
54 |
|
|
//
|
55 |
|
|
// Revision 1.2 2001/08/15 05:40:30 rudi
|
56 |
|
|
//
|
57 |
|
|
// - Changed IO names to be more clear.
|
58 |
|
|
// - Uniquifyed define names to be core specific.
|
59 |
|
|
// - Added Section 3.10, describing DMA restart.
|
60 |
|
|
//
|
61 |
|
|
// Revision 1.1 2001/07/29 08:57:02 rudi
|
62 |
|
|
//
|
63 |
|
|
//
|
64 |
|
|
// 1) Changed Directory Structure
|
65 |
|
|
// 2) Added restart signal (REST)
|
66 |
|
|
//
|
67 |
|
|
// Revision 1.3 2001/06/13 02:26:48 rudi
|
68 |
|
|
//
|
69 |
|
|
//
|
70 |
|
|
// Small changes after running lint.
|
71 |
|
|
//
|
72 |
|
|
// Revision 1.2 2001/06/05 10:22:36 rudi
|
73 |
|
|
//
|
74 |
|
|
//
|
75 |
|
|
// - Added Support of up to 31 channels
|
76 |
|
|
// - Added support for 2,4 and 8 priority levels
|
77 |
|
|
// - Now can have up to 31 channels
|
78 |
|
|
// - Added many configuration items
|
79 |
|
|
// - Changed reset to async
|
80 |
|
|
//
|
81 |
|
|
// Revision 1.1.1.1 2001/03/19 13:10:44 rudi
|
82 |
|
|
// Initial Release
|
83 |
|
|
//
|
84 |
|
|
//
|
85 |
|
|
//
|
86 |
|
|
|
87 |
|
|
`include "wb_dma_defines.v"
|
88 |
|
|
|
89 |
|
|
module wb_dma_de(clk, rst,
|
90 |
|
|
|
91 |
|
|
// WISHBONE MASTER INTERFACE 0
|
92 |
|
|
mast0_go, mast0_we, mast0_adr, mast0_din,
|
93 |
|
|
mast0_dout, mast0_err, mast0_drdy, mast0_wait,
|
94 |
|
|
|
95 |
|
|
// WISHBONE MASTER INTERFACE 1
|
96 |
|
|
mast1_go, mast1_we, mast1_adr, mast1_din,
|
97 |
|
|
mast1_dout, mast1_err, mast1_drdy, mast1_wait,
|
98 |
|
|
|
99 |
|
|
// DMA Engine Init & Setup
|
100 |
|
|
de_start, nd, csr, pointer, pointer_s, txsz,
|
101 |
|
|
adr0, adr1, am0, am1,
|
102 |
|
|
|
103 |
|
|
// DMA Engine Register File Update Outputs
|
104 |
|
|
de_csr_we, de_txsz_we, de_adr0_we, de_adr1_we, ptr_set,
|
105 |
|
|
de_csr, de_txsz, de_adr0, de_adr1, de_fetch_descr,
|
106 |
|
|
|
107 |
|
|
// DMA Engine Control Outputs
|
108 |
|
|
next_ch, de_ack,
|
109 |
|
|
|
110 |
|
|
// DMA Engine Status
|
111 |
|
|
pause_req, paused,
|
112 |
|
|
dma_abort, dma_busy, dma_err, dma_done, dma_done_all
|
113 |
|
|
);
|
114 |
|
|
|
115 |
|
|
input clk, rst;
|
116 |
|
|
|
117 |
|
|
// --------------------------------------
|
118 |
|
|
// WISHBONE MASTER INTERFACE 0
|
119 |
|
|
|
120 |
|
|
output mast0_go; // Perform a Master Cycle
|
121 |
|
|
output mast0_we; // Read/Write
|
122 |
|
|
output [31:0] mast0_adr; // Address for the transfer
|
123 |
|
|
input [31:0] mast0_din; // Internal Input Data
|
124 |
|
|
output [31:0] mast0_dout; // Internal Output Data
|
125 |
|
|
input mast0_err; // Indicates an error has occurred
|
126 |
|
|
input mast0_drdy; // Indicated that either data is available
|
127 |
|
|
// during a read, or that the master can accept
|
128 |
|
|
// the next data during a write
|
129 |
|
|
output mast0_wait; // Tells the master to insert wait cycles
|
130 |
|
|
// because data can not be accepted/provided
|
131 |
|
|
|
132 |
|
|
// --------------------------------------
|
133 |
|
|
// WISHBONE MASTER INTERFACE 1
|
134 |
|
|
|
135 |
|
|
output mast1_go; // Perform a Master Cycle
|
136 |
|
|
output mast1_we; // Read/Write
|
137 |
|
|
output [31:0] mast1_adr; // Address for the transfer
|
138 |
|
|
input [31:0] mast1_din; // Internal Input Data
|
139 |
|
|
output [31:0] mast1_dout; // Internal Output Data
|
140 |
|
|
input mast1_err; // Indicates an error has occurred
|
141 |
|
|
input mast1_drdy; // Indicated that either data is available
|
142 |
|
|
// during a read, or that the master can accept
|
143 |
|
|
// the next data during a write
|
144 |
|
|
output mast1_wait; // Tells the master to insert wait cycles
|
145 |
|
|
// because data can not be accepted/provided
|
146 |
|
|
|
147 |
|
|
// --------------------------------------
|
148 |
|
|
// DMA Engine Signals
|
149 |
|
|
|
150 |
|
|
// DMA Engine Init & Setup
|
151 |
|
|
input de_start; // Start DMA Engine Indicator
|
152 |
|
|
input nd; // Next Descriptor Indicator
|
153 |
|
|
input [31:0] csr; // Selected Channel CSR
|
154 |
|
|
input [31:0] pointer; // Linked List Descriptor pointer
|
155 |
|
|
input [31:0] pointer_s; // Previous Pointer
|
156 |
|
|
input [31:0] txsz; // Selected Channel Transfer Size
|
157 |
|
|
input [31:0] adr0, adr1; // Selected Channel Addresses
|
158 |
|
|
input [31:0] am0, am1; // Selected Channel Address Masks
|
159 |
|
|
|
160 |
|
|
// DMA Engine Register File Update Outputs
|
161 |
|
|
output de_csr_we; // Write enable for csr register
|
162 |
|
|
output de_txsz_we; // Write enable for txsz register
|
163 |
|
|
output de_adr0_we; // Write enable for adr0 register
|
164 |
|
|
output de_adr1_we; // Write enable for adr1 register
|
165 |
|
|
output ptr_set; // Set Pointer as Valid
|
166 |
|
|
output [31:0] de_csr; // Write Data for CSR when loading External Desc.
|
167 |
|
|
output [11:0] de_txsz; // Write back data for txsz register
|
168 |
|
|
output [31:0] de_adr0; // Write back data for adr0 register
|
169 |
|
|
output [31:0] de_adr1; // Write back data for adr1 register
|
170 |
|
|
output de_fetch_descr; // Indicates that we are fetching a descriptor
|
171 |
|
|
|
172 |
|
|
// DMA Engine Control Outputs
|
173 |
|
|
output next_ch; // Indicates the DMA Engine is done
|
174 |
|
|
output de_ack;
|
175 |
|
|
|
176 |
|
|
// DMA Abort from RF (software forced abort)
|
177 |
|
|
input dma_abort;
|
178 |
|
|
|
179 |
|
|
// DMA Engine Status
|
180 |
|
|
input pause_req;
|
181 |
|
|
output paused;
|
182 |
|
|
output dma_busy, dma_err, dma_done, dma_done_all;
|
183 |
|
|
|
184 |
|
|
////////////////////////////////////////////////////////////////////
|
185 |
|
|
//
|
186 |
|
|
// Local Wires
|
187 |
|
|
//
|
188 |
|
|
|
189 |
|
|
parameter [10:0] // synopsys enum state
|
190 |
|
|
IDLE = 11'b000_0000_0001,
|
191 |
|
|
READ = 11'b000_0000_0010,
|
192 |
|
|
WRITE = 11'b000_0000_0100,
|
193 |
|
|
UPDATE = 11'b000_0000_1000,
|
194 |
|
|
LD_DESC1 = 11'b000_0001_0000,
|
195 |
|
|
LD_DESC2 = 11'b000_0010_0000,
|
196 |
|
|
LD_DESC3 = 11'b000_0100_0000,
|
197 |
|
|
LD_DESC4 = 11'b000_1000_0000,
|
198 |
|
|
LD_DESC5 = 11'b001_0000_0000,
|
199 |
|
|
WB = 11'b010_0000_0000,
|
200 |
|
|
PAUSE = 11'b100_0000_0000;
|
201 |
|
|
|
202 |
|
|
reg [10:0] /* synopsys enum state */ state, next_state;
|
203 |
|
|
// synopsys state_vector state
|
204 |
|
|
|
205 |
|
|
reg [31:0] mast0_adr, mast1_adr;
|
206 |
|
|
|
207 |
|
|
reg [29:0] adr0_cnt, adr1_cnt;
|
208 |
|
|
wire [29:0] adr0_cnt_next, adr1_cnt_next;
|
209 |
|
|
wire [29:0] adr0_cnt_next1, adr1_cnt_next1;
|
210 |
|
|
reg adr0_inc, adr1_inc;
|
211 |
|
|
|
212 |
|
|
reg [8:0] chunk_cnt;
|
213 |
|
|
reg chunk_dec;
|
214 |
|
|
|
215 |
|
|
reg [11:0] tsz_cnt;
|
216 |
|
|
reg tsz_dec;
|
217 |
|
|
|
218 |
|
|
reg de_txsz_we;
|
219 |
|
|
reg de_csr_we;
|
220 |
|
|
reg de_adr0_we;
|
221 |
|
|
reg de_adr1_we;
|
222 |
|
|
reg ld_desc_sel;
|
223 |
|
|
|
224 |
|
|
wire chunk_cnt_is_0_d;
|
225 |
|
|
reg chunk_cnt_is_0_r;
|
226 |
|
|
wire tsz_cnt_is_0_d;
|
227 |
|
|
reg tsz_cnt_is_0_r;
|
228 |
|
|
|
229 |
|
|
reg read, write;
|
230 |
|
|
reg read_r, write_r;
|
231 |
|
|
wire rd_ack, wr_ack;
|
232 |
|
|
reg rd_ack_r;
|
233 |
|
|
|
234 |
|
|
reg chunk_0;
|
235 |
|
|
wire done;
|
236 |
|
|
reg dma_done_d;
|
237 |
|
|
reg dma_done_r;
|
238 |
|
|
reg dma_abort_r;
|
239 |
|
|
reg next_ch;
|
240 |
|
|
wire read_hold, write_hold;
|
241 |
|
|
reg write_hold_r;
|
242 |
|
|
|
243 |
|
|
reg [1:0] ptr_adr_low;
|
244 |
|
|
reg m0_go;
|
245 |
|
|
reg m0_we;
|
246 |
|
|
reg ptr_set;
|
247 |
|
|
|
248 |
|
|
// Aliases
|
249 |
|
|
wire a0_inc_en = csr[4]; // Source Address (Adr 0) increment enable
|
250 |
|
|
wire a1_inc_en = csr[3]; // Dest. Address (Adr 1) increment enable
|
251 |
|
|
wire ptr_valid = pointer[0];
|
252 |
|
|
wire use_ed = csr[`WDMA_USE_ED];
|
253 |
|
|
|
254 |
|
|
reg mast0_drdy_r;
|
255 |
|
|
reg paused;
|
256 |
|
|
|
257 |
|
|
reg de_fetch_descr; // Indicates that we are fetching a descriptor
|
258 |
|
|
////////////////////////////////////////////////////////////////////
|
259 |
|
|
//
|
260 |
|
|
// Misc Logic
|
261 |
|
|
//
|
262 |
|
|
|
263 |
|
|
always @(posedge clk)
|
264 |
|
|
dma_done_r <= #1 dma_done;
|
265 |
|
|
|
266 |
|
|
// Address Counter 0 (Source Address)
|
267 |
|
|
always @(posedge clk)
|
268 |
|
|
if(de_start | ptr_set) adr0_cnt <= #1 adr0[31:2];
|
269 |
|
|
else
|
270 |
|
|
if(adr0_inc & a0_inc_en) adr0_cnt <= #1 adr0_cnt_next;
|
271 |
|
|
|
272 |
|
|
// 30 Bit Incrementor (registered)
|
273 |
|
|
wb_dma_inc30r u0( .clk( clk ),
|
274 |
|
|
.in( adr0_cnt ),
|
275 |
|
|
.out( adr0_cnt_next1 ) );
|
276 |
|
|
|
277 |
|
|
assign adr0_cnt_next[1:0] = adr0_cnt_next1[1:0];
|
278 |
|
|
assign adr0_cnt_next[2] = am0[4] ? adr0_cnt_next1[2] : adr0_cnt[2];
|
279 |
|
|
assign adr0_cnt_next[3] = am0[5] ? adr0_cnt_next1[3] : adr0_cnt[3];
|
280 |
|
|
assign adr0_cnt_next[4] = am0[6] ? adr0_cnt_next1[4] : adr0_cnt[4];
|
281 |
|
|
assign adr0_cnt_next[5] = am0[7] ? adr0_cnt_next1[5] : adr0_cnt[5];
|
282 |
|
|
assign adr0_cnt_next[6] = am0[8] ? adr0_cnt_next1[6] : adr0_cnt[6];
|
283 |
|
|
assign adr0_cnt_next[7] = am0[9] ? adr0_cnt_next1[7] : adr0_cnt[7];
|
284 |
|
|
assign adr0_cnt_next[8] = am0[10] ? adr0_cnt_next1[8] : adr0_cnt[8];
|
285 |
|
|
assign adr0_cnt_next[9] = am0[11] ? adr0_cnt_next1[9] : adr0_cnt[9];
|
286 |
|
|
assign adr0_cnt_next[10] = am0[12] ? adr0_cnt_next1[10] : adr0_cnt[10];
|
287 |
|
|
assign adr0_cnt_next[11] = am0[13] ? adr0_cnt_next1[11] : adr0_cnt[11];
|
288 |
|
|
assign adr0_cnt_next[12] = am0[14] ? adr0_cnt_next1[12] : adr0_cnt[12];
|
289 |
|
|
assign adr0_cnt_next[13] = am0[15] ? adr0_cnt_next1[13] : adr0_cnt[13];
|
290 |
|
|
assign adr0_cnt_next[14] = am0[16] ? adr0_cnt_next1[14] : adr0_cnt[14];
|
291 |
|
|
assign adr0_cnt_next[15] = am0[17] ? adr0_cnt_next1[15] : adr0_cnt[15];
|
292 |
|
|
assign adr0_cnt_next[16] = am0[18] ? adr0_cnt_next1[16] : adr0_cnt[16];
|
293 |
|
|
assign adr0_cnt_next[17] = am0[19] ? adr0_cnt_next1[17] : adr0_cnt[17];
|
294 |
|
|
assign adr0_cnt_next[18] = am0[20] ? adr0_cnt_next1[18] : adr0_cnt[18];
|
295 |
|
|
assign adr0_cnt_next[19] = am0[21] ? adr0_cnt_next1[19] : adr0_cnt[19];
|
296 |
|
|
assign adr0_cnt_next[20] = am0[22] ? adr0_cnt_next1[20] : adr0_cnt[20];
|
297 |
|
|
assign adr0_cnt_next[21] = am0[23] ? adr0_cnt_next1[21] : adr0_cnt[21];
|
298 |
|
|
assign adr0_cnt_next[22] = am0[24] ? adr0_cnt_next1[22] : adr0_cnt[22];
|
299 |
|
|
assign adr0_cnt_next[23] = am0[25] ? adr0_cnt_next1[23] : adr0_cnt[23];
|
300 |
|
|
assign adr0_cnt_next[24] = am0[26] ? adr0_cnt_next1[24] : adr0_cnt[24];
|
301 |
|
|
assign adr0_cnt_next[25] = am0[27] ? adr0_cnt_next1[25] : adr0_cnt[25];
|
302 |
|
|
assign adr0_cnt_next[26] = am0[28] ? adr0_cnt_next1[26] : adr0_cnt[26];
|
303 |
|
|
assign adr0_cnt_next[27] = am0[29] ? adr0_cnt_next1[27] : adr0_cnt[27];
|
304 |
|
|
assign adr0_cnt_next[28] = am0[30] ? adr0_cnt_next1[28] : adr0_cnt[28];
|
305 |
|
|
assign adr0_cnt_next[29] = am0[31] ? adr0_cnt_next1[29] : adr0_cnt[29];
|
306 |
|
|
|
307 |
|
|
|
308 |
|
|
// Address Counter 1 (Destination Address)
|
309 |
|
|
always @(posedge clk)
|
310 |
|
|
if(de_start | ptr_set) adr1_cnt <= #1 adr1[31:2];
|
311 |
|
|
else
|
312 |
|
|
if(adr1_inc & a1_inc_en) adr1_cnt <= #1 adr1_cnt_next;
|
313 |
|
|
|
314 |
|
|
// 30 Bit Incrementor (registered)
|
315 |
|
|
wb_dma_inc30r u1( .clk( clk ),
|
316 |
|
|
.in( adr1_cnt ),
|
317 |
|
|
.out( adr1_cnt_next1 ) );
|
318 |
|
|
|
319 |
|
|
assign adr1_cnt_next[1:0] = adr1_cnt_next1[1:0];
|
320 |
|
|
assign adr1_cnt_next[2] = am1[4] ? adr1_cnt_next1[2] : adr1_cnt[2];
|
321 |
|
|
assign adr1_cnt_next[3] = am1[5] ? adr1_cnt_next1[3] : adr1_cnt[3];
|
322 |
|
|
assign adr1_cnt_next[4] = am1[6] ? adr1_cnt_next1[4] : adr1_cnt[4];
|
323 |
|
|
assign adr1_cnt_next[5] = am1[7] ? adr1_cnt_next1[5] : adr1_cnt[5];
|
324 |
|
|
assign adr1_cnt_next[6] = am1[8] ? adr1_cnt_next1[6] : adr1_cnt[6];
|
325 |
|
|
assign adr1_cnt_next[7] = am1[9] ? adr1_cnt_next1[7] : adr1_cnt[7];
|
326 |
|
|
assign adr1_cnt_next[8] = am1[10] ? adr1_cnt_next1[8] : adr1_cnt[8];
|
327 |
|
|
assign adr1_cnt_next[9] = am1[11] ? adr1_cnt_next1[9] : adr1_cnt[9];
|
328 |
|
|
assign adr1_cnt_next[10] = am1[12] ? adr1_cnt_next1[10] : adr1_cnt[10];
|
329 |
|
|
assign adr1_cnt_next[11] = am1[13] ? adr1_cnt_next1[11] : adr1_cnt[11];
|
330 |
|
|
assign adr1_cnt_next[12] = am1[14] ? adr1_cnt_next1[12] : adr1_cnt[12];
|
331 |
|
|
assign adr1_cnt_next[13] = am1[15] ? adr1_cnt_next1[13] : adr1_cnt[13];
|
332 |
|
|
assign adr1_cnt_next[14] = am1[16] ? adr1_cnt_next1[14] : adr1_cnt[14];
|
333 |
|
|
assign adr1_cnt_next[15] = am1[17] ? adr1_cnt_next1[15] : adr1_cnt[15];
|
334 |
|
|
assign adr1_cnt_next[16] = am1[18] ? adr1_cnt_next1[16] : adr1_cnt[16];
|
335 |
|
|
assign adr1_cnt_next[17] = am1[19] ? adr1_cnt_next1[17] : adr1_cnt[17];
|
336 |
|
|
assign adr1_cnt_next[18] = am1[20] ? adr1_cnt_next1[18] : adr1_cnt[18];
|
337 |
|
|
assign adr1_cnt_next[19] = am1[21] ? adr1_cnt_next1[19] : adr1_cnt[19];
|
338 |
|
|
assign adr1_cnt_next[20] = am1[22] ? adr1_cnt_next1[20] : adr1_cnt[20];
|
339 |
|
|
assign adr1_cnt_next[21] = am1[23] ? adr1_cnt_next1[21] : adr1_cnt[21];
|
340 |
|
|
assign adr1_cnt_next[22] = am1[24] ? adr1_cnt_next1[22] : adr1_cnt[22];
|
341 |
|
|
assign adr1_cnt_next[23] = am1[25] ? adr1_cnt_next1[23] : adr1_cnt[23];
|
342 |
|
|
assign adr1_cnt_next[24] = am1[26] ? adr1_cnt_next1[24] : adr1_cnt[24];
|
343 |
|
|
assign adr1_cnt_next[25] = am1[27] ? adr1_cnt_next1[25] : adr1_cnt[25];
|
344 |
|
|
assign adr1_cnt_next[26] = am1[28] ? adr1_cnt_next1[26] : adr1_cnt[26];
|
345 |
|
|
assign adr1_cnt_next[27] = am1[29] ? adr1_cnt_next1[27] : adr1_cnt[27];
|
346 |
|
|
assign adr1_cnt_next[28] = am1[30] ? adr1_cnt_next1[28] : adr1_cnt[28];
|
347 |
|
|
assign adr1_cnt_next[29] = am1[31] ? adr1_cnt_next1[29] : adr1_cnt[29];
|
348 |
|
|
|
349 |
|
|
// Chunk Counter
|
350 |
|
|
always @(posedge clk)
|
351 |
|
|
if(de_start) chunk_cnt <= #1 txsz[24:16];
|
352 |
|
|
else
|
353 |
|
|
if(chunk_dec & !chunk_cnt_is_0_r) chunk_cnt <= #1 chunk_cnt - 9'h1;
|
354 |
|
|
|
355 |
|
|
assign chunk_cnt_is_0_d = (chunk_cnt == 9'h0);
|
356 |
|
|
|
357 |
|
|
always @(posedge clk)
|
358 |
|
|
chunk_cnt_is_0_r <= #1 chunk_cnt_is_0_d;
|
359 |
|
|
|
360 |
|
|
// Total Size Counter
|
361 |
|
|
always @(posedge clk)
|
362 |
|
|
if(de_start | ptr_set) tsz_cnt <= #1 txsz[11:0];
|
363 |
|
|
else
|
364 |
|
|
if(tsz_dec & !tsz_cnt_is_0_r) tsz_cnt <= #1 tsz_cnt - 12'h1;
|
365 |
|
|
|
366 |
|
|
assign tsz_cnt_is_0_d = (tsz_cnt == 12'h0) & !txsz[15];
|
367 |
|
|
|
368 |
|
|
always @(posedge clk)
|
369 |
|
|
tsz_cnt_is_0_r <= #1 tsz_cnt_is_0_d;
|
370 |
|
|
|
371 |
|
|
// Counter Control Logic
|
372 |
|
|
always @(posedge clk)
|
373 |
|
|
chunk_dec <= #1 read & !read_r;
|
374 |
|
|
|
375 |
|
|
always @(posedge clk)
|
376 |
|
|
tsz_dec <= #1 read & !read_r;
|
377 |
|
|
|
378 |
|
|
//always @(posedge clk)
|
379 |
|
|
always @(rd_ack or read_r)
|
380 |
|
|
adr0_inc = rd_ack & read_r;
|
381 |
|
|
|
382 |
|
|
//always @(posedge clk)
|
383 |
|
|
always @(wr_ack or write_r)
|
384 |
|
|
adr1_inc = wr_ack & write_r;
|
385 |
|
|
|
386 |
|
|
// Done logic
|
387 |
|
|
always @(posedge clk)
|
388 |
|
|
chunk_0 <= #1 (txsz[24:16] == 9'h0);
|
389 |
|
|
|
390 |
|
|
assign done = chunk_0 ? tsz_cnt_is_0_d : (tsz_cnt_is_0_d | chunk_cnt_is_0_d);
|
391 |
|
|
assign dma_done = dma_done_d & done;
|
392 |
|
|
assign dma_done_all = dma_done_d & (tsz_cnt_is_0_r | (nd & chunk_cnt_is_0_d));
|
393 |
|
|
|
394 |
|
|
always @(posedge clk)
|
395 |
|
|
next_ch <= #1 dma_done;
|
396 |
|
|
|
397 |
|
|
// Register Update Outputs
|
398 |
|
|
assign de_txsz = ld_desc_sel ? mast0_din[11:0] : tsz_cnt;
|
399 |
|
|
assign de_adr0 = ld_desc_sel ? mast0_din : {adr0_cnt, 2'b00};
|
400 |
|
|
assign de_adr1 = ld_desc_sel ? mast0_din : {adr1_cnt, 2'b00};
|
401 |
|
|
assign de_csr = mast0_din;
|
402 |
|
|
|
403 |
|
|
// Abort logic
|
404 |
|
|
always @(posedge clk)
|
405 |
|
|
dma_abort_r <= #1 dma_abort | mast0_err | mast1_err;
|
406 |
|
|
|
407 |
|
|
assign dma_err = dma_abort_r;
|
408 |
|
|
|
409 |
|
|
assign dma_busy = (state != IDLE);
|
410 |
|
|
|
411 |
|
|
////////////////////////////////////////////////////////////////////
|
412 |
|
|
//
|
413 |
|
|
// WISHBONE Interface Logic
|
414 |
|
|
//
|
415 |
|
|
|
416 |
|
|
always @(posedge clk)
|
417 |
|
|
read_r <= #1 read;
|
418 |
|
|
|
419 |
|
|
always @(posedge clk)
|
420 |
|
|
write_r <= #1 write;
|
421 |
|
|
|
422 |
|
|
always @(posedge clk)
|
423 |
|
|
rd_ack_r <= #1 read_r;
|
424 |
|
|
|
425 |
|
|
// Data Path
|
426 |
|
|
assign mast0_dout = m0_we ? {20'h0, tsz_cnt} : csr[2] ? mast1_din : mast0_din;
|
427 |
|
|
assign mast1_dout = csr[2] ? mast1_din : mast0_din;
|
428 |
|
|
|
429 |
|
|
// Address Path
|
430 |
|
|
always @(posedge clk)
|
431 |
|
|
mast0_adr <= #1 m0_go ? (m0_we ? pointer_s : {pointer[31:4], ptr_adr_low, 2'b00}) :
|
432 |
|
|
(csr[2:1]==2'b00) ? ( (read) ? {adr0_cnt, 2'b00} : {adr1_cnt, 2'b00}) :
|
433 |
|
|
(csr[2:1]==2'b01) ? {adr0_cnt, 2'b00} :
|
434 |
|
|
(csr[2:1]==2'b10) ? {adr1_cnt, 2'b00} :
|
435 |
|
|
32'd0;
|
436 |
|
|
|
437 |
|
|
always @(posedge clk)
|
438 |
|
|
mast1_adr <= #1
|
439 |
|
|
(csr[2:1]==2'b11) ? ( (read) ? {adr0_cnt, 2'b00} : {adr1_cnt, 2'b00}) :
|
440 |
|
|
(csr[2:1]==2'b10) ? {adr0_cnt, 2'b00} :
|
441 |
|
|
(csr[2:1]==2'b01) ? {adr1_cnt, 2'b00} :
|
442 |
|
|
32'd0;
|
443 |
|
|
|
444 |
|
|
// CTRL
|
445 |
|
|
assign write_hold = ( read | write ) & write_hold_r;
|
446 |
|
|
|
447 |
|
|
always @(posedge clk)
|
448 |
|
|
write_hold_r <= #1 read | write ;
|
449 |
|
|
|
450 |
|
|
assign read_hold = done ? read : (read | write);
|
451 |
|
|
|
452 |
|
|
assign mast0_go = (!csr[2] & read_hold) | (!csr[1] & write_hold) | m0_go;
|
453 |
|
|
assign mast1_go = ( csr[2] & read_hold) | ( csr[1] & write_hold);
|
454 |
|
|
|
455 |
|
|
assign mast0_we = m0_go ? m0_we : (!csr[1] & write);
|
456 |
|
|
assign mast1_we = csr[1] & write;
|
457 |
|
|
|
458 |
|
|
assign rd_ack = (csr[2] ? mast1_drdy : mast0_drdy);
|
459 |
|
|
assign wr_ack = (csr[1] ? mast1_drdy : mast0_drdy);
|
460 |
|
|
|
461 |
|
|
assign mast0_wait = !((!csr[2] & read) | (!csr[1] & write)) & !m0_go;
|
462 |
|
|
assign mast1_wait = !(( csr[2] & read) | ( csr[1] & write));
|
463 |
|
|
|
464 |
|
|
always @(posedge clk)
|
465 |
|
|
mast0_drdy_r <= #1 mast0_drdy;
|
466 |
|
|
|
467 |
|
|
assign de_ack = dma_done;
|
468 |
|
|
|
469 |
|
|
////////////////////////////////////////////////////////////////////
|
470 |
|
|
//
|
471 |
|
|
// State Machine
|
472 |
|
|
//
|
473 |
|
|
|
474 |
|
|
always @(posedge clk or negedge rst)
|
475 |
|
|
if(!rst) state <= #1 IDLE;
|
476 |
|
|
else state <= #1 next_state;
|
477 |
|
|
|
478 |
|
|
always @(state or pause_req or dma_abort_r or de_start or rd_ack or wr_ack or
|
479 |
|
|
done or ptr_valid or use_ed or mast0_drdy or mast0_drdy_r or csr or nd)
|
480 |
|
|
begin
|
481 |
|
|
next_state = state; // Default keep state
|
482 |
|
|
read = 1'b0;
|
483 |
|
|
write = 1'b0;
|
484 |
|
|
dma_done_d = 1'b0;
|
485 |
|
|
de_csr_we = 1'b0;
|
486 |
|
|
de_txsz_we = 1'b0;
|
487 |
|
|
de_adr0_we = 1'b0;
|
488 |
|
|
de_adr1_we = 1'b0;
|
489 |
|
|
de_fetch_descr = 1'b0;
|
490 |
|
|
|
491 |
|
|
m0_go = 1'b0;
|
492 |
|
|
m0_we = 1'b0;
|
493 |
|
|
ptr_adr_low = 2'h0;
|
494 |
|
|
ptr_set = 1'b0;
|
495 |
|
|
ld_desc_sel = 1'b0;
|
496 |
|
|
paused = 1'b0;
|
497 |
|
|
|
498 |
|
|
case(state) // synopsys parallel_case full_case
|
499 |
|
|
|
500 |
|
|
IDLE:
|
501 |
|
|
begin
|
502 |
|
|
if(pause_req) next_state = PAUSE;
|
503 |
|
|
else
|
504 |
|
|
if(de_start & !csr[`WDMA_ERR])
|
505 |
|
|
begin
|
506 |
|
|
if(use_ed & !ptr_valid) next_state = LD_DESC1;
|
507 |
|
|
else next_state = READ;
|
508 |
|
|
end
|
509 |
|
|
end
|
510 |
|
|
|
511 |
|
|
PAUSE:
|
512 |
|
|
begin
|
513 |
|
|
paused = 1'b1;
|
514 |
|
|
if(!pause_req) next_state = IDLE;
|
515 |
|
|
end
|
516 |
|
|
|
517 |
|
|
READ: // Read From Source
|
518 |
|
|
begin
|
519 |
|
|
if(dma_abort_r) next_state = UPDATE;
|
520 |
|
|
else
|
521 |
|
|
if(!rd_ack) read = 1'b1;
|
522 |
|
|
else
|
523 |
|
|
begin
|
524 |
|
|
write = 1'b1;
|
525 |
|
|
next_state = WRITE;
|
526 |
|
|
end
|
527 |
|
|
end
|
528 |
|
|
|
529 |
|
|
WRITE: // Write To Destination
|
530 |
|
|
begin
|
531 |
|
|
if(dma_abort_r) next_state = UPDATE;
|
532 |
|
|
else
|
533 |
|
|
if(!wr_ack) write = 1'b1;
|
534 |
|
|
else
|
535 |
|
|
begin
|
536 |
|
|
if(done) next_state = UPDATE;
|
537 |
|
|
else
|
538 |
|
|
begin
|
539 |
|
|
read = 1'b1;
|
540 |
|
|
next_state = READ;
|
541 |
|
|
end
|
542 |
|
|
end
|
543 |
|
|
end
|
544 |
|
|
|
545 |
|
|
UPDATE: // Update Registers
|
546 |
|
|
begin
|
547 |
|
|
dma_done_d = 1'b1;
|
548 |
|
|
de_txsz_we = 1'b1;
|
549 |
|
|
de_adr0_we = 1'b1;
|
550 |
|
|
de_adr1_we = 1'b1;
|
551 |
|
|
if(use_ed & csr[`WDMA_WRB] & nd)
|
552 |
|
|
begin
|
553 |
|
|
m0_we = 1'b1;
|
554 |
|
|
m0_go = 1'b1;
|
555 |
|
|
next_state = WB;
|
556 |
|
|
end
|
557 |
|
|
else next_state = IDLE;
|
558 |
|
|
end
|
559 |
|
|
|
560 |
|
|
WB:
|
561 |
|
|
begin
|
562 |
|
|
m0_we = 1'b1;
|
563 |
|
|
if(mast0_drdy)
|
564 |
|
|
begin
|
565 |
|
|
next_state = IDLE;
|
566 |
|
|
end
|
567 |
|
|
else m0_go = 1'b1;
|
568 |
|
|
end
|
569 |
|
|
|
570 |
|
|
LD_DESC1: // Load Descriptor from memory to registers
|
571 |
|
|
begin
|
572 |
|
|
ptr_adr_low = 2'h0;
|
573 |
|
|
ld_desc_sel = 1'b1;
|
574 |
|
|
m0_go = 1'b1;
|
575 |
|
|
de_csr_we = 1'b1;
|
576 |
|
|
de_txsz_we = 1'b1;
|
577 |
|
|
de_fetch_descr = 1'b1;
|
578 |
|
|
if(mast0_drdy)
|
579 |
|
|
begin
|
580 |
|
|
ptr_adr_low = 2'h1;
|
581 |
|
|
next_state = LD_DESC2;
|
582 |
|
|
end
|
583 |
|
|
end
|
584 |
|
|
|
585 |
|
|
LD_DESC2:
|
586 |
|
|
begin
|
587 |
|
|
de_fetch_descr = 1'b1;
|
588 |
|
|
if(mast0_drdy_r) de_csr_we = 1'b1;
|
589 |
|
|
if(mast0_drdy_r) de_txsz_we = 1'b1;
|
590 |
|
|
ptr_adr_low = 2'h1;
|
591 |
|
|
ld_desc_sel = 1'b1;
|
592 |
|
|
m0_go = 1'b1;
|
593 |
|
|
if(mast0_drdy)
|
594 |
|
|
begin
|
595 |
|
|
ptr_adr_low = 2'h2;
|
596 |
|
|
next_state = LD_DESC3;
|
597 |
|
|
end
|
598 |
|
|
end
|
599 |
|
|
|
600 |
|
|
LD_DESC3:
|
601 |
|
|
begin
|
602 |
|
|
de_fetch_descr = 1'b1;
|
603 |
|
|
if(mast0_drdy_r) de_adr0_we = 1'b1;
|
604 |
|
|
ptr_adr_low = 2'h2;
|
605 |
|
|
ld_desc_sel = 1'b1;
|
606 |
|
|
m0_go = 1'b1;
|
607 |
|
|
if(mast0_drdy)
|
608 |
|
|
begin
|
609 |
|
|
ptr_adr_low = 2'h3;
|
610 |
|
|
next_state = LD_DESC4;
|
611 |
|
|
end
|
612 |
|
|
end
|
613 |
|
|
|
614 |
|
|
LD_DESC4:
|
615 |
|
|
begin
|
616 |
|
|
de_fetch_descr = 1'b1;
|
617 |
|
|
if(mast0_drdy_r) de_adr1_we = 1'b1;
|
618 |
|
|
ptr_adr_low = 2'h3;
|
619 |
|
|
ld_desc_sel = 1'b1;
|
620 |
|
|
if(mast0_drdy)
|
621 |
|
|
begin
|
622 |
|
|
next_state = LD_DESC5;
|
623 |
|
|
end
|
624 |
|
|
else m0_go = 1'b1;
|
625 |
|
|
end
|
626 |
|
|
|
627 |
|
|
LD_DESC5:
|
628 |
|
|
begin
|
629 |
|
|
de_fetch_descr = 1'b1;
|
630 |
|
|
ptr_set = 1'b1;
|
631 |
|
|
next_state = READ;
|
632 |
|
|
end
|
633 |
|
|
|
634 |
|
|
endcase
|
635 |
|
|
|
636 |
|
|
end
|
637 |
|
|
|
638 |
|
|
endmodule
|