Line 61... |
Line 61... |
// 7. Asynch Read-ID: Write here to cause controller to read ID into buffer
|
// 7. Asynch Read-ID: Write here to cause controller to read ID into buffer
|
// 8.-12. ID buffer (20 bytes, 5 words)
|
// 8.-12. ID buffer (20 bytes, 5 words)
|
// Attempted reads before buffer is full will stall bus until
|
// Attempted reads before buffer is full will stall bus until
|
// buffer is read. Writes act like the asynch-Read-ID command,
|
// buffer is read. Writes act like the asynch-Read-ID command,
|
// and will cause the controller to read the buffer.
|
// and will cause the controller to read the buffer.
|
// 13.-14. Unused, mapped to Asynch-read-ID
|
// 13. Reset Enable
|
|
// 14. Reset Memory
|
// 15. OTP control word
|
// 15. OTP control word
|
// Write zero to permanently lock OTP
|
// Write zero to permanently lock OTP
|
// Read to determine if OTP is permanently locked
|
// Read to determine if OTP is permanently locked
|
// 16.-31. OTP (64-bytes, 16 words, buffered until write)
|
// 16.-31. OTP (64-bytes, 16 words, buffered until write)
|
// (Send DWP before writing to clear write enable latch)
|
// (Send DWP before writing to clear write enable latch)
|
Line 176... |
Line 177... |
wire bus_ack;
|
wire bus_ack;
|
wire bus_readreq, bus_piperd, bus_ereq, bus_wreq,
|
wire bus_readreq, bus_piperd, bus_ereq, bus_wreq,
|
bus_pipewr, bus_endwr, bus_ctreq, bus_idreq,
|
bus_pipewr, bus_endwr, bus_ctreq, bus_idreq,
|
bus_other_req,
|
bus_other_req,
|
// Live parameters
|
// Live parameters
|
w_xip, w_quad, w_idloaded;
|
w_xip, w_quad, w_idloaded, w_leave_xip;
|
reg bus_wip;
|
reg bus_wip;
|
qspibus preproc(i_clk_200mhz, i_rst,
|
qspibus preproc(i_clk_200mhz, i_rst,
|
i_wb_cyc, i_wb_data_stb, i_wb_ctrl_stb,
|
i_wb_cyc, i_wb_data_stb, i_wb_ctrl_stb,
|
i_wb_we, i_wb_addr, i_wb_data,
|
i_wb_we, i_wb_addr, i_wb_data,
|
bus_wb_ack, bus_wb_stall, bus_wb_data,
|
bus_wb_ack, bus_wb_stall, bus_wb_data,
|
Line 216... |
Line 217... |
rd_qspi_req, rd_qspi_grant,
|
rd_qspi_req, rd_qspi_grant,
|
rd_spi_wr, rd_spi_hold, rd_spi_word, rd_spi_len,
|
rd_spi_wr, rd_spi_hold, rd_spi_word, rd_spi_len,
|
rd_spi_spd, rd_spi_dir, rd_spi_recycle,
|
rd_spi_spd, rd_spi_dir, rd_spi_recycle,
|
spi_out, spi_valid,
|
spi_out, spi_valid,
|
spi_busy, spi_stopped, rd_data_ack, rd_data,
|
spi_busy, spi_stopped, rd_data_ack, rd_data,
|
w_quad, w_xip);
|
w_quad, w_xip, w_leave_xip);
|
|
|
//
|
//
|
// Write/Erase flash module
|
// Write/Erase flash module
|
//
|
//
|
// Logic to write (program) and erase the flash.
|
// Logic to write (program) and erase the flash.
|
Line 266... |
Line 267... |
wire ct_spi_wr, ct_spi_hold, ct_spi_spd, ct_spi_dir;
|
wire ct_spi_wr, ct_spi_hold, ct_spi_spd, ct_spi_dir;
|
wire [31:0] ct_spi_word;
|
wire [31:0] ct_spi_word;
|
wire [1:0] ct_spi_len;
|
wire [1:0] ct_spi_len;
|
//
|
//
|
ctrlspi ctproc(i_clk_200mhz,
|
ctrlspi ctproc(i_clk_200mhz,
|
bus_ctreq, bus_wr, bus_addr[2:0], bus_data, bus_sector,
|
bus_ctreq, bus_wr, bus_addr[3:0], bus_data, bus_sector,
|
ct_qspi_req, ct_grant,
|
ct_qspi_req, ct_grant,
|
ct_spi_wr, ct_spi_hold, ct_spi_word, ct_spi_len,
|
ct_spi_wr, ct_spi_hold, ct_spi_word, ct_spi_len,
|
ct_spi_spd, ct_spi_dir,
|
ct_spi_spd, ct_spi_dir,
|
spi_out, spi_valid, spi_busy, spi_stopped,
|
spi_out, spi_valid, spi_busy, spi_stopped,
|
ct_ack, ct_data_ack, ct_data, w_xip, w_quad);
|
ct_ack, ct_data_ack, ct_data, w_leave_xip, w_xip, w_quad);
|
assign ct_spi_hold = 1'b0;
|
assign ct_spi_hold = 1'b0;
|
assign ct_spi_spd = 1'b0;
|
assign ct_spi_spd = 1'b0;
|
|
|
//
|
//
|
// ID/OTP module
|
// ID/OTP module
|
Line 532... |
Line 533... |
5'h8: o_idreq <= 1'b1; // ID[0]
|
5'h8: o_idreq <= 1'b1; // ID[0]
|
5'h9: o_idreq <= 1'b1; // ID[1]
|
5'h9: o_idreq <= 1'b1; // ID[1]
|
5'ha: o_idreq <= 1'b1; // ID[2]
|
5'ha: o_idreq <= 1'b1; // ID[2]
|
5'hb: o_idreq <= 1'b1; // ID[3]
|
5'hb: o_idreq <= 1'b1; // ID[3]
|
5'hc: o_idreq <= 1'b1; // ID[4]
|
5'hc: o_idreq <= 1'b1; // ID[4]
|
5'hd: o_idreq <= 1'b1; //
|
5'hd: lcl_ctreq <= 1'b1; //
|
5'he: o_idreq <= 1'b1;
|
5'he: lcl_ctreq <= 1'b1;
|
5'hf: o_idreq <= 1'b1; // Program OTP register
|
5'hf: o_idreq <= 1'b1; // Program OTP register
|
default: begin o_idreq <= 1'b1; end
|
default: begin o_idreq <= 1'b1; end
|
endcase
|
endcase
|
end else if (i_ctrl_stb)
|
end else if (i_ctrl_stb)
|
o_idreq <= 1'b1;
|
o_idreq <= 1'b1;
|
Line 579... |
Line 580... |
always @(posedge i_clk)
|
always @(posedge i_clk)
|
last_wip <= i_wip;
|
last_wip <= i_wip;
|
wire new_req;
|
wire new_req;
|
assign new_req = (pending)&&(~last_pending);
|
assign new_req = (pending)&&(~last_pending);
|
|
|
|
initial esector = 15'h00;
|
initial o_wrreq = 1'b0;
|
initial o_wrreq = 1'b0;
|
initial o_erreq = 1'b0;
|
initial o_erreq = 1'b0;
|
initial wp_err = 1'b0;
|
initial wp_err = 1'b0;
|
initial lcl_ack = 1'b0;
|
initial lcl_ack = 1'b0;
|
initial r_other = 1'b0;
|
initial r_other = 1'b0;
|
Line 610... |
Line 612... |
|
|
if (set_sector)
|
if (set_sector)
|
begin
|
begin
|
esector[13:0] <= { o_data[23:14], 4'h0 };
|
esector[13:0] <= { o_data[23:14], 4'h0 };
|
wp <= (o_data[30])&&(new_req)||(wp)&&(~new_req);
|
wp <= (o_data[30])&&(new_req)||(wp)&&(~new_req);
|
|
esector[14] <= o_data[28]; // Subsector
|
if (o_data[28])
|
if (o_data[28])
|
begin
|
begin
|
esector[14] <= o_data[28];
|
|
esector[3:0] <= o_data[13:10];
|
esector[3:0] <= o_data[13:10];
|
end
|
end
|
end
|
end
|
|
|
lcl_ack <= 1'b0;
|
lcl_ack <= 1'b0;
|
Line 699... |
Line 701... |
module readqspi(i_clk, i_readreq, i_piperd, i_other_req, i_addr, o_bus_ack,
|
module readqspi(i_clk, i_readreq, i_piperd, i_other_req, i_addr, o_bus_ack,
|
o_qspi_req, i_grant,
|
o_qspi_req, i_grant,
|
o_spi_wr, o_spi_hold, o_spi_word, o_spi_len,
|
o_spi_wr, o_spi_hold, o_spi_word, o_spi_len,
|
o_spi_spd, o_spi_dir, o_spi_recycle,
|
o_spi_spd, o_spi_dir, o_spi_recycle,
|
i_spi_data, i_spi_valid, i_spi_busy, i_spi_stopped,
|
i_spi_data, i_spi_valid, i_spi_busy, i_spi_stopped,
|
o_data_ack, o_data, i_quad, i_xip);
|
o_data_ack, o_data, i_quad, i_xip, o_leave_xip);
|
input i_clk;
|
input i_clk;
|
input i_readreq, i_piperd, i_other_req;
|
input i_readreq, i_piperd, i_other_req;
|
input [21:0] i_addr;
|
input [21:0] i_addr;
|
output reg o_bus_ack, o_qspi_req;
|
output reg o_bus_ack, o_qspi_req;
|
input wire i_grant;
|
input wire i_grant;
|
Line 715... |
Line 717... |
input [31:0] i_spi_data;
|
input [31:0] i_spi_data;
|
input i_spi_valid, i_spi_busy, i_spi_stopped;
|
input i_spi_valid, i_spi_busy, i_spi_stopped;
|
output reg o_data_ack;
|
output reg o_data_ack;
|
output reg [31:0] o_data;
|
output reg [31:0] o_data;
|
input i_quad, i_xip;
|
input i_quad, i_xip;
|
|
output wire o_leave_xip;
|
|
|
reg accepted;
|
reg accepted;
|
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);
|
Line 805... |
Line 808... |
end
|
end
|
`RD_QUAD_ADDRESS: begin
|
`RD_QUAD_ADDRESS: begin
|
o_qspi_req <= 1'b1;
|
o_qspi_req <= 1'b1;
|
o_spi_wr <= 1'b1;
|
o_spi_wr <= 1'b1;
|
o_spi_dir <= 1'b0; // Write the address
|
o_spi_dir <= 1'b0; // Write the address
|
o_spi_spd <= 1'b1; // High speed
|
o_spi_spd <= 1'b0;
|
o_spi_word[31:0] <= { i_addr, 2'b00, 8'h00 };
|
o_spi_word[31:0] <= { i_addr, 2'b00, 8'h00 };
|
o_spi_len <= 2'b10; // 24 bits, High speed, 6 clocks
|
o_spi_len <= 2'b10; // 24 bits, High speed, 6 clocks
|
if (accepted)
|
if (accepted)
|
rd_state <= `RD_QUAD_DUMMY;
|
rd_state <= `RD_QUAD_DUMMY;
|
end
|
end
|
Line 828... |
Line 831... |
r_requested <= 1'b0;
|
r_requested <= 1'b0;
|
o_qspi_req <= 1'b1;
|
o_qspi_req <= 1'b1;
|
o_spi_word <= { i_addr, 2'b00, 8'h00 };
|
o_spi_word <= { i_addr, 2'b00, 8'h00 };
|
o_spi_wr <= 1'b0;
|
o_spi_wr <= 1'b0;
|
o_spi_dir <= 1'b0; // Write to SPI
|
o_spi_dir <= 1'b0; // Write to SPI
|
o_spi_spd <= 1'b1; // High speed
|
o_spi_spd <= 1'b0;
|
o_spi_len <= 2'b11;
|
o_spi_len <= 2'b11;
|
r_leave_xip <= i_other_req;
|
r_leave_xip <= i_other_req;
|
r_xip <= (~i_other_req);
|
r_xip <= (~i_other_req);
|
o_bus_ack <= 1'b0;
|
o_bus_ack <= 1'b0;
|
if ((i_readreq)||(i_other_req))
|
if ((i_readreq)||(i_other_req))
|
Line 866... |
Line 869... |
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
assign o_spi_hold = 1'b0;
|
assign o_spi_hold = 1'b0;
|
|
assign o_leave_xip = r_leave_xip;
|
|
|
endmodule
|
endmodule
|
|
|
module writeqspi(i_clk, i_wreq, i_ereq, i_pipewr, i_endpipe, i_addr, i_data,
|
module writeqspi(i_clk, i_wreq, i_ereq, i_pipewr, i_endpipe, i_addr, i_data,
|
o_bus_ack, o_qspi_req, i_qspi_grant,
|
o_bus_ack, o_qspi_req, i_qspi_grant,
|
Line 1117... |
Line 1121... |
o_spi_req, i_grant,
|
o_spi_req, i_grant,
|
o_spi_wr, o_spi_hold, o_spi_word, o_spi_len,
|
o_spi_wr, o_spi_hold, o_spi_word, o_spi_len,
|
o_spi_spd, o_spi_dir,
|
o_spi_spd, o_spi_dir,
|
i_spi_data, i_spi_valid, i_spi_busy,
|
i_spi_data, i_spi_valid, i_spi_busy,
|
i_spi_stopped,
|
i_spi_stopped,
|
o_bus_ack, o_data_ack, o_data, o_xip, o_quad);
|
o_bus_ack, o_data_ack, o_data,
|
|
i_leave_xip, o_xip, o_quad);
|
input i_clk;
|
input i_clk;
|
// From the WB bus controller
|
// From the WB bus controller
|
input i_req;
|
input i_req;
|
input i_wr;
|
input i_wr;
|
input [2:0] i_addr;
|
input [3:0] i_addr;
|
input [31:0] i_data;
|
input [31:0] i_data;
|
input [21:0] i_sector_address;
|
input [21:0] i_sector_address;
|
// To/from the arbiter
|
// To/from the arbiter
|
output reg o_spi_req;
|
output reg o_spi_req;
|
input i_grant;
|
input i_grant;
|
Line 1142... |
Line 1147... |
input i_spi_busy, i_spi_stopped;
|
input i_spi_busy, i_spi_stopped;
|
// Return data to the bus controller, and the wishbone bus
|
// Return data to the bus controller, and the wishbone bus
|
output reg o_bus_ack, o_data_ack;
|
output reg o_bus_ack, o_data_ack;
|
output reg [31:0] o_data;
|
output reg [31:0] o_data;
|
// Configuration items that we may have configured.
|
// Configuration items that we may have configured.
|
|
input wire i_leave_xip;
|
output reg o_xip;
|
output reg o_xip;
|
output wire o_quad;
|
output wire o_quad;
|
|
|
// Command registers
|
// Command registers
|
reg [1:0] ctcmd_len;
|
reg [1:0] ctcmd_len;
|
Line 1179... |
Line 1185... |
ctcmd_word[23:0] <= { i_sector_address, 2'b00 };
|
ctcmd_word[23:0] <= { i_sector_address, 2'b00 };
|
ctdat_word <= { i_data[7:0], 24'h00 };
|
ctdat_word <= { i_data[7:0], 24'h00 };
|
ctcmd_len <= 2'b00; // 8bit command (for all but Lock regs)
|
ctcmd_len <= 2'b00; // 8bit command (for all but Lock regs)
|
r_ctdat_len <= 1'b0; // 8bit data (read or write)
|
r_ctdat_len <= 1'b0; // 8bit data (read or write)
|
ctdat_wr <= i_wr;
|
ctdat_wr <= i_wr;
|
casez({ i_addr[2:0], i_wr, i_data[30] })
|
casez({ i_addr[3:0], i_wr, i_data[30] })
|
5'b00010: begin // Write Disable
|
6'b000010: begin // Write Disable
|
ctcmd_word[31:24] <= 8'h04;
|
ctcmd_word[31:24] <= 8'h04;
|
ctdat_skip <= 1'b1;
|
ctdat_skip <= 1'b1;
|
ctbus_ack <= 1'b0;
|
ctbus_ack <= 1'b0;
|
end
|
end
|
5'b00011: begin // Write enable
|
6'b000011: begin // Write enable
|
ctcmd_word[31:24] <= 8'h06;
|
ctcmd_word[31:24] <= 8'h06;
|
ctdat_skip <= 1'b1;
|
ctdat_skip <= 1'b1;
|
ctbus_ack <= 1'b0;
|
ctbus_ack <= 1'b0;
|
end
|
end
|
// 4'b0010?: begin // Read Status register
|
// 4'b0010?: begin // Read Status register
|
// Moved to defaults section
|
// Moved to defaults section
|
5'b0011?: begin // Write Status register (Requires WEL)
|
6'b00011?: begin // Write Status register (Requires WEL)
|
ctcmd_word[31:24] <= 8'h01;
|
ctcmd_word[31:24] <= 8'h01;
|
`ifdef CT_SAFE
|
`ifdef CT_SAFE
|
ctdat_word <= { 6'h00, i_data[1:0], 24'h00 };
|
ctdat_word <= { 6'h00, i_data[1:0], 24'h00 };
|
`else
|
`else
|
ctdat_word <= { i_data[7:0], 24'h00 };
|
ctdat_word <= { i_data[7:0], 24'h00 };
|
`endif
|
`endif
|
end
|
end
|
5'b0100?: begin // Read NV-Config register (two bytes)
|
6'b00100?: begin // Read NV-Config register (two bytes)
|
ctcmd_word[31:24] <= 8'hB5;
|
ctcmd_word[31:24] <= 8'hB5;
|
r_ctdat_len <= 1'b1; // 16-bit data
|
r_ctdat_len <= 1'b1; // 16-bit data
|
end
|
end
|
5'b0101?: begin // Write NV-Config reg (2 bytes, Requires WEL)
|
6'b00101?: begin // Write NV-Config reg (2 bytes, Requires WEL)
|
ctcmd_word[31:24] <= 8'hB1;
|
ctcmd_word[31:24] <= 8'hB1;
|
r_ctdat_len <= 1'b1; // 16-bit data
|
r_ctdat_len <= 1'b1; // 16-bit data
|
`ifdef CT_SAFE
|
`ifdef CT_SAFE
|
ctdat_word <= { 4'h8, 3'h7, 3'h7, i_data[5:1], 1'b1, 16'h00 };
|
ctdat_word <= { 4'h8, 3'h7, 3'h7, i_data[5:1], 1'b1, 16'h00 };
|
`else
|
`else
|
ctdat_word <= { i_data[15:0], 16'h00 };
|
ctdat_word <= { i_data[15:0], 16'h00 };
|
`endif
|
`endif
|
end
|
end
|
5'b0110?: begin // Read V-Config register
|
6'b00110?: begin // Read V-Config register
|
ctcmd_word[31:24] <= 8'h85;
|
ctcmd_word[31:24] <= 8'h85;
|
end
|
end
|
5'b0111?: begin // Write V-Config register (Requires WEL)
|
6'b00111?: begin // Write V-Config register (Requires WEL)
|
ctcmd_word[31:24] <= 8'h81;
|
ctcmd_word[31:24] <= 8'h81;
|
r_ctdat_len <= 1'b0; // 8-bit data
|
r_ctdat_len <= 1'b0; // 8-bit data
|
`ifdef CT_SAFE
|
// `ifdef CT_SAFE
|
ctdat_word <= { 4'h8, i_data[3:2], 2'b11, 24'h00 };
|
// ctdat_word <= { 4'h8, i_data[3:2], 2'b11, 24'h00 };
|
`else
|
// `else
|
ctdat_word <= { i_data[7:0], 24'h00 };
|
ctdat_word <= { i_data[7:0], 24'h00 };
|
`endif
|
// `endif
|
o_xip <= i_data[3];
|
o_xip <= ~i_data[3];
|
end
|
end
|
5'b1000?: begin // Read EV-Config register
|
6'b01000?: begin // Read EV-Config register
|
ctcmd_word[31:24] <= 8'h65;
|
ctcmd_word[31:24] <= 8'h65;
|
end
|
end
|
5'b1001?: begin // Write EV-Config register (Requires WEL)
|
6'b01001?: begin // Write EV-Config register (Requires WEL)
|
ctcmd_word[31:24] <= 8'h61;
|
ctcmd_word[31:24] <= 8'h61;
|
// o_quad <= (~i_data[7]);
|
// o_quad <= (~i_data[7]);
|
`ifdef CT_SAFE
|
`ifdef CT_SAFE
|
ctdat_word <= { 1'b1, 3'h5, 4'hf, 24'h00 };
|
ctdat_word <= { 1'b1, 3'h5, 4'hf, 24'h00 };
|
`else
|
`else
|
ctdat_word <= { i_data[7:0], 24'h00 };
|
ctdat_word <= { i_data[7:0], 24'h00 };
|
`endif
|
`endif
|
end
|
end
|
5'b1010?: begin // Read Lock register
|
6'b01010?: begin // Read Lock register
|
ctcmd_word[31:0] <= { 8'he8, i_sector_address, 2'b00 };
|
ctcmd_word[31:0] <= { 8'he8, i_sector_address, 2'b00 };
|
ctcmd_len <= 2'b11;
|
ctcmd_len <= 2'b11;
|
ctdat_wr <= 1'b0; // Read, not write
|
ctdat_wr <= 1'b0; // Read, not write
|
end
|
end
|
5'b1011?: begin // Write Lock register (Requires WEL)
|
6'b01011?: begin // Write Lock register (Requires WEL)
|
ctcmd_word[31:0] <= { 8'he5, i_sector_address, 2'b00 };
|
ctcmd_word[31:0] <= { 8'he5, i_sector_address, 2'b00 };
|
ctcmd_len <= 2'b11;
|
ctcmd_len <= 2'b11;
|
ctdat_wr <= 1'b1; // Write
|
ctdat_wr <= 1'b1; // Write
|
end
|
end
|
5'b1100?: begin // Read Flag Status register
|
6'b01100?: begin // Read Flag Status register
|
ctcmd_word[31:24] <= 8'h70;
|
ctcmd_word[31:24] <= 8'h70;
|
ctdat_wr <= 1'b0; // Read, not write
|
ctdat_wr <= 1'b0; // Read, not write
|
end
|
end
|
5'b1101?: begin // Write/Clear Flag Status register (No WEL required)
|
6'b01101?: begin // Write/Clear Flag Status register (No WEL required)
|
ctcmd_word[31:24] <= 8'h50;
|
ctcmd_word[31:24] <= 8'h50;
|
ctdat_skip <= 1'b1;
|
ctdat_skip <= 1'b1;
|
end
|
end
|
|
6'b11011?: begin // RESET_ENABLE (when written to)
|
|
ctcmd_word[31:24] <= 8'h66;
|
|
ctdat_skip <= 1'b1;
|
|
end
|
|
6'b11101?: begin // RESET_MEMORY (when written to)
|
|
ctcmd_word[31:24] <= 8'h99;
|
|
ctdat_skip <= 1'b1;
|
|
end
|
default: begin // Default to reading the status register
|
default: begin // Default to reading the status register
|
ctcmd_word[31:24] <= 8'h05;
|
ctcmd_word[31:24] <= 8'h05;
|
ctdat_wr <= 1'b0; // Read, not write
|
ctdat_wr <= 1'b0; // Read, not write
|
r_ctdat_len <= 1'b0; // 8-bit data
|
r_ctdat_len <= 1'b0; // 8-bit data
|
end
|
end
|
endcase
|
endcase
|
end
|
end else if (i_leave_xip)
|
|
o_xip <= 1'b0;
|
|
|
assign o_quad = 1'b1;
|
assign o_quad = 1'b1;
|
|
|
reg nxt_data_ack;
|
reg nxt_data_ack;
|
|
|