Sat, 06 Aug 2011 01:48:48 +0100
Update to LM32 DMA v3.3
+// Version : 3.2
+// : 1. Support for 8/32-bit WISHBONE Data Bus. The Control and
+// : Read/Write Ports can be independently configured.
+// : 2. Support for "retry" on receipt of a WISHBONE RTY. This
+// : retry results in the current burst or classic cycle
+// : being issued again after a retry timeout.
+// : 3. Support for "error" on receipt of a WISHBONE ERR. This
+// : results in the current dma transfer being terminated
+// : and the error is updated within the STATUS CSR.
+// : 4. Support for burst size of 64.
+// :
+// Version : 3.3
+// : Support for MachXO2 added. The MachXO2 only has a FIFO
+// : with separate read/write clocks.
1 // ==================================================================
2 // >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
3 // ------------------------------------------------------------------
4 // Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
5 // ALL RIGHTS RESERVED
6 // ------------------------------------------------------------------
7 //
8 // IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
9 //
10 // Permission:
11 //
12 // Lattice Semiconductor grants permission to use this code
13 // pursuant to the terms of the Lattice Semiconductor Corporation
14 // Open Source License Agreement.
15 //
16 // Disclaimer:
17 //
18 // Lattice Semiconductor provides no warranty regarding the use or
19 // functionality of this code. It is the user's responsibility to
20 // verify the user’s design for consistency and functionality through
21 // the use of formal verification methods.
22 //
23 // --------------------------------------------------------------------
24 //
25 // Lattice Semiconductor Corporation
26 // 5555 NE Moore Court
27 // Hillsboro, OR 97214
28 // U.S.A
29 //
30 // TEL: 1-800-Lattice (USA and Canada)
31 // 503-286-8001 (other locations)
32 //
33 // web: http://www.latticesemi.com/
34 // email: techsupport@latticesemi.com
35 //
36 // --------------------------------------------------------------------
37 // FILE DETAILS
38 // Project : LM32 DMA Component
39 // File : slave_reg.v
40 // Title : DMA Slave controller
41 // Dependencies : None
42 // :
43 // Version : 7.0
44 // : Initial Release
45 // :
46 // Version : 7.0SP2, 3.0
47 // : 1. Read and Write channel of DMA controller are working in
48 // : parallel, due to that now as soon as FIFO is not empty
49 // : write channel of the DMA controller start writing data
50 // : to the slave.
51 // : 2. Burst Size supported by DMA controller is increased to
52 // : support bigger burst (from current value of 4 and 8 to
53 // : 16 and 32). Now 4 different type of burst sizes are
54 // : supported by the DMA controller 4, 8, 16 and 32. For
55 // : this Burst Size field of the control register is
56 // : increased to 2 bits.
57 // : 3. Glitch is removed on the S_ACK_O signal.
58 // :
59 // Version : 3.1
60 // : 1. Make DMA Engine compliant to Rule 3.100 of Wishbone Spec
61 // : which defines alignement of bytes in sub-word transfers.
62 // : 2. Removed glitch that did not pause the burst write when
63 // : the read burst was paused by the "read slave".
64 // :
65 // Version : 3.2
66 // : 1. Support for 8/32-bit WISHBONE Data Bus. The Control and
67 // : Read/Write Ports can be independently configured.
68 // : 2. Support for burst size of 64.
69 // :
70 // Version : 3.3
71 // : 1. Interrupt can be release by writing 0 to IE bit in the
72 // : status register.
73 // =============================================================================
75 `ifndef SLAVE_REG_FILE
76 `define SLAVE_REG_FILE
77 `include "system_conf.v"
78 module SLAVE_REG
79 #(parameter S_WB_DAT_WIDTH = 32,
80 parameter S_WB_ADR_WIDTH = 32,
81 parameter MA_WB_DAT_WIDTH = 32,
82 parameter MA_WB_ADR_WIDTH = 32,
83 parameter RETRY_TIMEOUT = 16,
84 parameter FIFO_IMPLEMENTATION = "EBR")
85 (
86 input CLK_I,
87 input RST_I,
89 // Slave port
90 input [S_WB_ADR_WIDTH-1:0] S_ADR_I,
91 input [S_WB_DAT_WIDTH-1:0] S_DAT_I,
92 input [S_WB_DAT_WIDTH/8-1:0] S_SEL_I,
93 input S_WE_I,
94 input S_STB_I,
95 input S_CYC_I,
96 input [2:0] S_CTI_I,
97 output [S_WB_DAT_WIDTH-1:0] S_DAT_O,
98 output reg S_ACK_O,
99 output reg S_INT_O,
101 output reg reg_start,
102 input reg_status,
103 input reg_interrupt,
104 input reg_busy,
105 output reg reg_bt3, reg_bt2, reg_bt1, reg_bt0,
106 output reg reg_s_con, reg_d_con,
107 output reg reg_incw, reg_inchw,
108 output reg [7:0] reg_rdelay,
109 output reg [31:0] reg_00_data,
110 output reg [31:0] reg_04_data,
111 output reg [31:0] reg_08_data
112 );
114 parameter UDLY = 1;
116 reg [31:0] reg_00_data_nxt, reg_04_data_nxt, reg_08_data_nxt;
117 reg [7:0] reg_0c_data, reg_0c_data_nxt;
119 always @(/*AUTOSENSE*/reg_0c_data)
120 begin
121 //reg_rdelay = reg_0c_data[23:16];
122 reg_rdelay = RETRY_TIMEOUT;
123 reg_bt3 = reg_0c_data[7];
124 reg_bt2 = reg_0c_data[6];
125 reg_bt1 = reg_0c_data[5];
126 reg_bt0 = reg_0c_data[4];
127 reg_incw = reg_0c_data[3];
128 reg_inchw = reg_0c_data[2];
129 reg_d_con = reg_0c_data[1];
130 reg_s_con = reg_0c_data[0];
131 end
133 reg [2:0] read_10_data;
134 reg reg_ie;
135 always @(/*AUTOSENSE*/reg_busy or reg_ie or reg_status)
136 begin
137 read_10_data[2] = reg_status;
138 read_10_data[1] = reg_ie;
139 read_10_data[0] = reg_busy;
140 end
142 wire master_idle, reg_wr_rd, reg_wr, reg_rd;
143 assign master_idle = ~reg_busy;
144 assign reg_wr_rd = S_CYC_I & S_STB_I;
145 assign reg_wr = reg_wr_rd & master_idle & S_WE_I & S_ACK_O;
146 assign reg_rd = reg_wr_rd & ~S_WE_I & S_ACK_O;
148 reg s_ack_o_pre, s_ack_o_pre_nxt;
149 always @(/*AUTOSENSE*/S_CYC_I or S_STB_I or S_WE_I or master_idle
150 or reg_wr_rd or s_ack_o_pre)
151 begin
152 if ((s_ack_o_pre == 1'b0)
153 && ((master_idle && reg_wr_rd)
154 || ((master_idle == 1'b0) && reg_wr_rd && (S_WE_I == 1'b0))))
155 s_ack_o_pre_nxt = 1'b1;
156 else
157 s_ack_o_pre_nxt = 1'b0;
159 S_ACK_O = s_ack_o_pre && S_CYC_I && S_STB_I;
160 end
162 always @(posedge CLK_I or posedge RST_I)
163 if (RST_I)
164 s_ack_o_pre <= #UDLY 1'b0;
165 else
166 s_ack_o_pre <= #UDLY s_ack_o_pre_nxt;
168 wire dw00_cs, dw04_cs, dw08_cs, dw0c_cs, dw10_cs;
169 assign dw00_cs = (S_ADR_I[5:2] == 4'h0);
170 assign dw04_cs = (S_ADR_I[5:2] == 4'h1);
171 assign dw08_cs = (S_ADR_I[5:2] == 4'h2);
172 assign dw0c_cs = (S_ADR_I[5:2] == 4'h3);
173 assign dw10_cs = (S_ADR_I[5:2] == 4'h4);
175 wire [31:0] S_DAT_O_int = (dw00_cs
176 ? reg_00_data
177 : (dw04_cs
178 ? reg_04_data
179 : (dw08_cs
180 ? reg_08_data
181 : (dw0c_cs
182 ? {4{reg_0c_data}}
183 : (dw10_cs
184 ? {4{5'h0,read_10_data}}
185 : 32'h0)))));
186 generate
187 if (S_WB_DAT_WIDTH == 8) begin
189 assign S_DAT_O = ((S_ADR_I[1:0] == 2'b00)
190 ? S_DAT_O_int[31:24]
191 : ((S_ADR_I[1:0] == 2'b01)
192 ? S_DAT_O_int[23:16]
193 : ((S_ADR_I[1:0] == 2'b10)
194 ? S_DAT_O_int[15:8]
195 : S_DAT_O_int[7:0])));
197 end
198 else begin
200 assign S_DAT_O = S_DAT_O_int;
202 end
203 endgenerate
207 // Interrupt
208 generate
209 if (S_WB_DAT_WIDTH == 8) begin
211 always @(posedge CLK_I or posedge RST_I)
212 begin
213 if(RST_I)
214 S_INT_O <= #UDLY 1'b0;
215 else if(reg_interrupt && reg_ie)
216 S_INT_O <= #UDLY 1'b1;
217 else if(dw10_cs && (reg_rd || (reg_wr && (S_DAT_I[1] == 1'b0))))
218 S_INT_O <= #UDLY 1'b0;
219 end
221 end
222 else begin
224 always @(posedge CLK_I or posedge RST_I)
225 begin
226 if(RST_I)
227 S_INT_O <= #UDLY 1'b0;
228 else if(reg_interrupt && reg_ie)
229 S_INT_O <= #UDLY 1'b1;
230 else if(dw10_cs && (reg_rd || (reg_wr && (S_DAT_I[25] == 1'b0))))
231 S_INT_O <= #UDLY 1'b0;
232 end
234 end
235 endgenerate
237 // reg_00
238 generate
239 if (S_WB_DAT_WIDTH == 8) begin
241 always @(/*AUTOSENSE*/S_ADR_I or S_DAT_I or dw00_cs
242 or reg_00_data or reg_wr)
243 begin
244 if (dw00_cs && reg_wr) begin
245 casez (S_ADR_I[1:0])
246 2'b00: reg_00_data_nxt = { S_DAT_I[7:0], reg_00_data[23: 0]};
247 2'b01: reg_00_data_nxt = {reg_00_data[31:24], S_DAT_I[7:0], reg_00_data[15: 0]};
248 2'b10: reg_00_data_nxt = {reg_00_data[31:16], S_DAT_I[7:0], reg_00_data[ 7: 0]};
249 2'b11: reg_00_data_nxt = {reg_00_data[31: 8], S_DAT_I[7:0] };
251 default:
252 reg_00_data_nxt = reg_00_data;
253 endcase
254 end
255 else
256 reg_00_data_nxt = reg_00_data;
257 end
259 end
260 else begin
262 always @(/*AUTOSENSE*/S_DAT_I or S_SEL_I or dw00_cs
263 or reg_00_data or reg_wr)
264 begin
265 if (dw00_cs && reg_wr) begin
266 casez (S_SEL_I)
267 4'b1000: reg_00_data_nxt = { S_DAT_I[31:24], reg_00_data[23:0]};
268 4'b0100: reg_00_data_nxt = {reg_00_data[31:24], S_DAT_I[23:16], reg_00_data[15:0]};
269 4'b0010: reg_00_data_nxt = {reg_00_data[31:16], S_DAT_I[15: 8], reg_00_data[ 7:0]};
270 4'b0001: reg_00_data_nxt = {reg_00_data[31: 8], S_DAT_I[ 7: 0] };
271 4'b1111: reg_00_data_nxt = S_DAT_I[31: 0] ;
273 default:
274 reg_00_data_nxt = reg_00_data;
275 endcase
276 end
277 else
278 reg_00_data_nxt = reg_00_data;
279 end
281 end
282 endgenerate
284 always @(posedge CLK_I or posedge RST_I)
285 if (RST_I)
286 reg_00_data <= #UDLY 32'b0;
287 else
288 reg_00_data <= #UDLY reg_00_data_nxt;
292 // reg_04
293 generate
294 if (S_WB_DAT_WIDTH == 8) begin
296 always @(/*AUTOSENSE*/S_ADR_I or S_DAT_I or dw04_cs
297 or reg_04_data or reg_wr)
298 begin
299 if (dw04_cs && reg_wr) begin
300 casez (S_ADR_I[1:0])
301 2'b00: reg_04_data_nxt = { S_DAT_I[7:0], reg_04_data[23: 0]};
302 2'b01: reg_04_data_nxt = {reg_04_data[31:24], S_DAT_I[7:0], reg_04_data[15: 0]};
303 2'b10: reg_04_data_nxt = {reg_04_data[31:16], S_DAT_I[7:0], reg_04_data[ 7: 0]};
304 2'b11: reg_04_data_nxt = {reg_04_data[31: 8], S_DAT_I[7:0] };
306 default:
307 reg_04_data_nxt = reg_04_data;
308 endcase
309 end
310 else
311 reg_04_data_nxt = reg_04_data;
312 end
314 end
315 else begin
317 always @(/*AUTOSENSE*/S_DAT_I or S_SEL_I or dw04_cs
318 or reg_04_data or reg_wr)
319 begin
320 if (dw04_cs && reg_wr) begin
321 casez (S_SEL_I)
322 4'b1000: reg_04_data_nxt = { S_DAT_I[31:24], reg_04_data[23:0]};
323 4'b0100: reg_04_data_nxt = {reg_04_data[31:24], S_DAT_I[23:16], reg_04_data[15:0]};
324 4'b0010: reg_04_data_nxt = {reg_04_data[31:16], S_DAT_I[15: 8], reg_04_data[ 7:0]};
325 4'b0001: reg_04_data_nxt = {reg_04_data[31: 8], S_DAT_I[ 7: 0] };
326 4'b1111: reg_04_data_nxt = { S_DAT_I[31: 0] };
328 default:
329 reg_04_data_nxt = reg_04_data;
330 endcase
331 end
332 else
333 reg_04_data_nxt = reg_04_data;
334 end
336 end
337 endgenerate
339 always @(posedge CLK_I or posedge RST_I)
340 if (RST_I)
341 reg_04_data <= #UDLY 32'b0;
342 else
343 reg_04_data <= #UDLY reg_04_data_nxt;
347 // reg_08
348 generate
349 if (S_WB_DAT_WIDTH == 8) begin
351 always @(/*AUTOSENSE*/S_ADR_I or S_DAT_I or dw08_cs
352 or reg_08_data or reg_wr)
353 if (dw08_cs && reg_wr) begin
354 casez (S_ADR_I[1:0])
355 2'b00: reg_08_data_nxt = { S_DAT_I[7:0], reg_08_data[23: 0]};
356 2'b01: reg_08_data_nxt = {reg_08_data[31:24], S_DAT_I[7:0], reg_08_data[15: 0]};
357 2'b10: reg_08_data_nxt = {reg_08_data[31:16], S_DAT_I[7:0], reg_08_data[ 7: 0]};
358 2'b11: reg_08_data_nxt = {reg_08_data[31: 8], S_DAT_I[7:0] };
360 default:
361 reg_08_data_nxt = reg_08_data;
362 endcase
363 end
365 end
366 else begin
368 always @(/*AUTOSENSE*/S_DAT_I or S_SEL_I or dw08_cs
369 or reg_08_data or reg_wr)
370 if (dw08_cs && reg_wr) begin
371 casez (S_SEL_I)
372 4'b1000: reg_08_data_nxt = { S_DAT_I[31:24], reg_08_data[23:0]};
373 4'b0100: reg_08_data_nxt = {reg_08_data[31:24], S_DAT_I[23:16], reg_08_data[15:0]};
374 4'b0010: reg_08_data_nxt = {reg_08_data[31:16], S_DAT_I[15: 8], reg_08_data[ 7:0]};
375 4'b0001: reg_08_data_nxt = {reg_08_data[31: 8], S_DAT_I[ 7: 0] };
376 4'b1111: reg_08_data_nxt = { S_DAT_I[31: 0] };
378 default:
379 reg_08_data_nxt = reg_08_data;
380 endcase
381 end
383 end
384 endgenerate
386 always @(posedge CLK_I or posedge RST_I)
387 if (RST_I)
388 reg_08_data <= #UDLY 0;
389 else
390 reg_08_data <= #UDLY reg_08_data_nxt[31:0];
394 // reg_0c
395 generate
396 if (S_WB_DAT_WIDTH == 8) begin
398 always @(/*AUTOSENSE*/S_DAT_I or dw0c_cs or reg_0c_data
399 or reg_wr)
400 if (dw0c_cs && reg_wr)
401 reg_0c_data_nxt = S_DAT_I[7:0];
402 else
403 reg_0c_data_nxt = reg_0c_data;
405 end
406 else begin
408 always @(/*AUTOSENSE*/S_DAT_I or S_SEL_I or dw0c_cs
409 or reg_0c_data or reg_wr)
410 if (dw0c_cs && reg_wr)
411 reg_0c_data_nxt = S_DAT_I[31:24];
412 else
413 reg_0c_data_nxt = reg_0c_data;
415 end
416 endgenerate
418 always @(posedge CLK_I or posedge RST_I)
419 if (RST_I)
420 reg_0c_data <= #UDLY 8'b0;
421 else
422 reg_0c_data <= #UDLY reg_0c_data_nxt;
426 // reg_10
427 reg reg_ie_nxt, reg_start_nxt;
428 generate
429 if (S_WB_DAT_WIDTH == 8) begin
431 always @(/*AUTOSENSE*/S_DAT_I or dw10_cs or reg_ie or reg_wr)
432 if (dw10_cs && reg_wr)
433 begin
434 reg_ie_nxt = S_DAT_I[1];
435 reg_start_nxt = S_DAT_I[3];
436 end
437 else
438 begin
439 reg_ie_nxt = reg_ie;
440 reg_start_nxt = 1'b0;
441 end
443 end
444 else begin
446 always @(/*AUTOSENSE*/S_DAT_I or S_SEL_I or dw10_cs or reg_ie
447 or reg_wr)
448 if (dw10_cs && reg_wr)
449 begin
450 reg_ie_nxt = S_DAT_I[25];
451 reg_start_nxt = S_DAT_I[27];
452 end
453 else
454 begin
455 reg_ie_nxt = reg_ie;
456 reg_start_nxt = 1'b0;
457 end
459 end
460 endgenerate
462 always @(posedge CLK_I or posedge RST_I)
463 if (RST_I)
464 begin
465 reg_ie <= #UDLY 1'b0;
466 reg_start <= #UDLY 1'b0;
467 end
468 else
469 begin
470 reg_ie <= #UDLY reg_ie_nxt;
471 reg_start <= #UDLY reg_start_nxt;
472 end
474 endmodule // SLAVE_REG
475 `endif // SLAVE_REG_FILE