Line 722... |
Line 722... |
initial accepted = 1'b0;
|
initial accepted = 1'b0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
accepted <= (~i_spi_busy)&&(i_grant)&&(o_spi_wr)&&(~accepted);
|
accepted <= (~i_spi_busy)&&(i_grant)&&(o_spi_wr)&&(~accepted);
|
|
|
reg [3:0] rd_state;
|
reg [3:0] rd_state;
|
reg r_leave_xip, r_xip, r_quad, r_requested;
|
reg r_leave_xip, r_xip, r_quad, r_requested, ack_valid;
|
initial rd_state = `RD_IDLE;
|
initial rd_state = `RD_IDLE;
|
initial o_data_ack = 1'b0;
|
initial o_data_ack = 1'b0;
|
initial o_bus_ack = 1'b0;
|
initial o_bus_ack = 1'b0;
|
initial o_qspi_req = 1'b0;
|
initial o_qspi_req = 1'b0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
Line 736... |
Line 736... |
o_spi_recycle <= 1'b0;
|
o_spi_recycle <= 1'b0;
|
if (i_spi_valid)
|
if (i_spi_valid)
|
o_data <= i_spi_data;
|
o_data <= i_spi_data;
|
case(rd_state)
|
case(rd_state)
|
`RD_IDLE: begin
|
`RD_IDLE: begin
|
|
ack_valid <= 1'b0;
|
r_requested <= 1'b0;
|
r_requested <= 1'b0;
|
o_qspi_req <= 1'b0;
|
o_qspi_req <= 1'b0;
|
o_spi_word <= { ((i_quad)? 8'h6B: 8'h0b), i_addr, 2'b00 };
|
o_spi_word <= { ((i_quad)? 8'h6B: 8'h0b), i_addr, 2'b00 };
|
o_spi_wr <= 1'b0;
|
o_spi_wr <= 1'b0;
|
o_spi_dir <= 1'b0;
|
o_spi_dir <= 1'b0;
|
Line 754... |
Line 755... |
o_bus_ack <= 1'b1;
|
o_bus_ack <= 1'b1;
|
end end
|
end end
|
`RD_IDLE_GET_PORT: begin
|
`RD_IDLE_GET_PORT: begin
|
o_spi_wr <= 1'b1; // Write the address
|
o_spi_wr <= 1'b1; // Write the address
|
o_qspi_req <= 1'b1;
|
o_qspi_req <= 1'b1;
|
|
ack_valid <= 1'b0;
|
if (accepted)
|
if (accepted)
|
rd_state <= `RD_SLOW_DUMMY;
|
rd_state <= `RD_SLOW_DUMMY;
|
end
|
end
|
`RD_SLOW_DUMMY: begin
|
`RD_SLOW_DUMMY: begin
|
o_spi_wr <= 1'b1; // Write 8 dummy clocks
|
o_spi_wr <= 1'b1; // Write 8 dummy clocks
|
o_qspi_req <= 1'b1;
|
o_qspi_req <= 1'b1;
|
o_spi_dir <= 1'b0;
|
o_spi_dir <= 1'b0;
|
o_spi_spd <= 1'b0;
|
o_spi_spd <= 1'b0;
|
o_spi_word[31:24] <= (r_xip) ? 8'h00 : 8'hff;
|
o_spi_word[31:24] <= (r_xip) ? 8'h00 : 8'hff;
|
o_spi_len <= 2'b00; // 8 clocks = 8-bits
|
o_spi_len <= 2'b00; // 8 clocks = 8-bits
|
|
ack_valid <= 1'b0;
|
if (accepted)
|
if (accepted)
|
rd_state <= (r_quad)?`RD_QUAD_READ_DATA
|
rd_state <= (r_quad)?`RD_QUAD_READ_DATA
|
: `RD_SLOW_READ_DATA;
|
: `RD_SLOW_READ_DATA;
|
end
|
end
|
`RD_SLOW_READ_DATA: begin
|
`RD_SLOW_READ_DATA: begin
|
Line 776... |
Line 779... |
o_spi_spd <= 1'b0;
|
o_spi_spd <= 1'b0;
|
o_spi_len <= 2'b11;
|
o_spi_len <= 2'b11;
|
o_spi_wr <= (~r_requested)||(i_piperd);
|
o_spi_wr <= (~r_requested)||(i_piperd);
|
// if (accepted)
|
// if (accepted)
|
// o_spi_wr <= (i_piperd);
|
// o_spi_wr <= (i_piperd);
|
o_data_ack <= (r_requested)&&(i_spi_valid);
|
o_data_ack <= (ack_valid)&&(i_spi_valid);
|
o_bus_ack <= (r_requested)&&(accepted)&&(i_piperd);
|
o_bus_ack <= (r_requested)&&(accepted)&&(i_piperd);
|
r_requested <= (r_requested)||(accepted);
|
r_requested <= (r_requested)||(accepted);
|
|
ack_valid <= (accepted)?(r_requested):ack_valid;
|
if ((i_spi_valid)&&(~o_spi_wr))
|
if ((i_spi_valid)&&(~o_spi_wr))
|
rd_state <= `RD_GO_TO_IDLE;
|
rd_state <= `RD_GO_TO_IDLE;
|
end
|
end
|
`RD_QUAD_READ_DATA: begin
|
`RD_QUAD_READ_DATA: begin
|
o_qspi_req <= 1'b1;
|
o_qspi_req <= 1'b1;
|
o_spi_dir <= 1'b1;
|
o_spi_dir <= 1'b1;
|
o_spi_spd <= 1'b1;
|
o_spi_spd <= 1'b1;
|
o_spi_len <= 2'b11;
|
o_spi_len <= 2'b11;
|
o_spi_recycle <= (r_leave_xip)? 1'b1: 1'b0;
|
o_spi_recycle <= (r_leave_xip)? 1'b1: 1'b0;
|
r_requested <= (r_requested)||(accepted);
|
r_requested <= (r_requested)||(accepted);
|
o_data_ack <= (r_requested)&&(i_spi_valid)&&(~r_leave_xip);
|
ack_valid <= (r_requested);
|
|
o_data_ack <= (ack_valid)&&(i_spi_valid)&&(~r_leave_xip);
|
o_bus_ack <= (r_requested)&&(accepted)&&(i_piperd)&&(~r_leave_xip);
|
o_bus_ack <= (r_requested)&&(accepted)&&(i_piperd)&&(~r_leave_xip);
|
o_spi_wr <= (~r_requested)||(i_piperd);
|
o_spi_wr <= (~r_requested)||(i_piperd);
|
// if (accepted)
|
// if (accepted)
|
// o_spi_wr <= (i_piperd);
|
// o_spi_wr <= (i_piperd);
|
if (accepted)
|
if (accepted) // only happens if (o_spi_wr)
|
o_data <= i_spi_data;
|
o_data <= i_spi_data;
|
if ((i_spi_valid)&&(~o_spi_wr))
|
if ((i_spi_valid)&&(~o_spi_wr))
|
rd_state <= ((r_leave_xip)||(~r_xip))?`RD_GO_TO_IDLE:`RD_GO_TO_XIP;
|
rd_state <= ((r_leave_xip)||(~r_xip))?`RD_GO_TO_IDLE:`RD_GO_TO_XIP;
|
end
|
end
|
`RD_QUAD_ADDRESS: begin
|
`RD_QUAD_ADDRESS: begin
|
Line 837... |
Line 842... |
begin
|
begin
|
rd_state <= `RD_QUAD_ADDRESS;
|
rd_state <= `RD_QUAD_ADDRESS;
|
o_bus_ack <= i_readreq;
|
o_bus_ack <= i_readreq;
|
end end
|
end end
|
`RD_GO_TO_IDLE: begin
|
`RD_GO_TO_IDLE: begin
|
o_qspi_req <= 1'b0;
|
r_requested <= 1'b0;
|
|
ack_valid <= 1'b0;
|
o_spi_wr <= 1'b0;
|
o_spi_wr <= 1'b0;
|
|
o_qspi_req <= 1'b0;
|
if ((i_spi_stopped)&&(~i_grant))
|
if ((i_spi_stopped)&&(~i_grant))
|
rd_state <= `RD_IDLE;
|
rd_state <= `RD_IDLE;
|
end
|
end
|
`RD_GO_TO_XIP: begin
|
`RD_GO_TO_XIP: begin
|
|
r_requested <= 1'b0;
|
|
ack_valid <= 1'b0;
|
o_qspi_req <= 1'b1;
|
o_qspi_req <= 1'b1;
|
o_spi_wr <= 1'b0;
|
o_spi_wr <= 1'b0;
|
if (i_spi_stopped)
|
if (i_spi_stopped)
|
rd_state <= `RD_XIP;
|
rd_state <= `RD_XIP;
|
end
|
end
|
Line 923... |
Line 932... |
initial accepted = 1'b0;
|
initial accepted = 1'b0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
accepted <= (~i_spi_busy)&&(i_qspi_grant)&&(o_spi_wr)&&(~accepted);
|
accepted <= (~i_spi_busy)&&(i_qspi_grant)&&(o_spi_wr)&&(~accepted);
|
|
|
|
|
reg cyc, chk_wip;
|
reg cyc, chk_wip, valid_status;
|
reg [3:0] wr_state;
|
reg [3:0] wr_state;
|
initial wr_state = `WR_IDLE;
|
initial wr_state = `WR_IDLE;
|
initial cyc = 1'b0;
|
initial cyc = 1'b0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
begin
|
begin
|
Line 935... |
Line 944... |
o_bus_ack <= 1'b0;
|
o_bus_ack <= 1'b0;
|
o_data_ack <= 1'b0;
|
o_data_ack <= 1'b0;
|
cyc <= (cyc)&&(~i_endpipe);
|
cyc <= (cyc)&&(~i_endpipe);
|
case(wr_state)
|
case(wr_state)
|
`WR_IDLE: begin
|
`WR_IDLE: begin
|
|
valid_status <= 1'b0;
|
o_qspi_req <= 1'b0;
|
o_qspi_req <= 1'b0;
|
cyc <= 1'b0;
|
cyc <= 1'b0;
|
if (i_ereq)
|
if (i_ereq)
|
wr_state <= `WR_START_ERASE;
|
wr_state <= `WR_START_ERASE;
|
else if (i_wreq)
|
else if (i_wreq)
|
Line 1059... |
Line 1069... |
o_spi_len <= 2'b00; // 8 bytes
|
o_spi_len <= 2'b00; // 8 bytes
|
o_spi_dir <= 1'b1; // Read
|
o_spi_dir <= 1'b1; // Read
|
o_spi_word <= 32'h00;
|
o_spi_word <= 32'h00;
|
if (accepted)
|
if (accepted)
|
wr_state <= `WR_READ_STATUS;
|
wr_state <= `WR_READ_STATUS;
|
|
valid_status <= 1'b0;
|
end
|
end
|
`WR_READ_STATUS: begin
|
`WR_READ_STATUS: begin
|
o_wip <= 1'b1;
|
o_wip <= 1'b1;
|
o_qspi_req <= 1'b1;
|
o_qspi_req <= 1'b1;
|
o_spi_hold <= 1'b0;
|
o_spi_hold <= 1'b0;
|
Line 1070... |
Line 1081... |
o_spi_spd <= 1'b0; // Slow speed
|
o_spi_spd <= 1'b0; // Slow speed
|
o_spi_len <= 2'b00; // 8 bytes
|
o_spi_len <= 2'b00; // 8 bytes
|
o_spi_dir <= 1'b1; // Read
|
o_spi_dir <= 1'b1; // Read
|
o_spi_word <= 32'h00;
|
o_spi_word <= 32'h00;
|
if (i_spi_valid)
|
if (i_spi_valid)
|
|
valid_status <= 1'b1;
|
|
if ((i_spi_valid)&&(valid_status))
|
chk_wip <= 1'b1;
|
chk_wip <= 1'b1;
|
if ((chk_wip)&&(~i_spi_data[0]))
|
if ((chk_wip)&&(~i_spi_data[0]))
|
wr_state <= `WR_WAIT_ON_FINAL_STOP;
|
wr_state <= `WR_WAIT_ON_FINAL_STOP;
|
end
|
end
|
// `WR_WAIT_ON_FINAL_STOP: // Same as the default
|
// `WR_WAIT_ON_FINAL_STOP: // Same as the default
|
Line 1151... |
Line 1164... |
|
|
initial accepted = 1'b0;
|
initial accepted = 1'b0;
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
accepted <= (~i_spi_busy)&&(i_grant)&&(o_spi_wr)&&(~accepted);
|
accepted <= (~i_spi_busy)&&(i_grant)&&(o_spi_wr)&&(~accepted);
|
|
|
reg r_ctdat_len, ctbus_ack;
|
reg r_ctdat_len, ctbus_ack, first_valid;
|
assign ctdat_len = { 1'b0, r_ctdat_len };
|
assign ctdat_len = { 1'b0, r_ctdat_len };
|
|
|
// First step, calculate the values for our state machine
|
// First step, calculate the values for our state machine
|
initial o_xip = 1'b0;
|
initial o_xip = 1'b0;
|
// initial o_quad = 1'b0;
|
// initial o_quad = 1'b0;
|
Line 1302... |
Line 1315... |
o_bus_ack <= 1'b1;
|
o_bus_ack <= 1'b1;
|
if (accepted)
|
if (accepted)
|
ctstate <= (ctdat_wr)?`CT_WAIT_FOR_IDLE:`CT_READ_DATA;
|
ctstate <= (ctdat_wr)?`CT_WAIT_FOR_IDLE:`CT_READ_DATA;
|
if ((accepted)&&(ctdat_wr))
|
if ((accepted)&&(ctdat_wr))
|
o_data_ack <= 1'b1;
|
o_data_ack <= 1'b1;
|
|
first_valid <= 1'b0;
|
end
|
end
|
`CT_READ_DATA: begin
|
`CT_READ_DATA: begin
|
o_spi_wr <= 1'b0; // No more words to go, just to wait
|
o_spi_wr <= 1'b0; // No more words to go, just to wait
|
o_spi_req <= 1'b1;
|
o_spi_req <= 1'b1;
|
if (i_spi_valid) // for a value to read
|
if (i_spi_valid)
|
|
first_valid <= 1'b1;
|
|
if ((i_spi_valid)&&(first_valid)) // for a value to read
|
begin
|
begin
|
o_data_ack <= 1'b1;
|
o_data_ack <= 1'b1;
|
o_data <= i_spi_data;
|
o_data <= i_spi_data;
|
ctstate <= `CT_WAIT_FOR_IDLE;
|
ctstate <= `CT_WAIT_FOR_IDLE;
|
end end
|
end end
|
Line 1424... |
Line 1440... |
// Now, quickly, let's deal with the fact that the data from the
|
// Now, quickly, let's deal with the fact that the data from the
|
// bus comes one clock later ...
|
// bus comes one clock later ...
|
reg nxt_data_ack, nxt_data_spi;
|
reg nxt_data_ack, nxt_data_spi;
|
reg [31:0] nxt_data;
|
reg [31:0] nxt_data;
|
|
|
reg set_val, chk_wip;
|
reg set_val, chk_wip, first_valid, valid_status;
|
reg [2:0] set_addr;
|
reg [2:0] set_addr;
|
|
|
always @(posedge i_clk)
|
always @(posedge i_clk)
|
begin // Depends upon state[4], otp_rd, otp_wr, otp_pipe, id_req, accepted, last_addr
|
begin // Depends upon state[4], otp_rd, otp_wr, otp_pipe, id_req, accepted, last_addr
|
o_bus_ack <= 1'b0;
|
o_bus_ack <= 1'b0;
|
Line 1452... |
Line 1468... |
lcl_id_addr <= 3'h0;
|
lcl_id_addr <= 3'h0;
|
o_spi_word[23:7] <= 17'h00;
|
o_spi_word[23:7] <= 17'h00;
|
o_spi_word[6:0] <= { req_addr[4:0], 2'b00 };
|
o_spi_word[6:0] <= { req_addr[4:0], 2'b00 };
|
r_data <= i_data;
|
r_data <= i_data;
|
o_wip <= 1'b0;
|
o_wip <= 1'b0;
|
|
first_valid <= 1'b0;
|
if (otp_read_request)
|
if (otp_read_request)
|
begin
|
begin
|
// o_spi_word <= { 8'h48, 8'h00, 8'h00, 8'h00 };
|
// o_spi_word <= { 8'h48, 8'h00, 8'h00, 8'h00 };
|
id_state <= `ID_WAIT_ON_START_OTP;
|
id_state <= `ID_WAIT_ON_START_OTP;
|
o_bus_ack <= 1'b1;
|
o_bus_ack <= 1'b1;
|
Line 1496... |
Line 1513... |
if (accepted) // Read OTP command was just sent
|
if (accepted) // Read OTP command was just sent
|
id_state <= `ID_OTP_WRITE;
|
id_state <= `ID_OTP_WRITE;
|
end
|
end
|
`ID_READ_DATA_COMMAND: begin
|
`ID_READ_DATA_COMMAND: begin
|
o_spi_len <= 2'b11; // 32-bits
|
o_spi_len <= 2'b11; // 32-bits
|
o_spi_wr <= (~last_addr); // Still transmitting
|
o_spi_wr <= 1'b1; // Still transmitting
|
o_spi_dir <= 1'b1; // Read from SPI
|
o_spi_dir <= 1'b1; // Read from SPI
|
o_qspi_req <= 1'b1;
|
o_qspi_req <= 1'b1;
|
if (accepted)
|
if (accepted)
|
id_state <= `ID_GET_DATA;
|
id_state <= `ID_GET_DATA;
|
|
first_valid <= 1'b0;
|
end
|
end
|
`ID_GET_DATA: begin
|
`ID_GET_DATA: begin
|
o_spi_len <= 2'b11; // 32-bits
|
o_spi_len <= 2'b11; // 32-bits
|
o_spi_wr <= (~last_addr); // Still transmitting
|
o_spi_wr <= (~last_addr); // Still transmitting
|
o_spi_dir <= 1'b1; // Read from SPI
|
o_spi_dir <= 1'b1; // Read from SPI
|
o_qspi_req <= 1'b1;
|
o_qspi_req <= 1'b1;
|
if (i_spi_valid) // same as accepted
|
if (i_spi_valid) // two clocks after accepted
|
|
first_valid <= 1'b1;
|
|
if((i_spi_valid)&&(first_valid))
|
begin
|
begin
|
set_val <= 1'b1;
|
set_val <= 1'b1;
|
set_addr <= lcl_id_addr[2:0];
|
set_addr <= lcl_id_addr[2:0];
|
// idmem[lcl_id_addr[2:0]] <= i_spi_data;
|
// idmem[lcl_id_addr[2:0]] <= i_spi_data;
|
lcl_id_addr <= lcl_id_addr + 3'h1;
|
lcl_id_addr <= lcl_id_addr + 3'h1;
|
Line 1540... |
Line 1560... |
id_state <= `ID_OTP_CLEAR;
|
id_state <= `ID_OTP_CLEAR;
|
end
|
end
|
`ID_OTP_CLEAR: begin
|
`ID_OTP_CLEAR: begin
|
o_spi_wr <= 1'b1; // Still writing
|
o_spi_wr <= 1'b1; // Still writing
|
o_spi_dir <= 1'b1; // Read from SPI
|
o_spi_dir <= 1'b1; // Read from SPI
|
o_spi_len <= 2'b11; // Read from SPI
|
o_spi_len <= 2'b11; // Read 32 bits
|
if (accepted)
|
if (accepted)
|
id_state <= `ID_OTP_GET_DATA;
|
id_state <= `ID_OTP_GET_DATA;
|
end
|
end
|
`ID_OTP_GET_DATA: begin
|
`ID_OTP_GET_DATA: begin
|
if (i_spi_valid)
|
if (i_spi_valid)
|
|
first_valid <= 1'b1;
|
|
if ((i_spi_valid)&&(first_valid))
|
begin
|
begin
|
id_state <= `ID_FINAL_STOP;
|
id_state <= `ID_FINAL_STOP;
|
nxt_data_ack <= 1'b1;
|
nxt_data_ack <= 1'b1;
|
nxt_data_spi <= 1'b1;
|
nxt_data_spi <= 1'b1;
|
end end
|
end end
|
Line 1585... |
Line 1607... |
o_spi_wr <= 1'b1;
|
o_spi_wr <= 1'b1;
|
o_spi_hold <= 1'b0;
|
o_spi_hold <= 1'b0;
|
o_spi_dir <= 1'b1; // Read
|
o_spi_dir <= 1'b1; // Read
|
o_spi_len <= 2'b00; // 8 bits
|
o_spi_len <= 2'b00; // 8 bits
|
// o_spi_word <= dont care
|
// o_spi_word <= dont care
|
|
valid_status <= 1'b0;
|
if (accepted)
|
if (accepted)
|
id_state <= `ID_READ_STATUS;
|
id_state <= `ID_READ_STATUS;
|
end
|
end
|
`ID_READ_STATUS: begin
|
`ID_READ_STATUS: begin
|
o_spi_wr <= 1'b1;
|
o_spi_wr <= 1'b1;
|
o_spi_hold <= 1'b0;
|
o_spi_hold <= 1'b0;
|
o_spi_dir <= 1'b1; // Read
|
o_spi_dir <= 1'b1; // Read
|
o_spi_len <= 2'b00; // 8 bits
|
o_spi_len <= 2'b00; // 8 bits
|
// o_spi_word <= dont care
|
// o_spi_word <= dont care
|
if (i_spi_valid)
|
if (i_spi_valid)
|
|
valid_status <= 1'b1;
|
|
if ((i_spi_valid)&&(valid_status))
|
chk_wip <= 1'b1;
|
chk_wip <= 1'b1;
|
if ((chk_wip)&&(~i_spi_data[0]))
|
if ((chk_wip)&&(~i_spi_data[0]))
|
begin
|
begin
|
o_wip <= 1'b0;
|
o_wip <= 1'b0;
|
id_state <= `ID_FINAL_STOP;
|
id_state <= `ID_FINAL_STOP;
|