blob: 2d0b6feb01c3d146546b9e6a1d494ea6f7e5addf [file] [log] [blame]
Tim Edwardscd64af52020-08-07 11:11:58 -04001/*
2 * PicoSoC - A simple example SoC using PicoRV32
3 *
4 * Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
shalanfd13eb52020-08-21 16:48:07 +020020module spimemio_wb (
21 input wb_clk_i,
22 input wb_rst_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040023
shalanfd13eb52020-08-21 16:48:07 +020024 input [31:0] wb_adr_i,
Tim Edwards04ba17f2020-10-02 22:27:50 -040025 input [31:0] wb_dat_i,
shalanfd13eb52020-08-21 16:48:07 +020026 input [3:0] wb_sel_i,
27 input wb_we_i,
28 input wb_cyc_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040029
shalanfd13eb52020-08-21 16:48:07 +020030 input wb_flash_stb_i,
31 input wb_cfg_stb_i,
Tim Edwardscd64af52020-08-07 11:11:58 -040032
shalanfd13eb52020-08-21 16:48:07 +020033 output wb_flash_ack_o,
34 output wb_cfg_ack_o,
Tim Edwardscd64af52020-08-07 11:11:58 -040035
shalanfd13eb52020-08-21 16:48:07 +020036 output [31:0] wb_flash_dat_o,
37 output [31:0] wb_cfg_dat_o,
Tim Edwardscd64af52020-08-07 11:11:58 -040038
Tim Edwards04ba17f2020-10-02 22:27:50 -040039 input pass_thru,
40 input pass_thru_csb,
41 input pass_thru_sck,
42 input pass_thru_sdi,
43 output pass_thru_sdo,
44
shalanfd13eb52020-08-21 16:48:07 +020045 output flash_csb,
46 output flash_clk,
Tim Edwardscd64af52020-08-07 11:11:58 -040047
shalanfd13eb52020-08-21 16:48:07 +020048 output flash_csb_oeb,
49 output flash_clk_oeb,
Tim Edwardscd64af52020-08-07 11:11:58 -040050
shalanfd13eb52020-08-21 16:48:07 +020051 output flash_io0_oeb,
52 output flash_io1_oeb,
53 output flash_io2_oeb,
54 output flash_io3_oeb,
Tim Edwardscd64af52020-08-07 11:11:58 -040055
shalanfd13eb52020-08-21 16:48:07 +020056 output flash_csb_ieb,
57 output flash_clk_ieb,
Tim Edwardscd64af52020-08-07 11:11:58 -040058
shalanfd13eb52020-08-21 16:48:07 +020059 output flash_io0_ieb,
60 output flash_io1_ieb,
61 output flash_io2_ieb,
62 output flash_io3_ieb,
63
64 output flash_io0_do,
65 output flash_io1_do,
66 output flash_io2_do,
67 output flash_io3_do,
68
69 input flash_io0_di,
70 input flash_io1_di,
71 input flash_io2_di,
72 input flash_io3_di
73
Tim Edwardscd64af52020-08-07 11:11:58 -040074);
shalanfd13eb52020-08-21 16:48:07 +020075 wire spimem_ready;
76 wire [23:0] mem_addr;
77 wire [31:0] spimem_rdata;
78 wire [31:0] spimemio_cfgreg_do;
79 wire [3:0] cfgreg_we;
80 wire spimemio_cfgreg_sel;
81 wire valid;
82 wire resetn;
Tim Edwardscd64af52020-08-07 11:11:58 -040083
shalanfd13eb52020-08-21 16:48:07 +020084 assign resetn = ~wb_rst_i;
85 assign valid = wb_cyc_i && wb_flash_stb_i;
86 assign wb_flash_ack_o = spimem_ready;
87 assign wb_cfg_ack_o = spimemio_cfgreg_sel;
Tim Edwardscd64af52020-08-07 11:11:58 -040088
shalanfd13eb52020-08-21 16:48:07 +020089 assign mem_addr = wb_adr_i[23:0];
90 assign spimemio_cfgreg_sel = wb_cyc_i && wb_cfg_stb_i;
Tim Edwardscd64af52020-08-07 11:11:58 -040091
shalanfd13eb52020-08-21 16:48:07 +020092 assign cfgreg_we = spimemio_cfgreg_sel ? wb_sel_i & {4{wb_we_i}} : 4'b 0000;
93 assign wb_flash_dat_o = spimem_rdata;
94 assign wb_cfg_dat_o = spimemio_cfgreg_do;
Tim Edwardscd64af52020-08-07 11:11:58 -040095
shalanfd13eb52020-08-21 16:48:07 +020096 spimemio spimemio (
97 .clk (wb_clk_i),
98 .resetn (resetn),
99 .valid (valid),
100 .ready (spimem_ready),
101 .addr (mem_addr),
102 .rdata (spimem_rdata),
Tim Edwardscd64af52020-08-07 11:11:58 -0400103
shalanfd13eb52020-08-21 16:48:07 +0200104 .flash_csb (flash_csb),
105 .flash_clk (flash_clk),
Tim Edwardscd64af52020-08-07 11:11:58 -0400106
shalanfd13eb52020-08-21 16:48:07 +0200107 .flash_csb_oeb (flash_csb_oeb),
108 .flash_clk_oeb (flash_clk_oeb),
Tim Edwardscd64af52020-08-07 11:11:58 -0400109
shalanfd13eb52020-08-21 16:48:07 +0200110 .flash_io0_oeb (flash_io0_oeb),
111 .flash_io1_oeb (flash_io1_oeb),
112 .flash_io2_oeb (flash_io2_oeb),
113 .flash_io3_oeb (flash_io3_oeb),
Tim Edwardscd64af52020-08-07 11:11:58 -0400114
shalanfd13eb52020-08-21 16:48:07 +0200115 .flash_csb_ieb (flash_csb_ieb),
116 .flash_clk_ieb (flash_clk_ieb),
Tim Edwardscd64af52020-08-07 11:11:58 -0400117
shalanfd13eb52020-08-21 16:48:07 +0200118 .flash_io0_ieb (flash_io0_ieb),
119 .flash_io1_ieb (flash_io1_ieb),
120 .flash_io2_ieb (flash_io2_ieb),
121 .flash_io3_ieb (flash_io3_ieb),
Tim Edwardscd64af52020-08-07 11:11:58 -0400122
shalanfd13eb52020-08-21 16:48:07 +0200123 .flash_io0_do (flash_io0_do),
124 .flash_io1_do (flash_io1_do),
125 .flash_io2_do (flash_io2_do),
126 .flash_io3_do (flash_io3_do),
Tim Edwardscd64af52020-08-07 11:11:58 -0400127
shalanfd13eb52020-08-21 16:48:07 +0200128 .flash_io0_di (flash_io0_di),
129 .flash_io1_di (flash_io1_di),
130 .flash_io2_di (flash_io2_di),
131 .flash_io3_di (flash_io3_di),
Tim Edwardscd64af52020-08-07 11:11:58 -0400132
shalanfd13eb52020-08-21 16:48:07 +0200133 .cfgreg_we(cfgreg_we),
134 .cfgreg_di(wb_dat_i),
Tim Edwards44bab472020-10-04 22:09:54 -0400135 .cfgreg_do(spimemio_cfgreg_do),
136
137 .pass_thru(pass_thru),
138 .pass_thru_csb(pass_thru_csb),
139 .pass_thru_sck(pass_thru_sck),
140 .pass_thru_sdi(pass_thru_sdi),
141 .pass_thru_sdo(pass_thru_sdo)
shalanfd13eb52020-08-21 16:48:07 +0200142 );
Tim Edwardscd64af52020-08-07 11:11:58 -0400143
shalanfd13eb52020-08-21 16:48:07 +0200144endmodule
Tim Edwardscd64af52020-08-07 11:11:58 -0400145
shalanfd13eb52020-08-21 16:48:07 +0200146module spimemio (
147 input clk, resetn,
Tim Edwardscd64af52020-08-07 11:11:58 -0400148
shalanfd13eb52020-08-21 16:48:07 +0200149 input valid,
150 output ready,
151 input [23:0] addr,
152 output reg [31:0] rdata,
Tim Edwardscd64af52020-08-07 11:11:58 -0400153
shalanfd13eb52020-08-21 16:48:07 +0200154 output flash_csb,
155 output flash_clk,
Tim Edwardscd64af52020-08-07 11:11:58 -0400156
shalanfd13eb52020-08-21 16:48:07 +0200157 output flash_csb_oeb,
158 output flash_clk_oeb,
Tim Edwardscd64af52020-08-07 11:11:58 -0400159
shalanfd13eb52020-08-21 16:48:07 +0200160 output flash_io0_oeb,
161 output flash_io1_oeb,
162 output flash_io2_oeb,
163 output flash_io3_oeb,
Tim Edwardscd64af52020-08-07 11:11:58 -0400164
shalanfd13eb52020-08-21 16:48:07 +0200165 output flash_csb_ieb,
166 output flash_clk_ieb,
Tim Edwardscd64af52020-08-07 11:11:58 -0400167
shalanfd13eb52020-08-21 16:48:07 +0200168 output flash_io0_ieb,
169 output flash_io1_ieb,
170 output flash_io2_ieb,
171 output flash_io3_ieb,
Tim Edwardscd64af52020-08-07 11:11:58 -0400172
shalanfd13eb52020-08-21 16:48:07 +0200173 output flash_io0_do,
174 output flash_io1_do,
175 output flash_io2_do,
176 output flash_io3_do,
Tim Edwardscd64af52020-08-07 11:11:58 -0400177
shalanfd13eb52020-08-21 16:48:07 +0200178 input flash_io0_di,
179 input flash_io1_di,
180 input flash_io2_di,
181 input flash_io3_di,
Tim Edwardscd64af52020-08-07 11:11:58 -0400182
shalanfd13eb52020-08-21 16:48:07 +0200183 input [3:0] cfgreg_we,
184 input [31:0] cfgreg_di,
Tim Edwards44bab472020-10-04 22:09:54 -0400185 output [31:0] cfgreg_do,
186
187 input pass_thru,
188 input pass_thru_csb,
189 input pass_thru_sck,
190 input pass_thru_sdi,
191 output pass_thru_sdo
shalanfd13eb52020-08-21 16:48:07 +0200192);
193 reg xfer_resetn;
194 reg din_valid;
195 wire din_ready;
196 reg [7:0] din_data;
197 reg [3:0] din_tag;
198 reg din_cont;
199 reg din_qspi;
200 reg din_ddr;
201 reg din_rd;
Tim Edwardscd64af52020-08-07 11:11:58 -0400202
shalanfd13eb52020-08-21 16:48:07 +0200203 wire dout_valid;
204 wire [7:0] dout_data;
205 wire [3:0] dout_tag;
Tim Edwardscd64af52020-08-07 11:11:58 -0400206
shalanfd13eb52020-08-21 16:48:07 +0200207 reg [23:0] buffer;
Tim Edwardscd64af52020-08-07 11:11:58 -0400208
shalanfd13eb52020-08-21 16:48:07 +0200209 reg [23:0] rd_addr;
210 reg rd_valid;
211 reg rd_wait;
212 reg rd_inc;
213
214 assign ready = valid && (addr == rd_addr) && rd_valid;
215 wire jump = valid && !ready && (addr != rd_addr+4) && rd_valid;
216
217 reg softreset;
218
219 reg config_en; // cfgreg[31]
220 reg config_ddr; // cfgreg[22]
221 reg config_qspi; // cfgreg[21]
222 reg config_cont; // cfgreg[20]
223 reg [3:0] config_dummy; // cfgreg[19:16]
224 reg [3:0] config_oe; // cfgreg[11:8]
225 reg config_csb; // cfgreg[5]
226 reg config_clk; // cfgref[4]
227 reg [3:0] config_do; // cfgreg[3:0]
228
229 assign cfgreg_do[31] = config_en;
230 assign cfgreg_do[30:23] = 0;
231 assign cfgreg_do[22] = config_ddr;
232 assign cfgreg_do[21] = config_qspi;
233 assign cfgreg_do[20] = config_cont;
234 assign cfgreg_do[19:16] = config_dummy;
235 assign cfgreg_do[15:12] = 0;
236 assign cfgreg_do[11:8] = {~flash_io3_oeb, ~flash_io2_oeb, ~flash_io1_oeb, ~flash_io0_oeb};
237 assign cfgreg_do[7:6] = 0;
238 assign cfgreg_do[5] = flash_csb;
239 assign cfgreg_do[4] = flash_clk;
240 assign cfgreg_do[3:0] = {flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
241
242 always @(posedge clk) begin
243 softreset <= !config_en || cfgreg_we;
244 if (!resetn) begin
245 softreset <= 1;
246 config_en <= 1;
247 config_csb <= 0;
248 config_clk <= 0;
249 config_oe <= 0;
250 config_do <= 0;
251 config_ddr <= 0;
252 config_qspi <= 0;
253 config_cont <= 0;
254 config_dummy <= 8;
255 end else begin
256 if (cfgreg_we[0]) begin
257 config_csb <= cfgreg_di[5];
258 config_clk <= cfgreg_di[4];
259 config_do <= cfgreg_di[3:0];
260 end
261 if (cfgreg_we[1]) begin
262 config_oe <= cfgreg_di[11:8];
263 end
264 if (cfgreg_we[2]) begin
265 config_ddr <= cfgreg_di[22];
266 config_qspi <= cfgreg_di[21];
267 config_cont <= cfgreg_di[20];
268 config_dummy <= cfgreg_di[19:16];
269 end
270 if (cfgreg_we[3]) begin
271 config_en <= cfgreg_di[31];
272 end
273 end
274 end
275
276 wire xfer_csb;
277 wire xfer_clk;
278
279 wire xfer_io0_oe;
280 wire xfer_io1_oe;
281 wire xfer_io2_oe;
282 wire xfer_io3_oe;
283
284 wire xfer_io0_do;
285 wire xfer_io1_do;
286 wire xfer_io2_do;
287 wire xfer_io3_do;
288
289 reg xfer_io0_90;
290 reg xfer_io1_90;
291 reg xfer_io2_90;
292 reg xfer_io3_90;
293
294 always @(negedge clk) begin
295 xfer_io0_90 <= xfer_io0_do;
296 xfer_io1_90 <= xfer_io1_do;
297 xfer_io2_90 <= xfer_io2_do;
298 xfer_io3_90 <= xfer_io3_do;
299 end
300
Tim Edwards04ba17f2020-10-02 22:27:50 -0400301 wire pass_thru;
302 wire pass_thru_csb;
303 wire pass_thru_sck;
304 wire pass_thru_sdi;
305 wire pass_thru_sdo;
shalanfd13eb52020-08-21 16:48:07 +0200306
Tim Edwards04ba17f2020-10-02 22:27:50 -0400307 assign flash_csb = (pass_thru) ? pass_thru_csb : (config_en ? xfer_csb : config_csb);
308 assign flash_clk = (pass_thru) ? pass_thru_sck : (config_en ? xfer_clk : config_clk);
shalanfd13eb52020-08-21 16:48:07 +0200309
Tim Edwards04ba17f2020-10-02 22:27:50 -0400310 assign flash_csb_oeb = (pass_thru) ? 1'b0 : (~resetn ? 1'b1 : 1'b0);
311 assign flash_clk_oeb = (pass_thru) ? 1'b0 : (~resetn ? 1'b1 : 1'b0);
312
313 assign flash_io0_oeb = pass_thru ? 1'b0 : ~resetn ? 1'b1 : (config_en ? ~xfer_io0_oe : ~config_oe[0]);
314 assign flash_io1_oeb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? ~xfer_io1_oe : ~config_oe[1]);
315 assign flash_io2_oeb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? ~xfer_io2_oe : ~config_oe[2]);
316 assign flash_io3_oeb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? ~xfer_io3_oe : ~config_oe[3]);
shalanfd13eb52020-08-21 16:48:07 +0200317 assign flash_csb_ieb = 1'b1; /* Always disabled */
318 assign flash_clk_ieb = 1'b1; /* Always disabled */
319
Tim Edwards04ba17f2020-10-02 22:27:50 -0400320 assign flash_io0_ieb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? xfer_io0_oe : config_oe[0]);
321 assign flash_io1_ieb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? xfer_io1_oe : config_oe[1]);
322 assign flash_io2_ieb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? xfer_io2_oe : config_oe[2]);
323 assign flash_io3_ieb = (pass_thru | ~resetn) ? 1'b1 : (config_en ? xfer_io3_oe : config_oe[3]);
shalanfd13eb52020-08-21 16:48:07 +0200324
Tim Edwards04ba17f2020-10-02 22:27:50 -0400325 assign flash_io0_do = pass_thru ? pass_thru_sdi : (config_en ? (config_ddr ? xfer_io0_90 : xfer_io0_do) : config_do[0]);
shalanfd13eb52020-08-21 16:48:07 +0200326 assign flash_io1_do = config_en ? (config_ddr ? xfer_io1_90 : xfer_io1_do) : config_do[1];
327 assign flash_io2_do = config_en ? (config_ddr ? xfer_io2_90 : xfer_io2_do) : config_do[2];
328 assign flash_io3_do = config_en ? (config_ddr ? xfer_io3_90 : xfer_io3_do) : config_do[3];
Tim Edwards04ba17f2020-10-02 22:27:50 -0400329 assign pass_thru_sdo = pass_thru ? flash_io1_di : 1'b0;
shalanfd13eb52020-08-21 16:48:07 +0200330
331 wire xfer_dspi = din_ddr && !din_qspi;
332 wire xfer_ddr = din_ddr && din_qspi;
333
334 spimemio_xfer xfer (
335 .clk (clk ),
336 .resetn (resetn ),
337 .xfer_resetn (xfer_resetn ),
338 .din_valid (din_valid ),
339 .din_ready (din_ready ),
340 .din_data (din_data ),
341 .din_tag (din_tag ),
342 .din_cont (din_cont ),
343 .din_dspi (xfer_dspi ),
344 .din_qspi (din_qspi ),
345 .din_ddr (xfer_ddr ),
346 .din_rd (din_rd ),
347 .dout_valid (dout_valid ),
348 .dout_data (dout_data ),
349 .dout_tag (dout_tag ),
350 .flash_csb (xfer_csb ),
351 .flash_clk (xfer_clk ),
352 .flash_io0_oe (xfer_io0_oe ),
353 .flash_io1_oe (xfer_io1_oe ),
354 .flash_io2_oe (xfer_io2_oe ),
355 .flash_io3_oe (xfer_io3_oe ),
356 .flash_io0_do (xfer_io0_do ),
357 .flash_io1_do (xfer_io1_do ),
358 .flash_io2_do (xfer_io2_do ),
359 .flash_io3_do (xfer_io3_do ),
360 .flash_io0_di (flash_io0_di),
361 .flash_io1_di (flash_io1_di),
362 .flash_io2_di (flash_io2_di),
363 .flash_io3_di (flash_io3_di)
364 );
365
366 reg [3:0] state;
367
368 always @(posedge clk) begin
369 xfer_resetn <= 1;
370 din_valid <= 0;
371
372 if (!resetn || softreset) begin
373 state <= 0;
374 xfer_resetn <= 0;
375 rd_valid <= 0;
376 din_tag <= 0;
377 din_cont <= 0;
378 din_qspi <= 0;
379 din_ddr <= 0;
380 din_rd <= 0;
381 end else begin
382 if (dout_valid && dout_tag == 1) buffer[ 7: 0] <= dout_data;
383 if (dout_valid && dout_tag == 2) buffer[15: 8] <= dout_data;
384 if (dout_valid && dout_tag == 3) buffer[23:16] <= dout_data;
385 if (dout_valid && dout_tag == 4) begin
386 rdata <= {dout_data, buffer};
387 rd_addr <= rd_inc ? rd_addr + 4 : addr;
388 rd_valid <= 1;
389 rd_wait <= rd_inc;
390 rd_inc <= 1;
391 end
392
393 if (valid)
394 rd_wait <= 0;
395
396 case (state)
397 0: begin
398 din_valid <= 1;
399 din_data <= 8'h ff;
400 din_tag <= 0;
401 if (din_ready) begin
402 din_valid <= 0;
403 state <= 1;
404 end
405 end
406 1: begin
407 if (dout_valid) begin
408 xfer_resetn <= 0;
409 state <= 2;
410 end
411 end
412 2: begin
413 din_valid <= 1;
414 din_data <= 8'h ab;
415 din_tag <= 0;
416 if (din_ready) begin
417 din_valid <= 0;
418 state <= 3;
419 end
420 end
421 3: begin
422 if (dout_valid) begin
423 xfer_resetn <= 0;
424 state <= 4;
425 end
426 end
427 4: begin
428 rd_inc <= 0;
429 din_valid <= 1;
430 din_tag <= 0;
431 case ({config_ddr, config_qspi})
432 2'b11: din_data <= 8'h ED;
433 2'b01: din_data <= 8'h EB;
434 2'b10: din_data <= 8'h BB;
435 2'b00: din_data <= 8'h 03;
436 endcase
437 if (din_ready) begin
438 din_valid <= 0;
439 state <= 5;
440 end
441 end
442 5: begin
443 if (valid && !ready) begin
444 din_valid <= 1;
445 din_tag <= 0;
446 din_data <= addr[23:16];
447 din_qspi <= config_qspi;
448 din_ddr <= config_ddr;
449 if (din_ready) begin
450 din_valid <= 0;
451 state <= 6;
452 end
453 end
454 end
455 6: begin
456 din_valid <= 1;
457 din_tag <= 0;
458 din_data <= addr[15:8];
459 if (din_ready) begin
460 din_valid <= 0;
461 state <= 7;
462 end
463 end
464 7: begin
465 din_valid <= 1;
466 din_tag <= 0;
467 din_data <= addr[7:0];
468 if (din_ready) begin
469 din_valid <= 0;
470 din_data <= 0;
471 state <= config_qspi || config_ddr ? 8 : 9;
472 end
473 end
474 8: begin
475 din_valid <= 1;
476 din_tag <= 0;
477 din_data <= config_cont ? 8'h A5 : 8'h FF;
478 if (din_ready) begin
479 din_rd <= 1;
480 din_data <= config_dummy;
481 din_valid <= 0;
482 state <= 9;
483 end
484 end
485 9: begin
486 din_valid <= 1;
487 din_tag <= 1;
488 if (din_ready) begin
489 din_valid <= 0;
490 state <= 10;
491 end
492 end
493 10: begin
494 din_valid <= 1;
495 din_data <= 8'h 00;
496 din_tag <= 2;
497 if (din_ready) begin
498 din_valid <= 0;
499 state <= 11;
500 end
501 end
502 11: begin
503 din_valid <= 1;
504 din_tag <= 3;
505 if (din_ready) begin
506 din_valid <= 0;
507 state <= 12;
508 end
509 end
510 12: begin
511 if (!rd_wait || valid) begin
512 din_valid <= 1;
513 din_tag <= 4;
514 if (din_ready) begin
515 din_valid <= 0;
516 state <= 9;
517 end
518 end
519 end
520 endcase
521
522 if (jump) begin
523 rd_inc <= 0;
524 rd_valid <= 0;
525 xfer_resetn <= 0;
526 if (config_cont) begin
527 state <= 5;
528 end else begin
529 state <= 4;
530 din_qspi <= 0;
531 din_ddr <= 0;
532 end
533 din_rd <= 0;
534 end
535 end
536 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400537endmodule
538
539module spimemio_xfer (
shalanfd13eb52020-08-21 16:48:07 +0200540 input clk, resetn, xfer_resetn,
Tim Edwardscd64af52020-08-07 11:11:58 -0400541
shalanfd13eb52020-08-21 16:48:07 +0200542 input din_valid,
543 output din_ready,
544 input [7:0] din_data,
545 input [3:0] din_tag,
546 input din_cont,
547 input din_dspi,
548 input din_qspi,
549 input din_ddr,
550 input din_rd,
Tim Edwardscd64af52020-08-07 11:11:58 -0400551
shalanfd13eb52020-08-21 16:48:07 +0200552 output dout_valid,
553 output [7:0] dout_data,
554 output [3:0] dout_tag,
Tim Edwardscd64af52020-08-07 11:11:58 -0400555
shalanfd13eb52020-08-21 16:48:07 +0200556 output reg flash_csb,
557 output reg flash_clk,
Tim Edwardscd64af52020-08-07 11:11:58 -0400558
shalanfd13eb52020-08-21 16:48:07 +0200559 output reg flash_io0_oe,
560 output reg flash_io1_oe,
561 output reg flash_io2_oe,
562 output reg flash_io3_oe,
Tim Edwardscd64af52020-08-07 11:11:58 -0400563
shalanfd13eb52020-08-21 16:48:07 +0200564 output reg flash_io0_do,
565 output reg flash_io1_do,
566 output reg flash_io2_do,
567 output reg flash_io3_do,
Tim Edwardscd64af52020-08-07 11:11:58 -0400568
shalanfd13eb52020-08-21 16:48:07 +0200569 input flash_io0_di,
570 input flash_io1_di,
571 input flash_io2_di,
572 input flash_io3_di
Tim Edwardscd64af52020-08-07 11:11:58 -0400573);
shalanfd13eb52020-08-21 16:48:07 +0200574 reg [7:0] obuffer;
575 reg [7:0] ibuffer;
Tim Edwardscd64af52020-08-07 11:11:58 -0400576
shalanfd13eb52020-08-21 16:48:07 +0200577 reg [3:0] count;
578 reg [3:0] dummy_count;
Tim Edwardscd64af52020-08-07 11:11:58 -0400579
shalanfd13eb52020-08-21 16:48:07 +0200580 reg xfer_cont;
581 reg xfer_dspi;
582 reg xfer_qspi;
583 reg xfer_ddr;
584 reg xfer_ddr_q;
585 reg xfer_rd;
586 reg [3:0] xfer_tag;
587 reg [3:0] xfer_tag_q;
Tim Edwardscd64af52020-08-07 11:11:58 -0400588
shalanfd13eb52020-08-21 16:48:07 +0200589 reg [7:0] next_obuffer;
590 reg [7:0] next_ibuffer;
591 reg [3:0] next_count;
Tim Edwardscd64af52020-08-07 11:11:58 -0400592
shalanfd13eb52020-08-21 16:48:07 +0200593 reg fetch;
594 reg next_fetch;
595 reg last_fetch;
Tim Edwardscd64af52020-08-07 11:11:58 -0400596
shalanfd13eb52020-08-21 16:48:07 +0200597 always @(posedge clk) begin
598 xfer_ddr_q <= xfer_ddr;
599 xfer_tag_q <= xfer_tag;
600 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400601
shalanfd13eb52020-08-21 16:48:07 +0200602 assign din_ready = din_valid && xfer_resetn && next_fetch;
Tim Edwardscd64af52020-08-07 11:11:58 -0400603
shalanfd13eb52020-08-21 16:48:07 +0200604 assign dout_valid = (xfer_ddr_q ? fetch && !last_fetch : next_fetch && !fetch) && xfer_resetn;
605 assign dout_data = ibuffer;
606 assign dout_tag = xfer_tag_q;
Tim Edwardscd64af52020-08-07 11:11:58 -0400607
shalanfd13eb52020-08-21 16:48:07 +0200608 always @* begin
609 flash_io0_oe = 0;
610 flash_io1_oe = 0;
611 flash_io2_oe = 0;
612 flash_io3_oe = 0;
Tim Edwardscd64af52020-08-07 11:11:58 -0400613
shalanfd13eb52020-08-21 16:48:07 +0200614 flash_io0_do = 0;
615 flash_io1_do = 0;
616 flash_io2_do = 0;
617 flash_io3_do = 0;
Tim Edwardscd64af52020-08-07 11:11:58 -0400618
shalanfd13eb52020-08-21 16:48:07 +0200619 next_obuffer = obuffer;
620 next_ibuffer = ibuffer;
621 next_count = count;
622 next_fetch = 0;
Tim Edwardscd64af52020-08-07 11:11:58 -0400623
shalanfd13eb52020-08-21 16:48:07 +0200624 if (dummy_count == 0) begin
625 casez ({xfer_ddr, xfer_qspi, xfer_dspi})
626 3'b 000: begin
627 flash_io0_oe = 1;
628 flash_io0_do = obuffer[7];
Tim Edwardscd64af52020-08-07 11:11:58 -0400629
shalanfd13eb52020-08-21 16:48:07 +0200630 if (flash_clk) begin
631 next_obuffer = {obuffer[6:0], 1'b 0};
632 next_count = count - |count;
633 end else begin
634 next_ibuffer = {ibuffer[6:0], flash_io1_di};
635 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400636
shalanfd13eb52020-08-21 16:48:07 +0200637 next_fetch = (next_count == 0);
638 end
639 3'b 01?: begin
640 flash_io0_oe = !xfer_rd;
641 flash_io1_oe = !xfer_rd;
642 flash_io2_oe = !xfer_rd;
643 flash_io3_oe = !xfer_rd;
Tim Edwardscd64af52020-08-07 11:11:58 -0400644
shalanfd13eb52020-08-21 16:48:07 +0200645 flash_io0_do = obuffer[4];
646 flash_io1_do = obuffer[5];
647 flash_io2_do = obuffer[6];
648 flash_io3_do = obuffer[7];
Tim Edwardscd64af52020-08-07 11:11:58 -0400649
shalanfd13eb52020-08-21 16:48:07 +0200650 if (flash_clk) begin
651 next_obuffer = {obuffer[3:0], 4'b 0000};
652 next_count = count - {|count, 2'b00};
653 end else begin
654 next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
655 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400656
shalanfd13eb52020-08-21 16:48:07 +0200657 next_fetch = (next_count == 0);
658 end
659 3'b 11?: begin
660 flash_io0_oe = !xfer_rd;
661 flash_io1_oe = !xfer_rd;
662 flash_io2_oe = !xfer_rd;
663 flash_io3_oe = !xfer_rd;
Tim Edwardscd64af52020-08-07 11:11:58 -0400664
shalanfd13eb52020-08-21 16:48:07 +0200665 flash_io0_do = obuffer[4];
666 flash_io1_do = obuffer[5];
667 flash_io2_do = obuffer[6];
668 flash_io3_do = obuffer[7];
Tim Edwardscd64af52020-08-07 11:11:58 -0400669
shalanfd13eb52020-08-21 16:48:07 +0200670 next_obuffer = {obuffer[3:0], 4'b 0000};
671 next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
672 next_count = count - {|count, 2'b00};
Tim Edwardscd64af52020-08-07 11:11:58 -0400673
shalanfd13eb52020-08-21 16:48:07 +0200674 next_fetch = (next_count == 0);
675 end
676 3'b ??1: begin
677 flash_io0_oe = !xfer_rd;
678 flash_io1_oe = !xfer_rd;
Tim Edwardscd64af52020-08-07 11:11:58 -0400679
shalanfd13eb52020-08-21 16:48:07 +0200680 flash_io0_do = obuffer[6];
681 flash_io1_do = obuffer[7];
Tim Edwardscd64af52020-08-07 11:11:58 -0400682
shalanfd13eb52020-08-21 16:48:07 +0200683 if (flash_clk) begin
684 next_obuffer = {obuffer[5:0], 2'b 00};
685 next_count = count - {|count, 1'b0};
686 end else begin
687 next_ibuffer = {ibuffer[5:0], flash_io1_di, flash_io0_di};
688 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400689
shalanfd13eb52020-08-21 16:48:07 +0200690 next_fetch = (next_count == 0);
691 end
692 endcase
693 end
694 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400695
shalanfd13eb52020-08-21 16:48:07 +0200696 always @(posedge clk) begin
697 if (!resetn || !xfer_resetn) begin
698 fetch <= 1;
699 last_fetch <= 1;
700 flash_csb <= 1;
701 flash_clk <= 0;
702 count <= 0;
703 dummy_count <= 0;
704 xfer_tag <= 0;
705 xfer_cont <= 0;
706 xfer_dspi <= 0;
707 xfer_qspi <= 0;
708 xfer_ddr <= 0;
709 xfer_rd <= 0;
710 end else begin
711 fetch <= next_fetch;
712 last_fetch <= xfer_ddr ? fetch : 1;
713 if (dummy_count) begin
714 flash_clk <= !flash_clk && !flash_csb;
715 dummy_count <= dummy_count - flash_clk;
716 end else
717 if (count) begin
718 flash_clk <= !flash_clk && !flash_csb;
719 obuffer <= next_obuffer;
720 ibuffer <= next_ibuffer;
721 count <= next_count;
722 end
723 if (din_valid && din_ready) begin
724 flash_csb <= 0;
725 flash_clk <= 0;
Tim Edwardscd64af52020-08-07 11:11:58 -0400726
shalanfd13eb52020-08-21 16:48:07 +0200727 count <= 8;
728 dummy_count <= din_rd ? din_data : 0;
729 obuffer <= din_data;
Tim Edwardscd64af52020-08-07 11:11:58 -0400730
shalanfd13eb52020-08-21 16:48:07 +0200731 xfer_tag <= din_tag;
732 xfer_cont <= din_cont;
733 xfer_dspi <= din_dspi;
734 xfer_qspi <= din_qspi;
735 xfer_ddr <= din_ddr;
736 xfer_rd <= din_rd;
737 end
738 end
739 end
Tim Edwardscd64af52020-08-07 11:11:58 -0400740endmodule
shalanfd13eb52020-08-21 16:48:07 +0200741