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) |
|
| 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 | 1 | EDh DDR Quad I/O Read | FFh |
|
| 0 | 1 | 0 | EBh Quad I/O Read | FFh |
|
||||||
| 1 | 1 | 1 | EDh DDR Quad I/O Read | A5h / 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 |
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue