Add PicoSoC spimem Dual I/O support
This commit is contained in:
parent
c00811e8e4
commit
c06ba38113
|
@ -55,8 +55,8 @@ GPIO pins mapped to the 32 bit word at address 0x03000000.
|
|||
| 30:23 | Reserved (read 0) |
|
||||
| 22 | DDR Enable bit (reset=0) |
|
||||
| 21 | QSPI Enable bit (reset=0) |
|
||||
| 20 | XIP Enable bit (reset=0) |
|
||||
| 19:16 | Number of QSPI dummy cycles (reset=0) |
|
||||
| 20 | CRM Enable bit (reset=0) |
|
||||
| 19:16 | Read latency (dummy) cycles (reset=0) |
|
||||
| 15:12 | Reserved (read 0) |
|
||||
| 11:8 | IO Output enable bits in bit bang mode |
|
||||
| 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 |
|
||||
| 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 | 1 | EBh Quad I/O Read | FFh |
|
||||
| 1 | 0 | 1 | EBh Quad I/O Read | A5h / FFh |
|
||||
| 0 | 0 | 1 | BBh Dual I/O Read | 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 |
|
||||
| 1 | 1 | 1 | EDh DDR Quad I/O Read | A5h / FFh |
|
||||
| 1 | 1 | 1 | EDh DDR Quad I/O Read | A5h |
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
// updates output signals 1ns after the SPI clock edge.
|
||||
//
|
||||
// Supported commands:
|
||||
// AB, B9, FF, 03, EB, ED
|
||||
// AB, B9, FF, 03, BB, EB, ED
|
||||
//
|
||||
// Well written SPI flash data sheets:
|
||||
// Cypress S25FL064L http://www.cypress.com/file/316661/download
|
||||
|
@ -60,10 +60,12 @@ module spiflash (
|
|||
reg powered_up = 0;
|
||||
|
||||
localparam [3:0] mode_spi = 1;
|
||||
localparam [3:0] mode_qspi_rd = 2;
|
||||
localparam [3:0] mode_qspi_wr = 3;
|
||||
localparam [3:0] mode_qspi_ddr_rd = 4;
|
||||
localparam [3:0] mode_qspi_ddr_wr = 5;
|
||||
localparam [3:0] mode_dspi_rd = 2;
|
||||
localparam [3:0] mode_dspi_wr = 3;
|
||||
localparam [3:0] mode_qspi_rd = 4;
|
||||
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] next_mode = 0;
|
||||
|
@ -133,6 +135,31 @@ module spiflash (
|
|||
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 (bytecount == 1)
|
||||
mode = mode_qspi_rd;
|
||||
|
@ -269,6 +296,20 @@ module spiflash (
|
|||
io3_oe = 0;
|
||||
io1_dout = buffer[7];
|
||||
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
|
||||
io0_oe = 0;
|
||||
io1_oe = 0;
|
||||
|
@ -332,6 +373,15 @@ module spiflash (
|
|||
spi_action;
|
||||
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
|
||||
buffer = {buffer, io3, io2, io1, io0};
|
||||
bitcount = bitcount + 4;
|
||||
|
|
|
@ -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_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 (
|
||||
.clk (clk ),
|
||||
.resetn (xfer_resetn ),
|
||||
|
@ -176,8 +179,9 @@ module spimemio (
|
|||
.din_data (din_data ),
|
||||
.din_tag (din_tag ),
|
||||
.din_cont (din_cont ),
|
||||
.din_dspi (xfer_dspi ),
|
||||
.din_qspi (din_qspi ),
|
||||
.din_ddr (din_ddr ),
|
||||
.din_ddr (xfer_ddr ),
|
||||
.din_rd (din_rd ),
|
||||
.dout_valid (dout_valid ),
|
||||
.dout_data (dout_data ),
|
||||
|
@ -266,6 +270,7 @@ module spimemio (
|
|||
case ({config_ddr, config_qspi})
|
||||
2'b11: din_data <= 8'h ED;
|
||||
2'b01: din_data <= 8'h EB;
|
||||
2'b10: din_data <= 8'h BB;
|
||||
2'b00: din_data <= 8'h 03;
|
||||
endcase
|
||||
if (din_ready) begin
|
||||
|
@ -302,7 +307,7 @@ module spimemio (
|
|||
if (din_ready) begin
|
||||
din_valid <= 0;
|
||||
din_data <= 0;
|
||||
state <= config_qspi ? 8 : 9;
|
||||
state <= config_qspi || config_ddr ? 8 : 9;
|
||||
end
|
||||
end
|
||||
8: begin
|
||||
|
@ -378,6 +383,7 @@ module spimemio_xfer (
|
|||
input [7:0] din_data,
|
||||
input [3:0] din_tag,
|
||||
input din_cont,
|
||||
input din_dspi,
|
||||
input din_qspi,
|
||||
input din_ddr,
|
||||
input din_rd,
|
||||
|
@ -411,6 +417,7 @@ module spimemio_xfer (
|
|||
reg [3:0] dummy_count;
|
||||
|
||||
reg xfer_cont;
|
||||
reg xfer_dspi;
|
||||
reg xfer_qspi;
|
||||
reg xfer_ddr;
|
||||
reg xfer_ddr_q;
|
||||
|
@ -454,8 +461,8 @@ module spimemio_xfer (
|
|||
next_fetch = 0;
|
||||
|
||||
if (dummy_count == 0) begin
|
||||
case ({xfer_ddr, xfer_qspi})
|
||||
2'b 00: begin
|
||||
casez ({xfer_ddr, xfer_qspi, xfer_dspi})
|
||||
3'b 000: begin
|
||||
flash_io0_oe = 1;
|
||||
flash_io0_do = obuffer[7];
|
||||
|
||||
|
@ -468,7 +475,7 @@ module spimemio_xfer (
|
|||
|
||||
next_fetch = (next_count == 0);
|
||||
end
|
||||
2'b 01: begin
|
||||
3'b 01?: begin
|
||||
flash_io0_oe = !xfer_rd;
|
||||
flash_io1_oe = !xfer_rd;
|
||||
flash_io2_oe = !xfer_rd;
|
||||
|
@ -488,7 +495,7 @@ module spimemio_xfer (
|
|||
|
||||
next_fetch = (next_count == 0);
|
||||
end
|
||||
2'b 11: begin
|
||||
3'b 11?: begin
|
||||
flash_io0_oe = !xfer_rd;
|
||||
flash_io1_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_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);
|
||||
end
|
||||
endcase
|
||||
|
@ -519,6 +542,7 @@ module spimemio_xfer (
|
|||
dummy_count <= 0;
|
||||
xfer_tag <= 0;
|
||||
xfer_cont <= 0;
|
||||
xfer_dspi <= 0;
|
||||
xfer_qspi <= 0;
|
||||
xfer_ddr <= 0;
|
||||
xfer_rd <= 0;
|
||||
|
@ -545,6 +569,7 @@ module spimemio_xfer (
|
|||
|
||||
xfer_tag <= din_tag;
|
||||
xfer_cont <= din_cont;
|
||||
xfer_dspi <= din_dspi;
|
||||
xfer_qspi <= din_qspi;
|
||||
xfer_ddr <= din_ddr;
|
||||
xfer_rd <= din_rd;
|
||||
|
|
Loading…
Reference in New Issue