Add spimemio QSPI support

This commit is contained in:
Clifford Wolf 2017-08-11 15:02:31 +02:00
parent 89ad9fc85a
commit 53b175d0fb
1 changed files with 133 additions and 41 deletions

View File

@ -66,6 +66,11 @@ 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;
spimemio_xfer xfer (
.clk (clk ),
.resetn (xfer_resetn ),
@ -99,7 +104,6 @@ module spimemio (
always @(posedge clk) begin
xfer_resetn <= 1;
din_valid <= 0;
din_data <= 8'h 00;
if (!resetn) begin
state <= 0;
@ -133,8 +137,10 @@ module spimemio (
0: begin
din_valid <= 1;
din_data <= 8'h ff;
if (din_ready)
if (din_ready) begin
din_valid <= 0;
state <= 1;
end
end
1: begin
if (dout_valid) begin
@ -145,8 +151,10 @@ module spimemio (
2: begin
din_valid <= 1;
din_data <= 8'h ab;
if (din_ready)
if (din_ready) begin
din_valid <= 0;
state <= 3;
end
end
3: begin
if (dout_valid) begin
@ -157,43 +165,60 @@ module spimemio (
4: begin
rd_inc <= 0;
din_valid <= 1;
din_data <= 8'h 03;
if (din_ready)
case ({config_ddr, config_qspi})
2'b11: din_data <= 8'h ED;
2'b01: din_data <= 8'h EB;
2'b00: din_data <= 8'h 03;
endcase
if (din_ready) begin
din_valid <= 0;
state <= 5;
end
end
5: begin
if (valid && !ready) begin
din_valid <= 1;
din_data <= addr[23:16];
if (din_ready)
din_qspi <= config_qspi;
din_ddr <= config_ddr;
if (din_ready) begin
din_valid <= 0;
state <= 6;
end
end
end
6: begin
din_valid <= 1;
din_data <= addr[15:8];
if (din_ready)
if (din_ready) begin
din_valid <= 0;
state <= 7;
end
end
7: begin
din_valid <= 1;
din_data <= addr[7:0];
if (din_ready)
state <= 8;
if (din_ready) begin
din_valid <= 0;
din_data <= 0;
state <= config_qspi ? 8 : 9;
end
end
8: begin
din_valid <= 1;
din_data <= 8'h 00;
din_data <= config_cont ? 8'h A5 : 8'h FF;
if (din_ready) begin
buffer_wen <= 4'b 0001;
din_rd <= 1;
din_data <= config_dummy;
din_valid <= 0;
state <= 9;
end
end
9: begin
din_valid <= 1;
din_data <= 8'h 00;
if (din_ready) begin
buffer_wen <= 4'b 0010;
buffer_wen <= 4'b 0001;
din_valid <= 0;
state <= 10;
end
end
@ -201,17 +226,26 @@ module spimemio (
din_valid <= 1;
din_data <= 8'h 00;
if (din_ready) begin
buffer_wen <= 4'b 0100;
buffer_wen <= 4'b 0010;
din_valid <= 0;
state <= 11;
end
end
11: begin
din_valid <= 1;
if (din_ready) begin
buffer_wen <= 4'b 0100;
din_valid <= 0;
state <= 12;
end
end
12: begin
if (!rd_wait || valid) begin
din_valid <= 1;
din_data <= 8'h 00;
if (din_ready) begin
buffer_wen <= 4'b 1000;
state <= 8;
din_valid <= 0;
state <= 9;
end
end
end
@ -222,7 +256,14 @@ module spimemio (
rd_valid <= 0;
xfer_resetn <= 0;
buffer_wen <= 0;
state <= 4;
if (config_cont) begin
state <= 5;
end else begin
state <= 4;
din_qspi <= 0;
din_ddr <= 0;
end
din_rd <= 0;
end
end
end
@ -260,13 +301,12 @@ module spimemio_xfer (
input flash_io2_di,
input flash_io3_di
);
localparam [3:0] mode_spi = 0;
reg [3:0] mode;
reg [7:0] obuffer;
reg [7:0] ibuffer;
reg [3:0] count;
reg [3:0] dummy_count;
reg xfer_cont;
reg xfer_qspi;
reg xfer_ddr;
@ -276,12 +316,13 @@ module spimemio_xfer (
reg [7:0] next_ibuffer;
reg [3:0] next_count;
reg fetch_next;
reg last_fetch_next;
reg fetch;
reg next_fetch;
reg last_fetch;
assign din_ready = din_valid && resetn && fetch_next;
assign din_ready = din_valid && resetn && next_fetch;
assign dout_valid = fetch_next && !last_fetch_next;
assign dout_valid = xfer_ddr ? fetch && !last_fetch : next_fetch && !fetch;
assign dout_data = ibuffer;
always @* begin
@ -298,34 +339,83 @@ module spimemio_xfer (
next_obuffer = obuffer;
next_ibuffer = ibuffer;
next_count = count;
fetch_next = 0;
next_fetch = 0;
case (mode)
mode_spi: begin
flash_io0_oe = 1;
flash_io0_do = obuffer[7];
if (dummy_count == 0) begin
case ({xfer_ddr, xfer_qspi})
2'b 00: begin
flash_io0_oe = 1;
flash_io0_do = obuffer[7];
if (flash_clk) begin
next_obuffer = {obuffer[6:0], 1'b 0};
next_count = count - |count;
end else begin
next_ibuffer = {ibuffer[6:0], flash_io1_di};
if (flash_clk) begin
next_obuffer = {obuffer[6:0], 1'b 0};
next_count = count - |count;
end else begin
next_ibuffer = {ibuffer[6:0], flash_io1_di};
end
next_fetch = (next_count == 0);
end
2'b 01: begin
flash_io0_oe = !xfer_rd;
flash_io1_oe = !xfer_rd;
flash_io2_oe = !xfer_rd;
flash_io3_oe = !xfer_rd;
fetch_next = (next_count == 0);
end
endcase
flash_io0_do = obuffer[4];
flash_io1_do = obuffer[5];
flash_io2_do = obuffer[6];
flash_io3_do = obuffer[7];
if (flash_clk) begin
next_obuffer = {obuffer[3:0], 4'b 0000};
next_count = count - {|count, 2'b00};
end else begin
next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
end
next_fetch = (next_count == 0);
end
2'b 11: begin
flash_io0_oe = !xfer_rd;
flash_io1_oe = !xfer_rd;
flash_io2_oe = !xfer_rd;
flash_io3_oe = !xfer_rd;
flash_io0_do = obuffer[4];
flash_io1_do = obuffer[5];
flash_io2_do = obuffer[6];
flash_io3_do = obuffer[7];
next_obuffer = {obuffer[3:0], 4'b 0000};
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
endcase
end
end
always @(posedge clk) begin
if (!resetn) begin
mode <= mode_spi;
last_fetch_next <= 1;
fetch <= 1;
last_fetch <= 1;
flash_csb <= 1;
flash_clk <= 0;
count <= 0;
dummy_count <= 0;
xfer_cont <= 0;
xfer_qspi <= 0;
xfer_ddr <= 0;
xfer_rd <= 0;
end else begin
last_fetch_next <= fetch_next;
fetch <= next_fetch;
last_fetch <= xfer_ddr ? fetch : 1;
if (dummy_count) begin
flash_clk <= !flash_clk && !flash_csb;
dummy_count <= dummy_count - flash_clk;
end else
if (count) begin
flash_clk <= !flash_clk && !flash_csb;
obuffer <= next_obuffer;
@ -337,8 +427,10 @@ module spimemio_xfer (
flash_clk <= 0;
obuffer <= din_data;
ibuffer <= 8'h 00;
// ibuffer <= 8'h 00;
count <= 8;
dummy_count <= din_rd ? din_data : 0;
xfer_cont <= din_cont;
xfer_qspi <= din_qspi;