aboutsummaryrefslogtreecommitdiffstats
path: root/picosoc
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2017-09-21 15:50:50 +0200
committerClifford Wolf <clifford@clifford.at>2017-09-21 15:50:50 +0200
commitc06ba38113b98b4996aed6d523667444a5d83bf6 (patch)
tree4907c5954f6b9da665a07574c2ac512f8360f689 /picosoc
parentc00811e8e45d535f6a260b2e78fa7f68df3d91f5 (diff)
downloadpicorv32-c06ba38113b98b4996aed6d523667444a5d83bf6.tar.gz
picorv32-c06ba38113b98b4996aed6d523667444a5d83bf6.zip
Add PicoSoC spimem Dual I/O support
Diffstat (limited to 'picosoc')
-rw-r--r--picosoc/README.md24
-rw-r--r--picosoc/spiflash.v60
-rw-r--r--picosoc/spimemio.v37
3 files changed, 99 insertions, 22 deletions
diff --git a/picosoc/README.md b/picosoc/README.md
index c112835..aec6142 100644
--- a/picosoc/README.md
+++ b/picosoc/README.md
@@ -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:
-
-| XIP | DDR | QSPI | 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 | 1 | 1 | EDh DDR Quad I/O Read | FFh |
-| 1 | 1 | 1 | EDh DDR Quad I/O Read | A5h / FFh |
+The following settings for CRM/DDR/QSPI modes are valid:
+
+| CRM | QSPI | DDR | Read Command Byte | Mode Byte |
+| :-: | :--: | :-: | :-------------------- | :-------: |
+| 0 | 0 | 0 | 03h Read | N/A |
+| 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 |
diff --git a/picosoc/spiflash.v b/picosoc/spiflash.v
index 18cd68d..63d21dc 100644
--- a/picosoc/spiflash.v
+++ b/picosoc/spiflash.v
@@ -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;
diff --git a/picosoc/spimemio.v b/picosoc/spimemio.v
index 311edcd..0bbf532 100644
--- a/picosoc/spimemio.v
+++ b/picosoc/spimemio.v
@@ -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;
@@ -505,6 +512,22 @@ module spimemio_xfer (
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
end
end
@@ -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;