aboutsummaryrefslogtreecommitdiffstats
path: root/picosoc/spimemio.v
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2017-08-11 15:57:42 +0200
committerClifford Wolf <clifford@clifford.at>2017-08-11 15:57:42 +0200
commit78f2f5efd27765820849df4cfca2b9adc7bcb9b5 (patch)
tree15a3da231698b09f2c7a15b26d3f81a0289f6925 /picosoc/spimemio.v
parent53b175d0fb036e114ce28c38831d7756afb834f5 (diff)
downloadpicorv32-78f2f5efd27765820849df4cfca2b9adc7bcb9b5.tar.gz
picorv32-78f2f5efd27765820849df4cfca2b9adc7bcb9b5.zip
Add support for QSPI DDR mode, Add SPI MEMIO config reg
Diffstat (limited to 'picosoc/spimemio.v')
-rw-r--r--picosoc/spimemio.v160
1 files changed, 127 insertions, 33 deletions
diff --git a/picosoc/spimemio.v b/picosoc/spimemio.v
index 91bbb2f..c7d8cb6 100644
--- a/picosoc/spimemio.v
+++ b/picosoc/spimemio.v
@@ -41,12 +41,17 @@ module spimemio (
input flash_io0_di,
input flash_io1_di,
input flash_io2_di,
- input flash_io3_di
+ input flash_io3_di,
+
+ input [3:0] cfgreg_we,
+ input [31:0] cfgreg_di,
+ output [31:0] cfgreg_do
);
reg xfer_resetn;
reg din_valid;
wire din_ready;
reg [7:0] din_data;
+ reg [3:0] din_tag;
reg din_cont;
reg din_qspi;
reg din_ddr;
@@ -54,9 +59,9 @@ module spimemio (
wire dout_valid;
wire [7:0] dout_data;
+ wire [3:0] dout_tag;
reg [23:0] buffer;
- reg [3:0] buffer_wen;
reg [23:0] rd_addr;
reg rd_valid;
@@ -66,10 +71,84 @@ module spimemio (
assign ready = valid && (addr == rd_addr) && rd_valid;
wire jump = valid && !ready && (addr != rd_addr+4) && rd_valid;
- reg config_ddr = 0;
- reg config_qspi = 0;
- reg config_cont = 0;
- reg [3:0] config_dummy = 1;
+ reg softreset;
+
+ reg config_en; // cfgreg[31]
+ reg [3:0] config_oe; // cfgreg[19:16]
+ reg config_csb; // cfgreg[13]
+ reg config_clk; // cfgref[12]
+ reg [3:0] config_do; // cfgreg[11:8]
+ reg config_ddr; // cfgreg[6]
+ reg config_qspi; // cfgreg[5]
+ reg config_cont; // cfgreg[4]
+ reg [3:0] config_dummy; // cfgreg[3:0]
+
+ assign cfgreg_do[31] = config_en;
+ assign cfgreg_do[30:20] = 0;
+ assign cfgreg_do[19:16] = {flash_io3_oe, flash_io2_oe, flash_io1_oe, flash_io0_oe};
+ assign cfgreg_do[15:14] = 0;
+ assign cfgreg_do[13] = flash_csb;
+ assign cfgreg_do[12] = flash_clk;
+ assign cfgreg_do[11:8] = {flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
+ assign cfgreg_do[7] = 0;
+ assign cfgreg_do[6] = config_ddr;
+ assign cfgreg_do[5] = config_qspi;
+ assign cfgreg_do[4] = config_cont;
+ assign cfgreg_do[3:0] = config_dummy;
+
+ always @(posedge clk) begin
+ softreset <= !config_en || cfgreg_we;
+ if (!resetn) begin
+ softreset <= 1;
+ config_en <= 1;
+ config_csb <= 0;
+ config_clk <= 0;
+ config_oe <= 0;
+ config_do <= 0;
+ config_ddr <= 0;
+ config_qspi <= 0;
+ config_cont <= 0;
+ config_dummy <= 0;
+ end else begin
+ if (cfgreg_we[0]) begin
+ config_ddr <= cfgreg_di[6];
+ config_qspi <= cfgreg_di[5];
+ config_cont <= cfgreg_di[4];
+ config_dummy <= cfgreg_di[3:0];
+ end
+ if (cfgreg_we[1]) begin
+ config_csb <= cfgreg_di[13];
+ config_clk <= cfgreg_di[12];
+ config_do <= cfgreg_di[11:8];
+ end
+ if (cfgreg_we[2]) begin
+ config_oe <= cfgreg_di[19:16];
+ end
+ if (cfgreg_we[3]) begin
+ config_en <= cfgreg_di[31];
+ end
+ end
+ end
+
+ wire xfer_io0_oe;
+ wire xfer_io1_oe;
+ wire xfer_io2_oe;
+ wire xfer_io3_oe;
+
+ wire xfer_io0_do;
+ wire xfer_io1_do;
+ wire xfer_io2_do;
+ wire xfer_io3_do;
+
+ assign flash_io0_oe = config_en ? xfer_io0_oe : config_oe[0];
+ assign flash_io1_oe = config_en ? xfer_io1_oe : config_oe[1];
+ assign flash_io2_oe = config_en ? xfer_io2_oe : config_oe[2];
+ assign flash_io3_oe = config_en ? xfer_io3_oe : config_oe[3];
+
+ assign flash_io0_do = config_en ? xfer_io0_do : config_do[0];
+ assign flash_io1_do = config_en ? xfer_io1_do : config_do[1];
+ assign flash_io2_do = config_en ? xfer_io2_do : config_do[2];
+ assign flash_io3_do = config_en ? xfer_io3_do : config_do[3];
spimemio_xfer xfer (
.clk (clk ),
@@ -77,22 +156,24 @@ module spimemio (
.din_valid (din_valid ),
.din_ready (din_ready ),
.din_data (din_data ),
+ .din_tag (din_tag ),
.din_cont (din_cont ),
.din_qspi (din_qspi ),
.din_ddr (din_ddr ),
.din_rd (din_rd ),
.dout_valid (dout_valid ),
.dout_data (dout_data ),
+ .dout_tag (dout_tag ),
.flash_csb (flash_csb ),
.flash_clk (flash_clk ),
- .flash_io0_oe (flash_io0_oe),
- .flash_io1_oe (flash_io1_oe),
- .flash_io2_oe (flash_io2_oe),
- .flash_io3_oe (flash_io3_oe),
- .flash_io0_do (flash_io0_do),
- .flash_io1_do (flash_io1_do),
- .flash_io2_do (flash_io2_do),
- .flash_io3_do (flash_io3_do),
+ .flash_io0_oe (xfer_io0_oe),
+ .flash_io1_oe (xfer_io1_oe),
+ .flash_io2_oe (xfer_io2_oe),
+ .flash_io3_oe (xfer_io3_oe),
+ .flash_io0_do (xfer_io0_do),
+ .flash_io1_do (xfer_io1_do),
+ .flash_io2_do (xfer_io2_do),
+ .flash_io3_do (xfer_io3_do),
.flash_io0_di (flash_io0_di),
.flash_io1_di (flash_io1_di),
.flash_io2_di (flash_io2_di),
@@ -105,20 +186,20 @@ module spimemio (
xfer_resetn <= 1;
din_valid <= 0;
- if (!resetn) begin
+ if (!resetn || softreset) begin
state <= 0;
xfer_resetn <= 0;
rd_valid <= 0;
- buffer_wen <= 0;
+ din_tag <= 0;
din_cont <= 0;
din_qspi <= 0;
din_ddr <= 0;
din_rd <= 0;
end else begin
- if (dout_valid && buffer_wen[0]) buffer[ 7: 0] <= dout_data;
- if (dout_valid && buffer_wen[1]) buffer[15: 8] <= dout_data;
- if (dout_valid && buffer_wen[2]) buffer[23:16] <= dout_data;
- if (dout_valid && buffer_wen[3]) begin
+ if (dout_valid && dout_tag == 1) buffer[ 7: 0] <= dout_data;
+ if (dout_valid && dout_tag == 2) buffer[15: 8] <= dout_data;
+ if (dout_valid && dout_tag == 3) buffer[23:16] <= dout_data;
+ if (dout_valid && dout_tag == 4) begin
rdata <= {dout_data, buffer};
rd_addr <= rd_inc ? rd_addr + 4 : addr;
rd_valid <= 1;
@@ -126,10 +207,6 @@ module spimemio (
rd_inc <= 1;
end
- if (dout_valid && buffer_wen) begin
- buffer_wen <= 0;
- end
-
if (valid)
rd_wait <= 0;
@@ -137,6 +214,7 @@ module spimemio (
0: begin
din_valid <= 1;
din_data <= 8'h ff;
+ din_tag <= 0;
if (din_ready) begin
din_valid <= 0;
state <= 1;
@@ -151,6 +229,7 @@ module spimemio (
2: begin
din_valid <= 1;
din_data <= 8'h ab;
+ din_tag <= 0;
if (din_ready) begin
din_valid <= 0;
state <= 3;
@@ -165,6 +244,7 @@ module spimemio (
4: begin
rd_inc <= 0;
din_valid <= 1;
+ din_tag <= 0;
case ({config_ddr, config_qspi})
2'b11: din_data <= 8'h ED;
2'b01: din_data <= 8'h EB;
@@ -178,6 +258,7 @@ module spimemio (
5: begin
if (valid && !ready) begin
din_valid <= 1;
+ din_tag <= 0;
din_data <= addr[23:16];
din_qspi <= config_qspi;
din_ddr <= config_ddr;
@@ -189,6 +270,7 @@ module spimemio (
end
6: begin
din_valid <= 1;
+ din_tag <= 0;
din_data <= addr[15:8];
if (din_ready) begin
din_valid <= 0;
@@ -197,6 +279,7 @@ module spimemio (
end
7: begin
din_valid <= 1;
+ din_tag <= 0;
din_data <= addr[7:0];
if (din_ready) begin
din_valid <= 0;
@@ -206,6 +289,7 @@ module spimemio (
end
8: begin
din_valid <= 1;
+ din_tag <= 0;
din_data <= config_cont ? 8'h A5 : 8'h FF;
if (din_ready) begin
din_rd <= 1;
@@ -216,8 +300,8 @@ module spimemio (
end
9: begin
din_valid <= 1;
+ din_tag <= 1;
if (din_ready) begin
- buffer_wen <= 4'b 0001;
din_valid <= 0;
state <= 10;
end
@@ -225,16 +309,16 @@ module spimemio (
10: begin
din_valid <= 1;
din_data <= 8'h 00;
+ din_tag <= 2;
if (din_ready) begin
- buffer_wen <= 4'b 0010;
din_valid <= 0;
state <= 11;
end
end
11: begin
din_valid <= 1;
+ din_tag <= 3;
if (din_ready) begin
- buffer_wen <= 4'b 0100;
din_valid <= 0;
state <= 12;
end
@@ -242,8 +326,8 @@ module spimemio (
12: begin
if (!rd_wait || valid) begin
din_valid <= 1;
+ din_tag <= 4;
if (din_ready) begin
- buffer_wen <= 4'b 1000;
din_valid <= 0;
state <= 9;
end
@@ -255,7 +339,6 @@ module spimemio (
rd_inc <= 0;
rd_valid <= 0;
xfer_resetn <= 0;
- buffer_wen <= 0;
if (config_cont) begin
state <= 5;
end else begin
@@ -275,6 +358,7 @@ module spimemio_xfer (
input din_valid,
output din_ready,
input [7:0] din_data,
+ input [3:0] din_tag,
input din_cont,
input din_qspi,
input din_ddr,
@@ -282,6 +366,7 @@ module spimemio_xfer (
output dout_valid,
output [7:0] dout_data,
+ output [3:0] dout_tag,
output reg flash_csb,
output reg flash_clk,
@@ -310,7 +395,10 @@ module spimemio_xfer (
reg xfer_cont;
reg xfer_qspi;
reg xfer_ddr;
+ reg xfer_ddr_q;
reg xfer_rd;
+ reg [3:0] xfer_tag;
+ reg [3:0] xfer_tag_q;
reg [7:0] next_obuffer;
reg [7:0] next_ibuffer;
@@ -320,10 +408,16 @@ module spimemio_xfer (
reg next_fetch;
reg last_fetch;
+ always @(posedge clk) begin
+ xfer_ddr_q <= xfer_ddr;
+ xfer_tag_q <= xfer_tag;
+ end
+
assign din_ready = din_valid && resetn && next_fetch;
- assign dout_valid = xfer_ddr ? fetch && !last_fetch : next_fetch && !fetch;
+ assign dout_valid = xfer_ddr_q ? fetch && !last_fetch : next_fetch && !fetch;
assign dout_data = ibuffer;
+ assign dout_tag = xfer_tag_q;
always @* begin
flash_io0_oe = 0;
@@ -405,6 +499,7 @@ module spimemio_xfer (
flash_clk <= 0;
count <= 0;
dummy_count <= 0;
+ xfer_tag <= 0;
xfer_cont <= 0;
xfer_qspi <= 0;
xfer_ddr <= 0;
@@ -426,12 +521,11 @@ module spimemio_xfer (
flash_csb <= 0;
flash_clk <= 0;
- obuffer <= din_data;
- // ibuffer <= 8'h 00;
-
count <= 8;
dummy_count <= din_rd ? din_data : 0;
+ obuffer <= din_data;
+ xfer_tag <= din_tag;
xfer_cont <= din_cont;
xfer_qspi <= din_qspi;
xfer_ddr <= din_ddr;