diff options
author | Clifford Wolf <clifford@clifford.at> | 2017-08-11 15:57:42 +0200 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2017-08-11 15:57:42 +0200 |
commit | 78f2f5efd27765820849df4cfca2b9adc7bcb9b5 (patch) | |
tree | 15a3da231698b09f2c7a15b26d3f81a0289f6925 /picosoc/spimemio.v | |
parent | 53b175d0fb036e114ce28c38831d7756afb834f5 (diff) | |
download | picorv32-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.v | 160 |
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; |