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.
| philpem@1 | 1 | // ================================================================== |
| philpem@1 | 2 | // >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< |
| philpem@1 | 3 | // ------------------------------------------------------------------ |
| philpem@1 | 4 | // Copyright (c) 2006-2011 by Lattice Semiconductor Corporation |
| philpem@1 | 5 | // ALL RIGHTS RESERVED |
| philpem@1 | 6 | // ------------------------------------------------------------------ |
| philpem@1 | 7 | // |
| philpem@1 | 8 | // IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM. |
| philpem@1 | 9 | // |
| philpem@1 | 10 | // Permission: |
| philpem@1 | 11 | // |
| philpem@1 | 12 | // Lattice Semiconductor grants permission to use this code |
| philpem@1 | 13 | // pursuant to the terms of the Lattice Semiconductor Corporation |
| philpem@1 | 14 | // Open Source License Agreement. |
| philpem@1 | 15 | // |
| philpem@1 | 16 | // Disclaimer: |
| philpem@0 | 17 | // |
| philpem@1 | 18 | // Lattice Semiconductor provides no warranty regarding the use or |
| philpem@1 | 19 | // functionality of this code. It is the user's responsibility to |
| philpem@1 | 20 | // verify the user’s design for consistency and functionality through |
| philpem@1 | 21 | // the use of formal verification methods. |
| philpem@1 | 22 | // |
| philpem@1 | 23 | // -------------------------------------------------------------------- |
| philpem@1 | 24 | // |
| philpem@1 | 25 | // Lattice Semiconductor Corporation |
| philpem@1 | 26 | // 5555 NE Moore Court |
| philpem@1 | 27 | // Hillsboro, OR 97214 |
| philpem@1 | 28 | // U.S.A |
| philpem@1 | 29 | // |
| philpem@1 | 30 | // TEL: 1-800-Lattice (USA and Canada) |
| philpem@1 | 31 | // 503-286-8001 (other locations) |
| philpem@1 | 32 | // |
| philpem@1 | 33 | // web: http://www.latticesemi.com/ |
| philpem@1 | 34 | // email: techsupport@latticesemi.com |
| philpem@1 | 35 | // |
| philpem@1 | 36 | // -------------------------------------------------------------------- |
| philpem@0 | 37 | // FILE DETAILS |
| philpem@0 | 38 | // Project : LM32 DMA Component |
| philpem@1 | 39 | // File : wb_dma_ctrl.v |
| philpem@1 | 40 | // Title : DMA controller top file |
| philpem@0 | 41 | // Dependencies : None |
| philpem@1 | 42 | // : |
| philpem@1 | 43 | // Version : 7.0 |
| philpem@1 | 44 | // : Initial Release |
| philpem@1 | 45 | // : |
| philpem@1 | 46 | // Version : 7.0SP2, 3.0 |
| philpem@1 | 47 | // : 1. Read and Write channel of DMA controller are working in |
| philpem@1 | 48 | // : parallel, due to that now as soon as FIFO is not empty |
| philpem@1 | 49 | // : write channel of the DMA controller start writing data |
| philpem@1 | 50 | // : to the slave. |
| philpem@1 | 51 | // : 2. Burst Size supported by DMA controller is increased to |
| philpem@1 | 52 | // : support bigger burst (from current value of 4 and 8 to |
| philpem@1 | 53 | // : 16 and 32). Now 4 different type of burst sizes are |
| philpem@1 | 54 | // : supported by the DMA controller 4, 8, 16 and 32. For |
| philpem@1 | 55 | // : this Burst Size field of the control register is |
| philpem@1 | 56 | // : increased to 2 bits. |
| philpem@1 | 57 | // : 3. Glitch is removed on the S_ACK_O signal. |
| philpem@1 | 58 | // : |
| philpem@1 | 59 | // Version : 3.1 |
| philpem@1 | 60 | // : Make DMA Engine compliant to Rule 3.100 of Wishbone Spec |
| philpem@1 | 61 | // : which defines alignement of bytes in sub-word transfers. |
| philpem@1 | 62 | // : |
| philpem@1 | 63 | // Version : 3.2 |
| philpem@1 | 64 | // : 1. Support for 8/32-bit WISHBONE Data Bus. The Control and |
| philpem@1 | 65 | // : Read/Write Ports can be independently configured. |
| philpem@1 | 66 | // : 2. Support for "retry" on receipt of a WISHBONE RTY. This |
| philpem@1 | 67 | // : retry results in the current burst or classic cycle |
| philpem@1 | 68 | // : being issued again after a retry timeout. |
| philpem@1 | 69 | // : 3. Support for "error" on receipt of a WISHBONE ERR. This |
| philpem@1 | 70 | // : results in the current dma transfer being terminated |
| philpem@1 | 71 | // : and the error is updated within the STATUS CSR. |
| philpem@1 | 72 | // : 4. Support for burst size of 64. |
| philpem@1 | 73 | // : |
| philpem@1 | 74 | // Version : 3.3 |
| philpem@1 | 75 | // : Support for MachXO2 added. The MachXO2 only has a FIFO |
| philpem@1 | 76 | // : with separate read/write clocks. |
| philpem@0 | 77 | // ============================================================================= |
| philpem@0 | 78 | |
| philpem@0 | 79 | `ifndef MASTER_CTRL_FILE |
| philpem@0 | 80 | `define MASTER_CTRL_FILE |
| philpem@0 | 81 | `include "system_conf.v" |
| philpem@0 | 82 | module MASTER_CTRL |
| philpem@1 | 83 | #(parameter MA_WB_DAT_WIDTH = 32, |
| philpem@1 | 84 | parameter MA_WB_ADR_WIDTH = 32, |
| philpem@1 | 85 | parameter MB_WB_DAT_WIDTH = 32, |
| philpem@1 | 86 | parameter MB_WB_ADR_WIDTH = 32, |
| philpem@1 | 87 | parameter S_WB_DAT_WIDTH = 32, |
| philpem@0 | 88 | parameter FIFO_IMPLEMENTATION = "EBR") |
| philpem@1 | 89 | ( |
| philpem@1 | 90 | // System clock and reset |
| philpem@1 | 91 | input CLK_I, |
| philpem@1 | 92 | input RST_I, |
| philpem@1 | 93 | // Master read port |
| philpem@1 | 94 | output reg [MA_WB_ADR_WIDTH-1:0] MA_ADR_O, |
| philpem@1 | 95 | output reg [MA_WB_DAT_WIDTH/8-1:0] MA_SEL_O, |
| philpem@1 | 96 | output reg [MA_WB_DAT_WIDTH-1:0] MA_DAT_O, |
| philpem@1 | 97 | output reg MA_WE_O, |
| philpem@1 | 98 | output reg MA_STB_O, |
| philpem@1 | 99 | output reg MA_CYC_O, |
| philpem@1 | 100 | output reg [2:0] MA_CTI_O, |
| philpem@1 | 101 | output reg MA_LOCK_O, |
| philpem@1 | 102 | input [MA_WB_DAT_WIDTH-1:0] MA_DAT_I, |
| philpem@1 | 103 | input MA_ACK_I, |
| philpem@1 | 104 | input MA_ERR_I, |
| philpem@1 | 105 | input MA_RTY_I, |
| philpem@1 | 106 | // Master write port |
| philpem@1 | 107 | output reg [MB_WB_ADR_WIDTH-1:0] MB_ADR_O, |
| philpem@1 | 108 | output reg [MB_WB_DAT_WIDTH/8-1:0] MB_SEL_O, |
| philpem@1 | 109 | output reg [MB_WB_DAT_WIDTH-1:0] MB_DAT_O, |
| philpem@1 | 110 | output reg MB_WE_O, |
| philpem@1 | 111 | output reg MB_STB_O, |
| philpem@1 | 112 | output reg MB_CYC_O, |
| philpem@1 | 113 | output reg [2:0] MB_CTI_O, |
| philpem@1 | 114 | output reg MB_LOCK_O, |
| philpem@1 | 115 | input MB_ACK_I, |
| philpem@1 | 116 | input MB_ERR_I, |
| philpem@1 | 117 | input MB_RTY_I, |
| philpem@1 | 118 | // Register interface |
| philpem@1 | 119 | input reg_start, |
| philpem@1 | 120 | output reg reg_busy, |
| philpem@1 | 121 | output reg reg_status, |
| philpem@1 | 122 | output reg reg_interrupt, |
| philpem@1 | 123 | input reg_bt3, reg_bt2, reg_bt1, reg_bt0, |
| philpem@1 | 124 | input reg_s_con, reg_d_con, |
| philpem@1 | 125 | input reg_incw, reg_inchw, |
| philpem@1 | 126 | input [7:0] reg_rdelay, |
| philpem@1 | 127 | input [31:0] reg_00_data, |
| philpem@1 | 128 | input [31:0] reg_04_data, |
| philpem@1 | 129 | input [31:0] reg_08_data |
| philpem@1 | 130 | ); |
| philpem@1 | 131 | |
| philpem@1 | 132 | parameter lat_family = `LATTICE_FAMILY; |
| philpem@1 | 133 | parameter UDLY = 1; |
| philpem@1 | 134 | |
| philpem@1 | 135 | wire [MB_WB_DAT_WIDTH-1:0] fifo_dout; |
| philpem@1 | 136 | wire fifo_empty, fifo_aempty; |
| philpem@1 | 137 | reg [MA_WB_DAT_WIDTH-1:0] fifo_din; |
| philpem@1 | 138 | |
| philpem@1 | 139 | reg [31:0] xfer_length, xfer_length_nxt; |
| philpem@1 | 140 | reg [5:0] rburst_count, rburst_count_nxt; |
| philpem@1 | 141 | reg [5:0] wburst_count, wburst_count_nxt; |
| philpem@1 | 142 | reg [5:0] save_wburst_count, save_wburst_count_nxt; |
| philpem@1 | 143 | reg [31:0] raddr_checkpoint, raddr_checkpoint_nxt, waddr_checkpoint, waddr_checkpoint_nxt; |
| philpem@1 | 144 | reg [7:0] retry_delay, retry_delay_nxt; |
| philpem@1 | 145 | reg MA_CYC_O_nxt, MA_STB_O_nxt, MA_CYC_O_d; |
| philpem@1 | 146 | reg [2:0] MA_CTI_O_nxt; |
| philpem@1 | 147 | reg [MA_WB_ADR_WIDTH-1:0] MA_ADR_O_nxt; |
| philpem@1 | 148 | reg [MA_WB_DAT_WIDTH/8-1:0] MA_SEL_O_nxt; |
| philpem@1 | 149 | reg MB_CYC_O_nxt, MB_STB_O_nxt, MB_CYC_O_d; |
| philpem@1 | 150 | reg [2:0] MB_CTI_O_nxt; |
| philpem@1 | 151 | reg [MB_WB_ADR_WIDTH-1:0] MB_ADR_O_nxt; |
| philpem@1 | 152 | reg [MB_WB_DAT_WIDTH/8-1:0] MB_SEL_O_nxt; |
| philpem@1 | 153 | reg reg_status_nxt; |
| philpem@1 | 154 | reg burst_start, xfer_done; |
| philpem@1 | 155 | wire [2:0] iCount; |
| philpem@1 | 156 | wire [5:0] bCount; |
| philpem@1 | 157 | wire [8:0] biCount; |
| philpem@1 | 158 | |
| philpem@1 | 159 | /*---------------------------------------------------------------------- |
| philpem@1 | 160 | |
| philpem@1 | 161 | READ State Machine |
| philpem@1 | 162 | |
| philpem@1 | 163 | ----------------------------------------------------------------------*/ |
| philpem@1 | 164 | reg [2:0] rstate, rstate_nxt; |
| philpem@1 | 165 | parameter RD_IDLE = 3'b000; |
| philpem@1 | 166 | parameter RD_SINGLEA = 3'b001; |
| philpem@1 | 167 | parameter RD_SINGLEB = 3'b010; |
| philpem@1 | 168 | parameter RD_SINGLE_RETRY = 3'b011; |
| philpem@1 | 169 | parameter RD_BURST = 3'b100; |
| philpem@1 | 170 | |
| philpem@1 | 171 | always @(/*AUTOSENSE*/MA_ACK_I or MA_ERR_I or MA_RTY_I or MB_ERR_I |
| philpem@1 | 172 | or MB_RTY_I or burst_start or rburst_count or reg_bt3 |
| philpem@1 | 173 | or reg_start or retry_delay or rstate or xfer_done) |
| philpem@1 | 174 | casez (rstate) |
| philpem@1 | 175 | RD_IDLE: |
| philpem@1 | 176 | if (reg_start && (reg_bt3 == 1'b0)) |
| philpem@1 | 177 | rstate_nxt = RD_SINGLEA; |
| philpem@1 | 178 | else if (burst_start && reg_bt3) |
| philpem@1 | 179 | rstate_nxt = RD_BURST; |
| philpem@1 | 180 | else |
| philpem@1 | 181 | rstate_nxt = rstate; |
| philpem@1 | 182 | |
| philpem@1 | 183 | RD_SINGLEA: |
| philpem@1 | 184 | if (MA_ACK_I) |
| philpem@1 | 185 | rstate_nxt = RD_SINGLEB; |
| philpem@1 | 186 | else if (MA_ERR_I) |
| philpem@1 | 187 | rstate_nxt = RD_IDLE; |
| philpem@1 | 188 | else if (MA_RTY_I) |
| philpem@1 | 189 | rstate_nxt = RD_SINGLE_RETRY; |
| philpem@1 | 190 | else |
| philpem@1 | 191 | rstate_nxt = rstate; |
| philpem@1 | 192 | |
| philpem@1 | 193 | RD_SINGLEB: |
| philpem@1 | 194 | if (burst_start) |
| philpem@1 | 195 | rstate_nxt = RD_SINGLEA; |
| philpem@1 | 196 | else if (MB_ERR_I || xfer_done) |
| philpem@1 | 197 | rstate_nxt = RD_IDLE; |
| philpem@1 | 198 | else if (MB_RTY_I) |
| philpem@1 | 199 | rstate_nxt = RD_SINGLE_RETRY; |
| philpem@1 | 200 | else |
| philpem@1 | 201 | rstate_nxt = rstate; |
| philpem@1 | 202 | |
| philpem@1 | 203 | RD_BURST: |
| philpem@1 | 204 | if (MB_ERR_I || MB_RTY_I || MA_ERR_I || MB_RTY_I || (MA_ACK_I && (rburst_count == 0))) |
| philpem@1 | 205 | rstate_nxt = RD_IDLE; |
| philpem@1 | 206 | else |
| philpem@1 | 207 | rstate_nxt = rstate; |
| philpem@1 | 208 | |
| philpem@1 | 209 | RD_SINGLE_RETRY: |
| philpem@1 | 210 | if (retry_delay == 8'h0) |
| philpem@1 | 211 | rstate_nxt = RD_SINGLEA; |
| philpem@1 | 212 | else |
| philpem@1 | 213 | rstate_nxt = rstate; |
| philpem@1 | 214 | |
| philpem@1 | 215 | default: |
| philpem@1 | 216 | rstate_nxt = RD_IDLE; |
| philpem@1 | 217 | endcase |
| philpem@1 | 218 | |
| philpem@1 | 219 | /*---------------------------------------------------------------------- |
| philpem@1 | 220 | |
| philpem@1 | 221 | WRITE State Machine |
| philpem@1 | 222 | |
| philpem@1 | 223 | ----------------------------------------------------------------------*/ |
| philpem@1 | 224 | reg [3:0] wstate, wstate_nxt; |
| philpem@1 | 225 | parameter WR_IDLE = 4'b0000; |
| philpem@1 | 226 | parameter WR_SINGLEA = 4'b0001; |
| philpem@1 | 227 | parameter WR_SINGLEB = 4'b0010; |
| philpem@1 | 228 | parameter WR_FIFO_CHECK = 4'b0011; |
| philpem@1 | 229 | parameter WR_SHORT = 4'b0100; |
| philpem@1 | 230 | parameter WR_BURST = 4'b0101; |
| philpem@1 | 231 | parameter WR_SBURST = 4'b0110; |
| philpem@1 | 232 | parameter WR_SETUPA = 4'b0111; |
| philpem@1 | 233 | parameter WR_SETUPB = 4'b1000; |
| philpem@1 | 234 | parameter WR_ERROR = 4'b1001; |
| philpem@1 | 235 | parameter WR_RETRY = 4'b1010; |
| philpem@1 | 236 | |
| philpem@1 | 237 | always @(/*AUTOSENSE*/MA_ERR_I or MA_RTY_I or MB_ACK_I or MB_ERR_I |
| philpem@1 | 238 | or MB_RTY_I or fifo_aempty or fifo_empty or iCount |
| philpem@1 | 239 | or reg_bt3 or reg_start or retry_delay or wburst_count |
| philpem@1 | 240 | or wstate or xfer_length) |
| philpem@1 | 241 | casez (wstate) |
| philpem@1 | 242 | WR_IDLE: |
| philpem@1 | 243 | if (reg_start) |
| philpem@1 | 244 | wstate_nxt = reg_bt3 ? WR_SETUPA : WR_SINGLEA; |
| philpem@1 | 245 | else |
| philpem@1 | 246 | wstate_nxt = wstate; |
| philpem@1 | 247 | |
| philpem@1 | 248 | WR_SINGLEA: |
| philpem@1 | 249 | if (MA_ERR_I) |
| philpem@1 | 250 | wstate_nxt = WR_IDLE; |
| philpem@1 | 251 | else if (fifo_empty == 1'b0) |
| philpem@1 | 252 | wstate_nxt = WR_SINGLEB; |
| philpem@1 | 253 | else |
| philpem@1 | 254 | wstate_nxt = wstate; |
| philpem@1 | 255 | |
| philpem@1 | 256 | WR_SINGLEB: |
| philpem@1 | 257 | if (MB_ACK_I) |
| philpem@1 | 258 | wstate_nxt = (xfer_length == iCount) ? WR_IDLE : WR_SINGLEA; |
| philpem@1 | 259 | else if (MB_ERR_I) |
| philpem@1 | 260 | wstate_nxt = WR_IDLE; |
| philpem@1 | 261 | else if (MB_RTY_I) |
| philpem@1 | 262 | wstate_nxt = WR_SINGLEA; |
| philpem@1 | 263 | else |
| philpem@1 | 264 | wstate_nxt = wstate; |
| philpem@1 | 265 | |
| philpem@1 | 266 | WR_FIFO_CHECK: |
| philpem@1 | 267 | if (MA_ERR_I) |
| philpem@1 | 268 | wstate_nxt = WR_ERROR; |
| philpem@1 | 269 | else if (MA_RTY_I) |
| philpem@1 | 270 | wstate_nxt = WR_RETRY; |
| philpem@1 | 271 | else |
| philpem@1 | 272 | if ((fifo_empty == 1'b0) && (wburst_count == 6'h0)) |
| philpem@1 | 273 | wstate_nxt = WR_SHORT; |
| philpem@1 | 274 | else if ((fifo_aempty == 1'b0) && (wburst_count >= 6'h1)) |
| philpem@1 | 275 | wstate_nxt = WR_BURST; |
| philpem@1 | 276 | else |
| philpem@1 | 277 | wstate_nxt = wstate; |
| philpem@1 | 278 | |
| philpem@1 | 279 | WR_SHORT: |
| philpem@1 | 280 | if (MA_ERR_I) |
| philpem@1 | 281 | wstate_nxt = WR_ERROR; |
| philpem@1 | 282 | else if (MA_RTY_I) |
| philpem@1 | 283 | wstate_nxt = WR_RETRY; |
| philpem@1 | 284 | else |
| philpem@1 | 285 | if (MB_ACK_I) |
| philpem@1 | 286 | wstate_nxt = WR_FIFO_CHECK; |
| philpem@1 | 287 | else if (MB_ERR_I) |
| philpem@1 | 288 | wstate_nxt = WR_ERROR; |
| philpem@1 | 289 | else if (MB_RTY_I) |
| philpem@1 | 290 | wstate_nxt = WR_RETRY; |
| philpem@1 | 291 | else |
| philpem@1 | 292 | wstate_nxt = wstate; |
| philpem@1 | 293 | |
| philpem@1 | 294 | WR_BURST: |
| philpem@1 | 295 | if (MA_ERR_I) |
| philpem@1 | 296 | wstate_nxt = WR_ERROR; |
| philpem@1 | 297 | else if (MA_RTY_I) |
| philpem@1 | 298 | wstate_nxt = WR_RETRY; |
| philpem@1 | 299 | else |
| philpem@1 | 300 | if (MB_ACK_I) |
| philpem@1 | 301 | if (fifo_aempty && (wburst_count >= 6'h2)) |
| philpem@1 | 302 | wstate_nxt = WR_SBURST; |
| philpem@1 | 303 | else if (wburst_count == 6'h0) |
| philpem@1 | 304 | wstate_nxt = WR_SETUPA; |
| philpem@1 | 305 | else |
| philpem@1 | 306 | wstate_nxt = wstate; |
| philpem@1 | 307 | else if (MB_ERR_I) |
| philpem@1 | 308 | wstate_nxt = WR_ERROR; |
| philpem@1 | 309 | else if (MB_RTY_I) |
| philpem@1 | 310 | wstate_nxt = WR_RETRY; |
| philpem@1 | 311 | else |
| philpem@1 | 312 | wstate_nxt = wstate; |
| philpem@1 | 313 | |
| philpem@1 | 314 | WR_SBURST: |
| philpem@1 | 315 | if (MA_ERR_I) |
| philpem@1 | 316 | wstate_nxt = WR_ERROR; |
| philpem@1 | 317 | else if (MA_RTY_I) |
| philpem@1 | 318 | wstate_nxt = WR_RETRY; |
| philpem@1 | 319 | else |
| philpem@1 | 320 | if (MB_ACK_I) |
| philpem@1 | 321 | wstate_nxt = WR_FIFO_CHECK; |
| philpem@1 | 322 | else if (MB_RTY_I) |
| philpem@1 | 323 | wstate_nxt = WR_RETRY; |
| philpem@1 | 324 | else |
| philpem@1 | 325 | wstate_nxt = wstate; |
| philpem@1 | 326 | |
| philpem@1 | 327 | WR_SETUPA: |
| philpem@1 | 328 | wstate_nxt = WR_SETUPB; |
| philpem@1 | 329 | |
| philpem@1 | 330 | WR_SETUPB: |
| philpem@1 | 331 | wstate_nxt = (wburst_count == 6'h0) ? WR_IDLE : WR_FIFO_CHECK; |
| philpem@1 | 332 | |
| philpem@1 | 333 | WR_ERROR: |
| philpem@1 | 334 | wstate_nxt = fifo_empty ? WR_IDLE : wstate; |
| philpem@1 | 335 | |
| philpem@1 | 336 | WR_RETRY: |
| philpem@1 | 337 | if (fifo_empty && (retry_delay == 8'h0)) |
| philpem@1 | 338 | wstate_nxt = WR_FIFO_CHECK; |
| philpem@1 | 339 | else |
| philpem@1 | 340 | wstate_nxt = wstate; |
| philpem@1 | 341 | |
| philpem@1 | 342 | default: |
| philpem@1 | 343 | wstate_nxt = WR_IDLE; |
| philpem@1 | 344 | endcase |
| philpem@1 | 345 | |
| philpem@1 | 346 | /*---------------------------------------------------------------------- |
| philpem@1 | 347 | Status Signals |
| philpem@1 | 348 | ----------------------------------------------------------------------*/ |
| philpem@1 | 349 | always @(/*AUTOSENSE*/MA_ERR_I or MB_ERR_I or reg_status or wstate |
| philpem@1 | 350 | or wstate_nxt) |
| philpem@1 | 351 | begin |
| philpem@1 | 352 | // Raise and hold busy signal until current DMA transfer is complete |
| philpem@1 | 353 | reg_busy = (wstate_nxt != WR_IDLE); |
| philpem@1 | 354 | |
| philpem@1 | 355 | // Raise and hold error signal until a new DMA transfer is initiated. |
| philpem@1 | 356 | // Error signal is raised when the WISHBONE cycle results in _ERR_I |
| philpem@1 | 357 | if ((wstate == WR_IDLE) && (wstate_nxt != WR_IDLE)) |
| philpem@1 | 358 | reg_status_nxt = 1'b0; |
| philpem@1 | 359 | else if (MA_ERR_I || MB_ERR_I) |
| philpem@1 | 360 | reg_status_nxt = 1'b1; |
| philpem@1 | 361 | else |
| philpem@1 | 362 | reg_status_nxt = reg_status; |
| philpem@1 | 363 | |
| philpem@1 | 364 | // Raise interrupt on completion of DMA transfer |
| philpem@1 | 365 | reg_interrupt = (wstate != WR_IDLE) & (wstate_nxt == WR_IDLE); |
| philpem@1 | 366 | end |
| philpem@1 | 367 | |
| philpem@1 | 368 | /*---------------------------------------------------------------------- |
| philpem@1 | 369 | WISHBONE Read Port |
| philpem@1 | 370 | ----------------------------------------------------------------------*/ |
| philpem@1 | 371 | always @(/*AUTOSENSE*/MA_ACK_I or MA_ADR_O or MA_CTI_O or MA_CYC_O |
| philpem@1 | 372 | or MA_CYC_O_d or MA_ERR_I or MA_RTY_I or MA_STB_O |
| philpem@1 | 373 | or MB_ERR_I or MB_RTY_I or burst_start or iCount |
| philpem@1 | 374 | or raddr_checkpoint or rburst_count or reg_00_data |
| philpem@1 | 375 | or reg_bt3 or reg_s_con or reg_start or rstate |
| philpem@1 | 376 | or rstate_nxt) |
| philpem@1 | 377 | begin |
| philpem@1 | 378 | // MA_CYC_O and MA_STB_O |
| philpem@1 | 379 | |
| philpem@1 | 380 | // handle all conditions that cause MA_CYC_O to go 0 |
| philpem@1 | 381 | if (((rstate == RD_SINGLEA) |
| philpem@1 | 382 | && (MA_ACK_I || MA_ERR_I || MA_RTY_I)) |
| philpem@1 | 383 | || ((rstate == RD_BURST) |
| philpem@1 | 384 | && (MB_ERR_I || MB_RTY_I || (MA_ACK_I && (rburst_count == 6'h0))))) |
| philpem@1 | 385 | begin |
| philpem@1 | 386 | MA_CYC_O_nxt = 1'b0; |
| philpem@1 | 387 | MA_STB_O_nxt = 1'b0; |
| philpem@1 | 388 | end |
| philpem@1 | 389 | // handle all conditions that cause MA_CYC_O to go 1 |
| philpem@1 | 390 | else if (((rstate_nxt == RD_SINGLEA) |
| philpem@1 | 391 | && ((rstate == RD_IDLE) || (rstate == RD_SINGLEB) || (rstate == RD_SINGLE_RETRY))) |
| philpem@1 | 392 | || ((rstate == RD_BURST) && (MA_CYC_O_d == 1'b0))) |
| philpem@1 | 393 | begin |
| philpem@1 | 394 | MA_CYC_O_nxt = 1'b1; |
| philpem@1 | 395 | MA_STB_O_nxt = 1'b1; |
| philpem@1 | 396 | end |
| philpem@1 | 397 | // default: maintain state |
| philpem@1 | 398 | else |
| philpem@1 | 399 | begin |
| philpem@1 | 400 | MA_CYC_O_nxt = MA_CYC_O; |
| philpem@1 | 401 | MA_STB_O_nxt = MA_STB_O; |
| philpem@1 | 402 | end |
| philpem@1 | 403 | |
| philpem@1 | 404 | |
| philpem@1 | 405 | // MA_ADR_O |
| philpem@1 | 406 | |
| philpem@1 | 407 | // set up first address of the dma transfer |
| philpem@1 | 408 | if (reg_start) |
| philpem@1 | 409 | MA_ADR_O_nxt = reg_00_data; |
| philpem@1 | 410 | else if (reg_s_con == 1'b0) |
| philpem@1 | 411 | begin |
| philpem@1 | 412 | // roll back to first address in a burst transfer on a retry |
| philpem@1 | 413 | if (/*(rstate == RD_BURST) && */MB_RTY_I) |
| philpem@1 | 414 | MA_ADR_O_nxt = raddr_checkpoint; |
| philpem@1 | 415 | // increment for every regular transfer |
| philpem@1 | 416 | else if ((MB_RTY_I == 1'b0) |
| philpem@1 | 417 | && (((rstate == RD_SINGLEB) && burst_start) |
| philpem@1 | 418 | || ((rstate == RD_BURST) && MA_ACK_I))) |
| philpem@1 | 419 | MA_ADR_O_nxt = MA_ADR_O + iCount; |
| philpem@1 | 420 | else |
| philpem@1 | 421 | MA_ADR_O_nxt = MA_ADR_O; |
| philpem@1 | 422 | end |
| philpem@1 | 423 | else |
| philpem@1 | 424 | MA_ADR_O_nxt = MA_ADR_O; |
| philpem@1 | 425 | |
| philpem@1 | 426 | |
| philpem@1 | 427 | // MA_CTI_O |
| philpem@1 | 428 | |
| philpem@1 | 429 | if (reg_start || burst_start) |
| philpem@1 | 430 | MA_CTI_O_nxt = reg_bt3 ? (reg_s_con ? 3'b001 : 3'b010) : 3'b000; |
| philpem@1 | 431 | else if ((rstate == RD_BURST) && (rburst_count == 6'h1) && MA_ACK_I) |
| philpem@1 | 432 | MA_CTI_O_nxt = 3'b111; |
| philpem@1 | 433 | else |
| philpem@1 | 434 | MA_CTI_O_nxt = MA_CTI_O; |
| philpem@1 | 435 | |
| philpem@1 | 436 | |
| philpem@1 | 437 | // Other signals |
| philpem@1 | 438 | MA_WE_O = 1'b0; |
| philpem@1 | 439 | MA_DAT_O = 0; |
| philpem@1 | 440 | MA_LOCK_O = 1'b0; |
| philpem@1 | 441 | end |
| philpem@1 | 442 | |
| philpem@1 | 443 | generate |
| philpem@1 | 444 | if (MA_WB_DAT_WIDTH == 8) begin |
| philpem@1 | 445 | |
| philpem@1 | 446 | always @(*) |
| philpem@1 | 447 | MA_SEL_O_nxt = 1'b1; |
| philpem@1 | 448 | |
| philpem@1 | 449 | end |
| philpem@1 | 450 | else begin |
| philpem@1 | 451 | |
| philpem@1 | 452 | always @(/*AUTOSENSE*/MA_ADR_O_nxt or iCount) |
| philpem@1 | 453 | begin |
| philpem@1 | 454 | if (iCount == 1) |
| philpem@1 | 455 | casez (MA_ADR_O_nxt[1:0]) |
| philpem@1 | 456 | 2'b00: MA_SEL_O_nxt = 4'b1000; |
| philpem@1 | 457 | 2'b01: MA_SEL_O_nxt = 4'b0100; |
| philpem@1 | 458 | 2'b10: MA_SEL_O_nxt = 4'b0010; |
| philpem@1 | 459 | 2'b11: MA_SEL_O_nxt = 4'b0001; |
| philpem@1 | 460 | default: |
| philpem@1 | 461 | MA_SEL_O_nxt = 4'b1111; |
| philpem@1 | 462 | endcase |
| philpem@1 | 463 | else if (iCount == 2) |
| philpem@1 | 464 | MA_SEL_O_nxt = MA_ADR_O_nxt[1] ? 4'b0011 : 4'b1100; |
| philpem@1 | 465 | else |
| philpem@1 | 466 | MA_SEL_O_nxt = 4'b1111; |
| philpem@1 | 467 | end |
| philpem@1 | 468 | |
| philpem@1 | 469 | end |
| philpem@1 | 470 | endgenerate |
| philpem@1 | 471 | |
| philpem@1 | 472 | |
| philpem@1 | 473 | /*---------------------------------------------------------------------- |
| philpem@1 | 474 | WISHBONE Write Port |
| philpem@1 | 475 | ----------------------------------------------------------------------*/ |
| philpem@1 | 476 | always @(/*AUTOSENSE*/MA_ERR_I or MA_RTY_I or MB_ACK_I or MB_ADR_O |
| philpem@1 | 477 | or MB_CTI_O or MB_CYC_O or MB_ERR_I or MB_RTY_I |
| philpem@1 | 478 | or MB_STB_O or fifo_aempty or fifo_dout or fifo_empty |
| philpem@1 | 479 | or iCount or reg_04_data or reg_d_con or reg_s_con |
| philpem@1 | 480 | or reg_start or waddr_checkpoint or wburst_count or wstate |
| philpem@1 | 481 | or wstate_nxt) |
| philpem@1 | 482 | begin |
| philpem@1 | 483 | // MB_CYC_O and MB_STB_O |
| philpem@1 | 484 | |
| philpem@1 | 485 | // handle all conditions that cause MB_CYC_O to go 0 |
| philpem@1 | 486 | if (((wstate == WR_SINGLEB) |
| philpem@1 | 487 | && (MB_ACK_I || MB_ERR_I || MB_RTY_I)) |
| philpem@1 | 488 | || ((MA_ERR_I || MA_RTY_I) |
| philpem@1 | 489 | && ((wstate == WR_SHORT) || (wstate == WR_FIFO_CHECK) || (wstate == WR_BURST) || (wstate == WR_SBURST))) |
| philpem@1 | 490 | || ((wstate == WR_BURST) |
| philpem@1 | 491 | && ((MB_ACK_I && (wburst_count == 6'h0)) || MB_ERR_I || MB_RTY_I)) |
| philpem@1 | 492 | || ((wstate == WR_SBURST) |
| philpem@1 | 493 | && (MB_ACK_I || MB_ERR_I || MB_RTY_I))) |
| philpem@1 | 494 | begin |
| philpem@1 | 495 | MB_CYC_O_nxt = 1'b0; |
| philpem@1 | 496 | MB_STB_O_nxt = 1'b0; |
| philpem@1 | 497 | end |
| philpem@1 | 498 | // handle all conditions that cause MB_CYC_O to go 1 |
| philpem@1 | 499 | else if (((wstate == WR_SINGLEA) && (fifo_empty == 1'b0)) |
| philpem@1 | 500 | || ((wstate == WR_FIFO_CHECK) |
| philpem@1 | 501 | && (((fifo_empty == 1'b0) && (wburst_count == 6'h0)) |
| philpem@1 | 502 | || ((fifo_aempty == 1'b0) && (wburst_count >= 6'h1))))) |
| philpem@1 | 503 | begin |
| philpem@1 | 504 | MB_CYC_O_nxt = 1'b1; |
| philpem@1 | 505 | MB_STB_O_nxt = 1'b1; |
| philpem@1 | 506 | end |
| philpem@1 | 507 | // default: maintain state |
| philpem@1 | 508 | else |
| philpem@1 | 509 | begin |
| philpem@1 | 510 | MB_CYC_O_nxt = MB_CYC_O; |
| philpem@1 | 511 | MB_STB_O_nxt = MB_STB_O; |
| philpem@1 | 512 | end |
| philpem@1 | 513 | |
| philpem@1 | 514 | |
| philpem@1 | 515 | // MB_ADR_O |
| philpem@1 | 516 | |
| philpem@1 | 517 | // set up first address of the dma transfer |
| philpem@1 | 518 | if (reg_start) |
| philpem@1 | 519 | MB_ADR_O_nxt = reg_04_data; |
| philpem@1 | 520 | else if (reg_d_con == 1'b0) |
| philpem@1 | 521 | begin |
| philpem@1 | 522 | // roll back to first address in a burst transfer on a retry |
| philpem@1 | 523 | if (wstate == WR_RETRY) |
| philpem@1 | 524 | MB_ADR_O_nxt = waddr_checkpoint; |
| philpem@1 | 525 | // increment for every regular transfer |
| philpem@1 | 526 | else if (((wstate == WR_SINGLEB) && MB_ACK_I) |
| philpem@1 | 527 | || (MB_ACK_I && (MA_RTY_I == 1'b0) && (MA_ERR_I == 1'b0) |
| philpem@1 | 528 | && ((wstate == WR_SHORT) || (wstate == WR_BURST) || (wstate == WR_SBURST)))) |
| philpem@1 | 529 | MB_ADR_O_nxt = MB_ADR_O + iCount; |
| philpem@1 | 530 | else |
| philpem@1 | 531 | MB_ADR_O_nxt = MB_ADR_O; |
| philpem@1 | 532 | end |
| philpem@1 | 533 | else |
| philpem@1 | 534 | MB_ADR_O_nxt = MB_ADR_O; |
| philpem@1 | 535 | |
| philpem@1 | 536 | |
| philpem@1 | 537 | // MB_CTI_O |
| philpem@1 | 538 | |
| philpem@1 | 539 | // set up classic wishbone cycle |
| philpem@1 | 540 | if ((wstate == WR_SINGLEA) |
| philpem@1 | 541 | || ((wstate == WR_FIFO_CHECK) && (wstate_nxt == WR_SHORT))) |
| philpem@1 | 542 | MB_CTI_O_nxt = 3'b000; |
| philpem@1 | 543 | // set up termination of a wishbone burst cycle |
| philpem@1 | 544 | else if ((wstate == WR_BURST) |
| philpem@1 | 545 | && ((MB_ACK_I && (wburst_count == 6'h1)) || (wstate_nxt == WR_SBURST))) |
| philpem@1 | 546 | MB_CTI_O_nxt = 3'b111; |
| philpem@1 | 547 | // set up wishbone burst (incrementing or constant address) |
| philpem@1 | 548 | else if (((wstate == WR_FIFO_CHECK) && (wstate_nxt == WR_BURST)) |
| philpem@1 | 549 | || ((wstate == WR_BURST) && MB_ACK_I)) |
| philpem@1 | 550 | MB_CTI_O_nxt = reg_s_con ? 3'b001 : 3'b010; |
| philpem@1 | 551 | // hold |
| philpem@1 | 552 | else |
| philpem@1 | 553 | MB_CTI_O_nxt = MB_CTI_O; |
| philpem@1 | 554 | |
| philpem@1 | 555 | // MB_DAT_O |
| philpem@1 | 556 | MB_DAT_O = fifo_dout; |
| philpem@1 | 557 | |
| philpem@1 | 558 | |
| philpem@1 | 559 | // Other signals |
| philpem@1 | 560 | MB_WE_O = 1'b1; |
| philpem@1 | 561 | MB_LOCK_O = 1'b0; |
| philpem@1 | 562 | end |
| philpem@1 | 563 | |
| philpem@1 | 564 | generate |
| philpem@1 | 565 | if (MB_WB_DAT_WIDTH == 8) begin |
| philpem@1 | 566 | |
| philpem@1 | 567 | always @(*) |
| philpem@1 | 568 | MB_SEL_O_nxt = 1'b1; |
| philpem@1 | 569 | |
| philpem@1 | 570 | end |
| philpem@1 | 571 | else begin |
| philpem@1 | 572 | |
| philpem@1 | 573 | always @(/*AUTOSENSE*/MB_ADR_O_nxt or iCount) |
| philpem@1 | 574 | begin |
| philpem@1 | 575 | if (iCount == 1) |
| philpem@1 | 576 | casez (MB_ADR_O_nxt[1:0]) |
| philpem@1 | 577 | 2'b00: MB_SEL_O_nxt = 4'b1000; |
| philpem@1 | 578 | 2'b01: MB_SEL_O_nxt = 4'b0100; |
| philpem@1 | 579 | 2'b10: MB_SEL_O_nxt = 4'b0010; |
| philpem@1 | 580 | 2'b11: MB_SEL_O_nxt = 4'b0001; |
| philpem@1 | 581 | default: |
| philpem@1 | 582 | MB_SEL_O_nxt = 4'b1111; |
| philpem@1 | 583 | endcase |
| philpem@1 | 584 | else if (iCount == 2) |
| philpem@1 | 585 | MB_SEL_O_nxt = MB_ADR_O_nxt[1] ? 4'b0011 : 4'b1100; |
| philpem@1 | 586 | else |
| philpem@1 | 587 | MB_SEL_O_nxt = 4'b1111; |
| philpem@1 | 588 | end |
| philpem@1 | 589 | |
| philpem@1 | 590 | end |
| philpem@1 | 591 | endgenerate |
| philpem@1 | 592 | |
| philpem@1 | 593 | /*---------------------------------------------------------------------- |
| philpem@1 | 594 | Logic to keep track of where we are in the transfer process |
| philpem@1 | 595 | ----------------------------------------------------------------------*/ |
| philpem@1 | 596 | // Increment Count |
| philpem@1 | 597 | generate |
| philpem@1 | 598 | if (S_WB_DAT_WIDTH == 8) begin |
| philpem@1 | 599 | assign iCount = 3'h1; |
| philpem@1 | 600 | end |
| philpem@1 | 601 | else begin |
| philpem@1 | 602 | assign iCount = reg_incw ? 3'h4 : (reg_inchw ? 3'h2 : 3'h1); |
| philpem@1 | 603 | end |
| philpem@1 | 604 | endgenerate |
| philpem@1 | 605 | |
| philpem@1 | 606 | // Burst Count |
| philpem@1 | 607 | assign bCount = (reg_bt3 |
| philpem@1 | 608 | ? (reg_bt2 |
| philpem@1 | 609 | ? 6'h3f |
| philpem@1 | 610 | : (reg_bt1 |
| philpem@1 | 611 | ? (reg_bt0 ? 6'h1f : 6'h0f) |
| philpem@1 | 612 | : (reg_bt0 ? 6'h07 : 6'h03))) |
| philpem@1 | 613 | : 6'h01 |
| philpem@1 | 614 | ); |
| philpem@1 | 615 | |
| philpem@1 | 616 | // Burst Increment Count |
| philpem@1 | 617 | assign biCount = (reg_bt3 |
| philpem@1 | 618 | ? (reg_bt2 |
| philpem@1 | 619 | ? iCount<<6 |
| philpem@1 | 620 | : (reg_bt1 |
| philpem@1 | 621 | ? (reg_bt0 ? iCount<<5 : iCount<<4) |
| philpem@1 | 622 | : (reg_bt0 ? iCount<<3 : iCount<<2) |
| philpem@1 | 623 | ) |
| philpem@1 | 624 | ) |
| philpem@1 | 625 | : iCount |
| philpem@1 | 626 | ); |
| philpem@1 | 627 | |
| philpem@1 | 628 | always @(/*AUTOSENSE*/MA_ACK_I or MB_ACK_I or bCount or biCount |
| philpem@1 | 629 | or fifo_empty or iCount or rburst_count or reg_08_data |
| philpem@1 | 630 | or reg_inchw or reg_incw or reg_start or rstate |
| philpem@1 | 631 | or save_wburst_count or wburst_count or wstate |
| philpem@1 | 632 | or xfer_length) |
| philpem@1 | 633 | begin |
| philpem@1 | 634 | // Transfer Length |
| philpem@1 | 635 | if (reg_start && (wstate == WR_IDLE)) |
| philpem@1 | 636 | xfer_length_nxt = reg_08_data; |
| philpem@1 | 637 | else if (MB_ACK_I && (wstate == WR_SINGLEB)) |
| philpem@1 | 638 | xfer_length_nxt = xfer_length - iCount; |
| philpem@1 | 639 | else if (wstate == WR_SETUPA) |
| philpem@1 | 640 | xfer_length_nxt = (xfer_length >= biCount) ? (xfer_length - biCount) : 0; |
| philpem@1 | 641 | else |
| philpem@1 | 642 | xfer_length_nxt = xfer_length; |
| philpem@1 | 643 | |
| philpem@1 | 644 | // Read-side Burst Count |
| philpem@1 | 645 | if (rstate == RD_IDLE) |
| philpem@1 | 646 | rburst_count_nxt = wburst_count; |
| philpem@1 | 647 | else if ((rstate == RD_BURST) && MA_ACK_I) |
| philpem@1 | 648 | rburst_count_nxt = rburst_count - 1'b1; |
| philpem@1 | 649 | else |
| philpem@1 | 650 | rburst_count_nxt = rburst_count; |
| philpem@1 | 651 | |
| philpem@1 | 652 | // Write-side Burst Count |
| philpem@1 | 653 | if (wstate == WR_SETUPA) |
| philpem@1 | 654 | wburst_count_nxt = ((xfer_length == 0) |
| philpem@1 | 655 | ? 0 |
| philpem@1 | 656 | : ((xfer_length >= biCount) |
| philpem@1 | 657 | ? bCount |
| philpem@1 | 658 | : (xfer_length-1)>>(reg_incw ? 2 : (reg_inchw ? 1 : 0)))); |
| philpem@1 | 659 | else if ((wstate == WR_RETRY) && fifo_empty) |
| philpem@1 | 660 | wburst_count_nxt = save_wburst_count; |
| philpem@1 | 661 | else if (MB_ACK_I |
| philpem@1 | 662 | && ((wstate == WR_SHORT) || (wstate == WR_BURST) || (wstate == WR_SBURST))) |
| philpem@1 | 663 | wburst_count_nxt = wburst_count - 1'b1; |
| philpem@1 | 664 | else |
| philpem@1 | 665 | wburst_count_nxt = wburst_count; |
| philpem@1 | 666 | end |
| philpem@1 | 667 | |
| philpem@1 | 668 | /*---------------------------------------------------------------------- |
| philpem@1 | 669 | Logic to support a burst retry |
| philpem@1 | 670 | ----------------------------------------------------------------------*/ |
| philpem@1 | 671 | always @(/*AUTOSENSE*/MA_ADR_O or MB_ADR_O or raddr_checkpoint |
| philpem@1 | 672 | or reg_rdelay or retry_delay or rstate or rstate_nxt |
| philpem@1 | 673 | or save_wburst_count or waddr_checkpoint |
| philpem@1 | 674 | or wburst_count_nxt or wstate or wstate_nxt) |
| philpem@1 | 675 | begin |
| philpem@1 | 676 | // Write-side Saved Burst Count |
| philpem@1 | 677 | if (wstate == WR_SETUPA) |
| philpem@1 | 678 | save_wburst_count_nxt = wburst_count_nxt; |
| philpem@1 | 679 | else |
| philpem@1 | 680 | save_wburst_count_nxt = save_wburst_count; |
| philpem@1 | 681 | |
| philpem@1 | 682 | // Retry Delay |
| philpem@1 | 683 | if (((wstate != WR_RETRY) && (wstate_nxt == WR_RETRY)) |
| philpem@1 | 684 | || ((rstate == RD_SINGLEA) && (rstate_nxt == RD_SINGLE_RETRY))) |
| philpem@1 | 685 | retry_delay_nxt = reg_rdelay; |
| philpem@1 | 686 | else if ((wstate == WR_RETRY) || (rstate == RD_SINGLE_RETRY)) |
| philpem@1 | 687 | retry_delay_nxt = retry_delay - 1'b1; |
| philpem@1 | 688 | else |
| philpem@1 | 689 | retry_delay_nxt = retry_delay; |
| philpem@1 | 690 | |
| philpem@1 | 691 | // Read Address Checkpoint |
| philpem@1 | 692 | if ((rstate == RD_IDLE) && (rstate_nxt == RD_BURST)) |
| philpem@1 | 693 | raddr_checkpoint_nxt = MA_ADR_O; |
| philpem@1 | 694 | else |
| philpem@1 | 695 | raddr_checkpoint_nxt = raddr_checkpoint; |
| philpem@1 | 696 | |
| philpem@1 | 697 | // Write Address Checkpoint |
| philpem@1 | 698 | if (wstate == WR_SETUPA) |
| philpem@1 | 699 | waddr_checkpoint_nxt = MB_ADR_O; |
| philpem@1 | 700 | else |
| philpem@1 | 701 | waddr_checkpoint_nxt = waddr_checkpoint; |
| philpem@1 | 702 | end |
| philpem@1 | 703 | |
| philpem@1 | 704 | /*---------------------------------------------------------------------- |
| philpem@1 | 705 | Logic to indicate start/end of transfer and bursts |
| philpem@1 | 706 | ----------------------------------------------------------------------*/ |
| philpem@1 | 707 | always @(/*AUTOSENSE*/MA_ERR_I or MB_ACK_I or MB_ERR_I or iCount |
| philpem@1 | 708 | or retry_delay or wburst_count or wstate or xfer_length) |
| philpem@1 | 709 | begin |
| philpem@1 | 710 | if (((wstate == WR_SINGLEB) && (xfer_length > iCount) && MB_ACK_I) |
| philpem@1 | 711 | || ((wstate == WR_SETUPB) && (wburst_count > 0)) |
| philpem@1 | 712 | || ((wstate == WR_RETRY) && (retry_delay == 8'b0))) |
| philpem@1 | 713 | burst_start = 1'b1; |
| philpem@1 | 714 | else |
| philpem@1 | 715 | burst_start = 1'b0; |
| philpem@1 | 716 | |
| philpem@1 | 717 | if (MB_ERR_I |
| philpem@1 | 718 | || MA_ERR_I |
| philpem@1 | 719 | || ((wstate == WR_SINGLEB) && (xfer_length == iCount) && MB_ACK_I) |
| philpem@1 | 720 | || ((wstate == WR_SETUPB) && (wburst_count == 0))) |
| philpem@1 | 721 | xfer_done = 1'b1; |
| philpem@1 | 722 | else |
| philpem@1 | 723 | xfer_done = 1'b0; |
| philpem@1 | 724 | end |
| philpem@0 | 725 | |
| philpem@1 | 726 | /*---------------------------------------------------------------------- |
| philpem@1 | 727 | Sequential Logic |
| philpem@1 | 728 | ----------------------------------------------------------------------*/ |
| philpem@0 | 729 | always @(posedge CLK_I or posedge RST_I) |
| philpem@1 | 730 | if (RST_I) |
| philpem@0 | 731 | begin |
| philpem@1 | 732 | rstate <= #UDLY RD_IDLE; |
| philpem@1 | 733 | wstate <= #UDLY WR_IDLE; |
| philpem@1 | 734 | xfer_length <= #UDLY 32'b0; |
| philpem@1 | 735 | rburst_count <= #UDLY 6'b0; |
| philpem@1 | 736 | wburst_count <= #UDLY 6'b0; |
| philpem@1 | 737 | retry_delay <= #UDLY 8'b0; |
| philpem@1 | 738 | reg_status <= #UDLY 1'b0; |
| philpem@1 | 739 | MA_CYC_O <= #UDLY 1'b0; |
| philpem@1 | 740 | MA_CYC_O_d <= #UDLY 1'b0; |
| philpem@1 | 741 | MA_STB_O <= #UDLY 1'b0; |
| philpem@1 | 742 | MA_CTI_O <= #UDLY 3'b0; |
| philpem@1 | 743 | MA_ADR_O <= #UDLY 'b0; |
| philpem@1 | 744 | MA_SEL_O <= #UDLY 'b0; |
| philpem@1 | 745 | MB_CYC_O <= #UDLY 1'b0; |
| philpem@1 | 746 | MB_CYC_O_d <= #UDLY 1'b0; |
| philpem@1 | 747 | MB_STB_O <= #UDLY 1'b0; |
| philpem@1 | 748 | MB_CTI_O <= #UDLY 3'b0; |
| philpem@1 | 749 | MB_ADR_O <= #UDLY 'b0; |
| philpem@1 | 750 | MB_SEL_O <= #UDLY 'b0; |
| philpem@1 | 751 | raddr_checkpoint <= #UDLY 32'b0; |
| philpem@1 | 752 | waddr_checkpoint <= #UDLY 32'b0; |
| philpem@1 | 753 | save_wburst_count <= #UDLY 6'b0; |
| philpem@0 | 754 | end |
| philpem@1 | 755 | else |
| philpem@0 | 756 | begin |
| philpem@1 | 757 | rstate <= #UDLY rstate_nxt; |
| philpem@1 | 758 | wstate <= #UDLY wstate_nxt; |
| philpem@1 | 759 | xfer_length <= #UDLY xfer_length_nxt; |
| philpem@1 | 760 | rburst_count <= #UDLY rburst_count_nxt; |
| philpem@1 | 761 | wburst_count <= #UDLY wburst_count_nxt; |
| philpem@1 | 762 | retry_delay <= #UDLY retry_delay_nxt; |
| philpem@1 | 763 | reg_status <= #UDLY reg_status_nxt; |
| philpem@1 | 764 | MA_CYC_O <= #UDLY MA_CYC_O_nxt; |
| philpem@1 | 765 | MA_CYC_O_d <= #UDLY MA_CYC_O; |
| philpem@1 | 766 | MA_STB_O <= #UDLY MA_STB_O_nxt; |
| philpem@1 | 767 | MA_CTI_O <= #UDLY MA_CTI_O_nxt; |
| philpem@1 | 768 | MA_ADR_O <= #UDLY MA_ADR_O_nxt; |
| philpem@1 | 769 | MA_SEL_O <= #UDLY MA_SEL_O_nxt; |
| philpem@1 | 770 | MB_CYC_O <= #UDLY MB_CYC_O_nxt; |
| philpem@1 | 771 | MB_CYC_O_d <= #UDLY MB_CYC_O; |
| philpem@1 | 772 | MB_STB_O <= #UDLY MB_STB_O_nxt; |
| philpem@1 | 773 | MB_CTI_O <= #UDLY MB_CTI_O_nxt; |
| philpem@1 | 774 | MB_ADR_O <= #UDLY MB_ADR_O_nxt; |
| philpem@1 | 775 | MB_SEL_O <= #UDLY MB_SEL_O_nxt; |
| philpem@1 | 776 | raddr_checkpoint <= #UDLY raddr_checkpoint_nxt; |
| philpem@1 | 777 | waddr_checkpoint <= #UDLY waddr_checkpoint_nxt; |
| philpem@1 | 778 | save_wburst_count <= #UDLY save_wburst_count_nxt; |
| philpem@0 | 779 | end |
| philpem@0 | 780 | |
| philpem@1 | 781 | /*---------------------------------------------------------------------- |
| philpem@1 | 782 | FIFO Logic |
| philpem@1 | 783 | ----------------------------------------------------------------------*/ |
| philpem@1 | 784 | reg fifo_rd_en, fifo_wr_en; |
| philpem@1 | 785 | always @(/*AUTOSENSE*/MA_ACK_I or MA_DAT_I or MB_ACK_I |
| philpem@1 | 786 | or fifo_aempty or fifo_empty or rstate or wburst_count |
| philpem@1 | 787 | or wstate) |
| philpem@1 | 788 | begin |
| philpem@1 | 789 | if (((wstate == WR_SINGLEA) && (fifo_empty == 1'b0)) |
| philpem@1 | 790 | || ((wstate == WR_FIFO_CHECK) |
| philpem@1 | 791 | && (((fifo_empty == 1'b0) && (wburst_count == 6'h0)) |
| philpem@1 | 792 | || ((fifo_aempty == 1'b0) && (wburst_count >= 6'h1)))) |
| philpem@1 | 793 | || ((wstate == WR_BURST) |
| philpem@1 | 794 | && (/*(MB_CYC_O_d == 1'b0) |
| philpem@1 | 795 | ||*/ (MB_ACK_I && (wburst_count >= 6'h1)))) |
| philpem@1 | 796 | || ((wstate == WR_ERROR) && (fifo_empty == 1'b0)) |
| philpem@1 | 797 | || ((wstate == WR_RETRY) && (fifo_empty == 1'b0))) |
| philpem@1 | 798 | fifo_rd_en = 1'b1; |
| philpem@1 | 799 | else |
| philpem@1 | 800 | fifo_rd_en = 1'b0; |
| philpem@1 | 801 | |
| philpem@1 | 802 | if (MA_ACK_I |
| philpem@1 | 803 | && ((rstate == RD_SINGLEA) || (rstate == RD_BURST))) |
| philpem@1 | 804 | fifo_wr_en = 1'b1; |
| philpem@1 | 805 | else |
| philpem@1 | 806 | fifo_wr_en = 1'b0; |
| philpem@1 | 807 | |
| philpem@1 | 808 | fifo_din = MA_DAT_I; |
| philpem@1 | 809 | end |
| philpem@1 | 810 | |
| philpem@0 | 811 | generate |
| philpem@0 | 812 | if (lat_family == "SC" || lat_family == "SCM") begin |
| philpem@1 | 813 | |
| philpem@1 | 814 | pmi_fifo_dc |
| philpem@1 | 815 | #(.pmi_data_width_w(MA_WB_DAT_WIDTH), |
| philpem@1 | 816 | .pmi_data_width_r(MA_WB_DAT_WIDTH), |
| philpem@1 | 817 | .pmi_data_depth_w(64), |
| philpem@1 | 818 | .pmi_data_depth_r(64), |
| philpem@1 | 819 | .pmi_full_flag(64), |
| philpem@1 | 820 | .pmi_empty_flag(0), |
| philpem@1 | 821 | .pmi_almost_full_flag(60), |
| philpem@1 | 822 | .pmi_almost_empty_flag(4), |
| philpem@1 | 823 | .pmi_regmode("noreg"), |
| philpem@1 | 824 | .pmi_family(`LATTICE_FAMILY), |
| philpem@1 | 825 | .module_type("pmi_fifo_dc"), |
| philpem@1 | 826 | .pmi_implementation(FIFO_IMPLEMENTATION)) |
| philpem@1 | 827 | dma_fifo_dc |
| philpem@1 | 828 | ( |
| philpem@1 | 829 | .Data(fifo_din), |
| philpem@1 | 830 | .WrClock (CLK_I), |
| philpem@1 | 831 | .RdClock (CLK_I), |
| philpem@1 | 832 | .WrEn (fifo_wr_en), |
| philpem@1 | 833 | .RdEn (fifo_rd_en), |
| philpem@1 | 834 | .Reset (RST_I), |
| philpem@1 | 835 | .RPReset (RST_I), |
| philpem@1 | 836 | .Q (fifo_dout), |
| philpem@1 | 837 | .Empty (fifo_empty), |
| philpem@1 | 838 | .Full (), |
| philpem@1 | 839 | .AlmostEmpty(), |
| philpem@1 | 840 | .AlmostFull ()); |
| philpem@1 | 841 | |
| philpem@1 | 842 | end else if (lat_family == "MachXO2") begin |
| philpem@1 | 843 | |
| philpem@1 | 844 | pmi_fifo_dc |
| philpem@1 | 845 | #(.pmi_data_width_w (MA_WB_DAT_WIDTH), |
| philpem@1 | 846 | .pmi_data_width_r (MA_WB_DAT_WIDTH), |
| philpem@1 | 847 | .pmi_data_depth_w (64), |
| philpem@1 | 848 | .pmi_data_depth_r (64), |
| philpem@1 | 849 | .pmi_full_flag (64), |
| philpem@1 | 850 | .pmi_empty_flag (0), |
| philpem@1 | 851 | .pmi_almost_full_flag (60), |
| philpem@1 | 852 | .pmi_almost_empty_flag (1), |
| philpem@1 | 853 | .pmi_regmode ("noreg"), |
| philpem@1 | 854 | .pmi_family ("XO2"), |
| philpem@1 | 855 | .module_type ("pmi_fifo_dc"), |
| philpem@1 | 856 | .pmi_implementation (FIFO_IMPLEMENTATION)) |
| philpem@1 | 857 | dma_fifo |
| philpem@1 | 858 | (.Data (fifo_din), |
| philpem@1 | 859 | .WrClock (CLK_I), |
| philpem@1 | 860 | .RdClock (CLK_I), |
| philpem@1 | 861 | .WrEn (fifo_wr_en), |
| philpem@1 | 862 | .RdEn (fifo_rd_en), |
| philpem@1 | 863 | .Reset (RST_I), |
| philpem@1 | 864 | .RPReset (RST_I), |
| philpem@1 | 865 | .Q (fifo_dout), |
| philpem@1 | 866 | .Empty (fifo_empty), |
| philpem@1 | 867 | .Full (), |
| philpem@1 | 868 | .AlmostEmpty(fifo_aempty), |
| philpem@1 | 869 | .AlmostFull ()); |
| philpem@0 | 870 | |
| philpem@0 | 871 | end else begin |
| philpem@1 | 872 | |
| philpem@1 | 873 | pmi_fifo |
| philpem@1 | 874 | #(.pmi_data_width(MA_WB_DAT_WIDTH), |
| philpem@1 | 875 | .pmi_data_depth(64), |
| philpem@1 | 876 | .pmi_full_flag(64), |
| philpem@1 | 877 | .pmi_empty_flag(0), |
| philpem@1 | 878 | .pmi_almost_full_flag(60), |
| philpem@1 | 879 | .pmi_almost_empty_flag(1), |
| philpem@1 | 880 | .pmi_regmode("noreg"), |
| philpem@1 | 881 | .pmi_family(`LATTICE_FAMILY), |
| philpem@1 | 882 | .module_type("pmi_fifo"), |
| philpem@1 | 883 | .pmi_implementation(FIFO_IMPLEMENTATION)) |
| philpem@1 | 884 | dma_fifo |
| philpem@1 | 885 | (.Data (fifo_din), |
| philpem@1 | 886 | .Clock (CLK_I), |
| philpem@1 | 887 | .WrEn (fifo_wr_en), |
| philpem@1 | 888 | .RdEn (fifo_rd_en), |
| philpem@1 | 889 | .Reset (RST_I), |
| philpem@1 | 890 | .Q (fifo_dout), |
| philpem@1 | 891 | .Empty (fifo_empty), |
| philpem@1 | 892 | .Full (), |
| philpem@1 | 893 | .AlmostEmpty(fifo_aempty), |
| philpem@1 | 894 | .AlmostFull ()); |
| philpem@1 | 895 | |
| philpem@1 | 896 | end |
| philpem@1 | 897 | |
| philpem@0 | 898 | endgenerate |
| philpem@0 | 899 | |
| philpem@1 | 900 | endmodule |
| philpem@0 | 901 | |
| philpem@1 | 902 | `endif // `ifndef MASTER_CTRL_FILE |