Add PicoSoC spimem Dual I/O support

This commit is contained in:
Clifford Wolf 2017-09-21 15:50:50 +02:00
parent c00811e8e4
commit c06ba38113
3 changed files with 98 additions and 21 deletions

View File

@ -55,8 +55,8 @@ GPIO pins mapped to the 32 bit word at address 0x03000000.
| 30:23 | Reserved (read 0) | | 30:23 | Reserved (read 0) |
| 22 | DDR Enable bit (reset=0) | | 22 | DDR Enable bit (reset=0) |
| 21 | QSPI Enable bit (reset=0) | | 21 | QSPI Enable bit (reset=0) |
| 20 | XIP Enable bit (reset=0) | | 20 | CRM Enable bit (reset=0) |
| 19:16 | Number of QSPI dummy cycles (reset=0) | | 19:16 | Read latency (dummy) cycles (reset=0) |
| 15:12 | Reserved (read 0) | | 15:12 | Reserved (read 0) |
| 11:8 | IO Output enable bits in bit bang mode | | 11:8 | IO Output enable bits in bit bang mode |
| 7:6 | Reserved (read 0) | | 7:6 | Reserved (read 0) |
@ -64,13 +64,15 @@ GPIO pins mapped to the 32 bit word at address 0x03000000.
| 4 | Serial clock line in bit bang mode | | 4 | Serial clock line in bit bang mode |
| 3:0 | IO data bits in bit bang mode | | 3:0 | IO data bits in bit bang mode |
The following settings for XIP/DDR/QSPI modes are valid: The following settings for CRM/DDR/QSPI modes are valid:
| XIP | DDR | QSPI | Read Command Byte | Mode Byte | | CRM | QSPI | DDR | Read Command Byte | Mode Byte |
| :-: | :-: | :--: | :-------------------- | :-------: | | :-: | :--: | :-: | :-------------------- | :-------: |
| 0 | 0 | 0 | 03h Read | N/A | | 0 | 0 | 0 | 03h Read | N/A |
| 0 | 0 | 1 | EBh Quad I/O Read | FFh | | 0 | 0 | 1 | BBh Dual I/O Read | FFh |
| 1 | 0 | 1 | EBh Quad I/O Read | A5h / FFh | | 1 | 0 | 1 | BBh Dual I/O Read | A5h |
| 0 | 1 | 0 | EBh Quad I/O Read | FFh |
| 1 | 1 | 0 | EBh Quad I/O Read | A5h |
| 0 | 1 | 1 | EDh DDR Quad I/O Read | FFh | | 0 | 1 | 1 | EDh DDR Quad I/O Read | FFh |
| 1 | 1 | 1 | EDh DDR Quad I/O Read | A5h / FFh | | 1 | 1 | 1 | EDh DDR Quad I/O Read | A5h |

View File

