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