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; 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;