@ -26,7 +26,7 @@
// updates output signals 1ns after the SPI clock edge. // updates output signals 1ns after the SPI clock edge.
// //
// Supported commands: // Supported commands:
// AB, B9, FF, 03, EB, ED // AB, B9, FF, 03, BB, EB, ED
// //
// Well written SPI flash data sheets: // Well written SPI flash data sheets:
// Cypress S25FL064L http://www.cypress.com/file/316661/download // Cypress S25FL064L http://www.cypress.com/file/316661/download
@ -60,10 +60,12 @@ module spiflash (
reg powered_up = 0; reg powered_up = 0;
localparam [3:0] mode_spi = 1; localparam [3:0] mode_spi = 1;
localparam [3:0] mode_qspi_rd = 2; localparam [3:0] mode_dspi_rd = 2;
localparam [3:0] mode_qspi_wr = 3; localparam [3:0] mode_dspi_wr = 3;
localparam [3:0] mode_qspi_ddr_rd = 4; localparam [3:0] mode_qspi_rd = 4;
localparam [3:0] mode_qspi_ddr_wr = 5; localparam [3:0] mode_qspi_wr = 5;
localparam [3:0] mode_qspi_ddr_rd = 6;
localparam [3:0] mode_qspi_ddr_wr = 7;
reg [3:0] mode = 0; reg [3:0] mode = 0;
reg [3:0] next_mode = 0; reg [3:0] next_mode = 0;
@ -133,6 +135,31 @@ module spiflash (
end end
end end
if (powered_up && spi_cmd == 'h bb) begin
if (bytecount == 1)
mode = mode_dspi_rd;
if (bytecount == 2)
spi_addr[23:16] = buffer;
if (bytecount == 3)
spi_addr[15:8] = buffer;
if (bytecount == 4)
spi_addr[7:0] = buffer;
if (bytecount == 5) begin
xip_cmd = (buffer == 8'h a5) ? spi_cmd : 8'h 00;
mode = mode_dspi_wr;
dummycount = latency;
end
if (bytecount >= 5) begin
buffer = memory[spi_addr];
spi_addr = spi_addr + 1;
end
end
if (powered_up && spi_cmd == 'h eb) begin if (powered_up && spi_cmd == 'h eb) begin
if (bytecount == 1) if (bytecount == 1)
mode = mode_qspi_rd; mode = mode_qspi_rd;
@ -269,6 +296,20 @@ module spiflash (
io3_oe = 0; io3_oe = 0;
io1_dout = buffer[7]; io1_dout = buffer[7];
end end
mode_dspi_rd: begin
io0_oe = 0;
io1_oe = 0;
io2_oe = 0;
io3_oe = 0;
end
mode_dspi_wr: begin
io0_oe = 1;
io1_oe = 1;
io2_oe = 0;
io3_oe = 0;
io0_dout = buffer[6];
io1_dout = buffer[7];
end
mode_qspi_rd: begin mode_qspi_rd: begin
io0_oe = 0; io0_oe = 0;
io1_oe = 0; io1_oe = 0;
@ -332,6 +373,15 @@ module spiflash (
spi_action; spi_action;
end end
end end
mode_dspi_rd, mode_dspi_wr: begin
buffer = {buffer, io1, io0};
bitcount = bitcount + 2;
if (bitcount == 8) begin
bitcount = 0;
bytecount = bytecount + 1;
spi_action;
end
end
mode_qspi_rd, mode_qspi_wr: begin mode_qspi_rd, mode_qspi_wr: begin
buffer = {buffer, io3, io2, io1, io0}; buffer = {buffer, io3, io2, io1, io0};
bitcount = bitcount + 4; bitcount = bitcount + 4;

View File

@ -168,6 +168,9 @@ module spimemio (
assign flash_io2_do = config_en ? (config_ddr ? xfer_io2_90 : xfer_io2_do) : config_do[2]; assign flash_io2_do = config_en ? (config_ddr ? xfer_io2_90 : xfer_io2_do) : config_do[2];
assign flash_io3_do = config_en ? (config_ddr ? xfer_io3_90 : xfer_io3_do) : config_do[3]; assign flash_io3_do = config_en ? (config_ddr ? xfer_io3_90 : xfer_io3_do) : config_do[3];
wire xfer_dspi = din_ddr && !din_qspi;
wire xfer_ddr = din_ddr && din_qspi;
spimemio_xfer xfer ( spimemio_xfer xfer (
.clk (clk ), .clk (clk ),
.resetn (xfer_resetn ), .resetn (xfer_resetn ),
@ -176,8 +179,9 @@ module spimemio (
.din_data (din_data ), .din_data (din_data ),
.din_tag (din_tag ), .din_tag (din_tag ),
.din_cont (din_cont ), .din_cont (din_cont ),
.din_dspi (xfer_dspi ),
.din_qspi (din_qspi ), .din_qspi (din_qspi ),
.din_ddr (din_ddr ), .din_ddr (xfer_ddr ),
.din_rd (din_rd ), .din_rd (din_rd ),
.dout_valid (dout_valid ), .dout_valid (dout_valid ),
.dout_data (dout_data ), .dout_data (dout_data ),
@ -266,6 +270,7 @@ module spimemio (
case ({config_ddr, config_qspi}) case ({config_ddr, config_qspi})
2'b11: din_data <= 8'h ED; 2'b11: din_data <= 8'h ED;
2'b01: din_data <= 8'h EB; 2'b01: din_data <= 8'h EB;
2'b10: din_data <= 8'h BB;
2'b00: din_data <= 8'h 03; 2'b00: din_data <= 8'h 03;
endcase endcase
if (din_ready) begin if (din_ready) begin
@ -302,7 +307,7 @@ module spimemio (
if (din_ready) begin if (din_ready) begin
din_valid <= 0; din_valid <= 0;
din_data <= 0; din_data <= 0;
state <= config_qspi ? 8 : 9; state <= config_qspi || config_ddr ? 8 : 9;
end end
end end
8: begin 8: begin
@ -378,6 +383,7 @@ module spimemio_xfer (
input [7:0] din_data, input [7:0] din_data,
input [3:0] din_tag, input [3:0] din_tag,
input din_cont, input din_cont,
input din_dspi,
input din_qspi, input din_qspi,
input din_ddr, input din_ddr,
input din_rd, input din_rd,
@ -411,6 +417,7 @@ module spimemio_xfer (
reg [3:0] dummy_count; reg [3:0] dummy_count;
reg xfer_cont; reg xfer_cont;
reg xfer_dspi;
reg xfer_qspi; reg xfer_qspi;
reg xfer_ddr; reg xfer_ddr;
reg xfer_ddr_q; reg xfer_ddr_q;
@ -454,8 +461,8 @@ module spimemio_xfer (
next_fetch = 0; next_fetch = 0;
if (dummy_count == 0) begin if (dummy_count == 0) begin
case ({xfer_ddr, xfer_qspi}) casez ({xfer_ddr, xfer_qspi, xfer_dspi})
2'b 00: begin 3'b 000: begin
flash_io0_oe = 1; flash_io0_oe = 1;
flash_io0_do = obuffer[7]; flash_io0_do = obuffer[7];
@ -468,7 +475,7 @@ module spimemio_xfer (
next_fetch = (next_count == 0); next_fetch = (next_count == 0);
end end
2'b 01: begin 3'b 01?: begin
flash_io0_oe = !xfer_rd; flash_io0_oe = !xfer_rd;
flash_io1_oe = !xfer_rd; flash_io1_oe = !xfer_rd;
flash_io2_oe = !xfer_rd; flash_io2_oe = !xfer_rd;
@ -488,7 +495,7 @@ module spimemio_xfer (
next_fetch = (next_count == 0); next_fetch = (next_count == 0);
end end
2'b 11: begin 3'b 11?: begin
flash_io0_oe = !xfer_rd; flash_io0_oe = !xfer_rd;
flash_io1_oe = !xfer_rd; flash_io1_oe = !xfer_rd;
flash_io2_oe = !xfer_rd; flash_io2_oe = !xfer_rd;
@ -503,6 +510,22 @@ module spimemio_xfer (
next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di}; next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
next_count = count - {|count, 2'b00}; next_count = count - {|count, 2'b00};
next_fetch = (next_count == 0);
end
3'b ??1: begin
flash_io0_oe = !xfer_rd;
flash_io1_oe = !xfer_rd;
flash_io0_do = obuffer[6];
flash_io1_do = obuffer[7];
if (flash_clk) begin
next_obuffer = {obuffer[5:0], 2'b 00};
next_count = count - {|count, 1'b0};
end else begin
next_ibuffer = {ibuffer[5:0], flash_io1_di, flash_io0_di};
end
next_fetch = (next_count == 0); next_fetch = (next_count == 0);
end end
endcase endcase
@ -519,6 +542,7 @@ module spimemio_xfer (
dummy_count <= 0; dummy_count <= 0;
xfer_tag <= 0; xfer_tag <= 0;
xfer_cont <= 0; xfer_cont <= 0;
xfer_dspi <= 0;
xfer_qspi <= 0; xfer_qspi <= 0;
xfer_ddr <= 0; xfer_ddr <= 0;
xfer_rd <= 0; xfer_rd <= 0;
@ -545,6 +569,7 @@ module spimemio_xfer (
xfer_tag <= din_tag; xfer_tag <= din_tag;
xfer_cont <= din_cont; xfer_cont <= din_cont;
xfer_dspi <= din_dspi;
xfer_qspi <= din_qspi; xfer_qspi <= din_qspi;
xfer_ddr <= din_ddr; xfer_ddr <= din_ddr;
xfer_rd <= din_rd; xfer_rd <= din_rd;