URL
https://opencores.org/ocsvn/qspiflash/qspiflash/trunk
Subversion Repositories qspiflash
Compare Revisions
- This comparison shows the changes necessary to convert path
/qspiflash/trunk
- from Rev 14 to Rev 13
- ↔ Reverse comparison
Rev 14 → Rev 13
/bench/cpp/eqspiflashsim.cpp
110,7 → 110,7
m_ireg = m_oreg = 0; |
m_sreg = 0x01c; |
m_creg = 0x001; // Initial creg on delivery |
m_vconfig = 0x7; // Volatile configuration register |
m_config = 0x7; // Volatile configuration register |
m_nvconfig = 0x0fff; // Nonvolatile configuration register |
m_quad_mode = false; |
m_mode_byte = 0; |
431,12 → 431,12
break; |
case 0x81: // Write volatile config register |
m_state = EQSPIF_WRCR; |
if (m_debug) printf("EQSPI: WRITING VOLATILE CONFIG REGISTER: %02x\n", m_vconfig); |
if (m_debug) printf("EQSPI: WRITING CONFIG REGISTER: %02x\n", m_config); |
break; |
case 0x85: // Read volatile config register |
m_state = EQSPIF_RDCR; |
if (m_debug) printf("EQSPI: READING VOLATILE CONFIG REGISTER: %02x\n", m_vconfig); |
QOREG(m_vconfig); |
if (m_debug) printf("EQSPI: READING CONFIG REGISTER: %02x\n", m_config); |
QOREG(m_config>>8); |
break; |
case 0x9e: // Read ID (fall through) |
case 0x9f: // Read ID |
508,19 → 508,19
} |
break; |
case EQSPIF_WRCR: // Write volatile config register, 0x81 |
if (m_count == 8+8) { |
m_vconfig = m_ireg & 0x0ff; |
printf("Setting volatile config register to %08x\n", m_vconfig); |
assert((m_vconfig & 0xfb)==0x8b); |
if (m_count == 8) { |
m_config = m_ireg & 0x0ff; |
printf("Setting volatile config register to %08x\n", m_config); |
assert((m_config & 0xfb)==0x8b); |
} break; |
case EQSPIF_WRNVCONFIG: // Write nonvolatile config register |
if (m_count == 8+8) { |
if (m_count == 8) { |
m_nvconfig = m_ireg & 0x0ffdf; |
printf("Setting nonvolatile config register to %08x\n", m_nvconfig); |
printf("Setting nonvolatile config register to %08x\n", m_config); |
assert((m_nvconfig & 0xffc5)==0x8fc5); |
} break; |
case EQSPIF_WREVCONFIG: // Write enhanced volatile config reg |
if (m_count == 8+8) { |
if (m_count == 8) { |
m_evconfig = m_ireg & 0x0ff; |
printf("Setting enhanced volatile config register to %08x\n", m_evconfig); |
assert((m_evconfig & 0x0d7)==0xd7); |
592,7 → 592,7
QOREG(m_sreg); |
break; |
case EQSPIF_RDCR: |
if (m_debug) printf("Read VCONF = %02x\n", m_vconfig); |
if (m_debug) printf("Read CREG = %02x\n", m_creg); |
QOREG(m_creg); |
break; |
case EQSPIF_FAST_READ: |
637,7 → 637,7
// printf("EQSPIF[%08x]/QR = %02x\n", |
// m_addr-1, m_oreg); |
} else { |
// printf("ERR: EQSPIF--TRYING TO READ WHILE BUSY! (count = %d)\n", m_count); |
printf("ERR: EQSPIF--TRYING TO READ WHILE BUSY! (count = %d)\n", m_count); |
m_oreg = 0; |
} |
break; |
/bench/cpp/eqspiflashsim.h
82,7 → 82,7
char *m_mem, *m_pmem, *m_otp, *m_lockregs; |
int m_last_sck; |
unsigned m_write_count, m_ireg, m_oreg, m_sreg, m_addr, |
m_count, m_vconfig, m_mode_byte, m_creg, |
m_count, m_config, m_mode_byte, m_creg, |
m_nvconfig, m_evconfig, m_flagreg, m_nxtout[4]; |
bool m_quad_mode, m_debug, m_otp_wp; |
|
bench/cpp
Property changes :
Deleted: svn:ignore
## -1,2 +0,0 ##
-eqspiflash_tb
-obj-pc
Index: rtl/eqspiflash.v
===================================================================
--- rtl/eqspiflash.v (revision 14)
+++ rtl/eqspiflash.v (revision 13)
@@ -63,8 +63,7 @@
// Attempted reads before buffer is full will stall bus until
// buffer is read. Writes act like the asynch-Read-ID command,
// and will cause the controller to read the buffer.
-// 13. Reset Enable
-// 14. Reset Memory
+// 13.-14. Unused, mapped to Asynch-read-ID
// 15. OTP control word
// Write zero to permanently lock OTP
// Read to determine if OTP is permanently locked
@@ -179,7 +178,7 @@
bus_pipewr, bus_endwr, bus_ctreq, bus_idreq,
bus_other_req,
// Live parameters
- w_xip, w_quad, w_idloaded, w_leave_xip;
+ w_xip, w_quad, w_idloaded;
reg bus_wip;
qspibus preproc(i_clk_200mhz, i_rst,
i_wb_cyc, i_wb_data_stb, i_wb_ctrl_stb,
@@ -219,7 +218,7 @@
rd_spi_spd, rd_spi_dir, rd_spi_recycle,
spi_out, spi_valid,
spi_busy, spi_stopped, rd_data_ack, rd_data,
- w_quad, w_xip, w_leave_xip);
+ w_quad, w_xip);
//
// Write/Erase flash module
@@ -269,12 +268,12 @@
wire [1:0] ct_spi_len;
//
ctrlspi ctproc(i_clk_200mhz,
- bus_ctreq, bus_wr, bus_addr[3:0], bus_data, bus_sector,
+ bus_ctreq, bus_wr, bus_addr[2:0], bus_data, bus_sector,
ct_qspi_req, ct_grant,
ct_spi_wr, ct_spi_hold, ct_spi_word, ct_spi_len,
ct_spi_spd, ct_spi_dir,
spi_out, spi_valid, spi_busy, spi_stopped,
- ct_ack, ct_data_ack, ct_data, w_leave_xip, w_xip, w_quad);
+ ct_ack, ct_data_ack, ct_data, w_xip, w_quad);
assign ct_spi_hold = 1'b0;
assign ct_spi_spd = 1'b0;
@@ -505,8 +504,6 @@
||(pending)&&(ctreg_stb)&&(~lcl_ack)&&(~i_ack);
if (~o_wb_stall)
begin // Bus command accepted!
- if (i_data_stb)
- next_addr <= i_addr + 22'h1;
if ((i_data_stb)||(i_ctrl_stb))
begin
pending <= 1'b1;
@@ -513,6 +510,7 @@
o_addr <= i_addr;
o_data <= i_data;
o_wr <= i_we;
+ next_addr <= i_addr + 22'h1;
end
if ((i_data_stb)&&(~i_we))
@@ -531,14 +529,14 @@
5'h5: lcl_ctreq <= 1'b1;
5'h6: lcl_ctreq <= 1'b1;
5'h7: lcl_ctreq <= 1'b1;
- 5'h8: o_idreq <= 1'b1; // ID[0]
- 5'h9: o_idreq <= 1'b1; // ID[1]
- 5'ha: o_idreq <= 1'b1; // ID[2]
- 5'hb: o_idreq <= 1'b1; // ID[3]
- 5'hc: o_idreq <= 1'b1; // ID[4]
- 5'hd: lcl_ctreq <= 1'b1; //
- 5'he: lcl_ctreq <= 1'b1;
- 5'hf: o_idreq <= 1'b1; // Program OTP register
+ 5'h8: o_idreq <= 1'b1; // ID[0]
+ 5'h9: o_idreq <= 1'b1; // ID[1]
+ 5'ha: o_idreq <= 1'b1; // ID[2]
+ 5'hb: o_idreq <= 1'b1; // ID[3]
+ 5'hc: o_idreq <= 1'b1; // ID[4]
+ 5'hd: o_idreq <= 1'b1; //
+ 5'he: o_idreq <= 1'b1;
+ 5'hf: o_idreq <= 1'b1; // Program OTP register
default: begin o_idreq <= 1'b1; end
endcase
end else if (i_ctrl_stb)
@@ -561,9 +559,9 @@
lcl_wrreq <= 1'b0;
end
- if ((i_data_stb)&&((~o_wb_stall)||(i_ack)))
- o_piperd <= ((~i_we)&&(pipeable)&&(i_addr == next_addr));
- else if ((i_ack)&&(~i_data_stb))
+ if ((i_data_stb)&&(~o_wb_stall))
+ o_piperd <= ((~i_we)&&(~o_wb_stall)&&(pipeable)&&(i_addr == next_addr));
+ else if ((i_ack)||(((i_ctrl_stb)||(i_data_stb))&&(~o_wb_stall)))
o_piperd <= 1'b0;
if ((i_data_stb)&&(~o_wb_stall))
pipeable <= (~i_we);
@@ -583,7 +581,6 @@
wire new_req;
assign new_req = (pending)&&(~last_pending);
- initial esector = 15'h00;
initial o_wrreq = 1'b0;
initial o_erreq = 1'b0;
initial wp_err = 1'b0;
@@ -615,9 +612,9 @@
begin
esector[13:0] <= { o_data[23:14], 4'h0 };
wp <= (o_data[30])&&(new_req)||(wp)&&(~new_req);
- esector[14] <= o_data[28]; // Subsector
if (o_data[28])
begin
+ esector[14] <= o_data[28];
esector[3:0] <= o_data[13:10];
end
end
@@ -704,7 +701,7 @@
o_spi_wr, o_spi_hold, o_spi_word, o_spi_len,
o_spi_spd, o_spi_dir, o_spi_recycle,
i_spi_data, i_spi_valid, i_spi_busy, i_spi_stopped,
- o_data_ack, o_data, i_quad, i_xip, o_leave_xip);
+ o_data_ack, o_data, i_quad, i_xip);
input i_clk;
input i_readreq, i_piperd, i_other_req;
input [21:0] i_addr;
@@ -720,7 +717,6 @@
output reg o_data_ack;
output reg [31:0] o_data;
input i_quad, i_xip;
- output wire o_leave_xip;
reg accepted;
initial accepted = 1'b0;
@@ -790,13 +786,13 @@
rd_state <= `RD_GO_TO_IDLE;
end
`RD_QUAD_READ_DATA: begin
- o_qspi_req <= 1'b1; // Insist that we keep the port
- o_spi_dir <= 1'b1; // Read
- o_spi_spd <= 1'b1; // Read at Quad rates
- o_spi_len <= 2'b11; // Read 4-bytes
+ o_qspi_req <= 1'b1;
+ o_spi_dir <= 1'b1;
+ o_spi_spd <= 1'b1;
+ o_spi_len <= 2'b11;
o_spi_recycle <= (r_leave_xip)? 1'b1: 1'b0;
invalid_ack_pipe[0] <= (!r_requested);
- r_requested <= (r_requested)||(accepted); // Make sure at least one request goes through
+ r_requested <= (r_requested)||(accepted);
o_data_ack <= (!invalid_ack_pipe[3])&&(i_spi_valid)&&(r_requested)&&(~r_leave_xip);
o_bus_ack <= (r_requested)&&(accepted)&&(i_piperd)&&(~r_leave_xip);
o_spi_wr <= (~r_requested)||(i_piperd);
@@ -872,7 +868,6 @@
end
assign o_spi_hold = 1'b0;
- assign o_leave_xip = r_leave_xip;
endmodule
@@ -1124,13 +1119,12 @@
o_spi_spd, o_spi_dir,
i_spi_data, i_spi_valid, i_spi_busy,
i_spi_stopped,
- o_bus_ack, o_data_ack, o_data,
- i_leave_xip, o_xip, o_quad);
+ o_bus_ack, o_data_ack, o_data, o_xip, o_quad);
input i_clk;
// From the WB bus controller
input i_req;
input i_wr;
- input [3:0] i_addr;
+ input [2:0] i_addr;
input [31:0] i_data;
input [21:0] i_sector_address;
// To/from the arbiter
@@ -1150,7 +1144,6 @@
output reg o_bus_ack, o_data_ack;
output reg [31:0] o_data;
// Configuration items that we may have configured.
- input wire i_leave_xip;
output reg o_xip;
output wire o_quad;
@@ -1188,13 +1181,13 @@
ctcmd_len <= 2'b00; // 8bit command (for all but Lock regs)
r_ctdat_len <= 1'b0; // 8bit data (read or write)
ctdat_wr <= i_wr;
- casez({ i_addr[3:0], i_wr, i_data[30] })
- 6'b000010: begin // Write Disable
+ casez({ i_addr[2:0], i_wr, i_data[30] })
+ 5'b00010: begin // Write Disable
ctcmd_word[31:24] <= 8'h04;
ctdat_skip <= 1'b1;
ctbus_ack <= 1'b0;
end
- 6'b000011: begin // Write enable
+ 5'b00011: begin // Write enable
ctcmd_word[31:24] <= 8'h06;
ctdat_skip <= 1'b1;
ctbus_ack <= 1'b0;
@@ -1201,7 +1194,7 @@
end
// 4'b0010?: begin // Read Status register
// Moved to defaults section
- 6'b00011?: begin // Write Status register (Requires WEL)
+ 5'b0011?: begin // Write Status register (Requires WEL)
ctcmd_word[31:24] <= 8'h01;
`ifdef CT_SAFE
ctdat_word <= { 6'h00, i_data[1:0], 24'h00 };
@@ -1209,11 +1202,11 @@
ctdat_word <= { i_data[7:0], 24'h00 };
`endif
end
- 6'b00100?: begin // Read NV-Config register (two bytes)
+ 5'b0100?: begin // Read NV-Config register (two bytes)
ctcmd_word[31:24] <= 8'hB5;
r_ctdat_len <= 1'b1; // 16-bit data
end
- 6'b00101?: begin // Write NV-Config reg (2 bytes, Requires WEL)
+ 5'b0101?: begin // Write NV-Config reg (2 bytes, Requires WEL)
ctcmd_word[31:24] <= 8'hB1;
r_ctdat_len <= 1'b1; // 16-bit data
`ifdef CT_SAFE
@@ -1222,10 +1215,10 @@
ctdat_word <= { i_data[15:0], 16'h00 };
`endif
end
- 6'b00110?: begin // Read V-Config register
+ 5'b0110?: begin // Read V-Config register
ctcmd_word[31:24] <= 8'h85;
end
- 6'b00111?: begin // Write V-Config register (Requires WEL)
+ 5'b0111?: begin // Write V-Config register (Requires WEL)
ctcmd_word[31:24] <= 8'h81;
r_ctdat_len <= 1'b0; // 8-bit data
`ifdef CT_SAFE
@@ -1233,12 +1226,12 @@
`else
ctdat_word <= { i_data[7:0], 24'h00 };
`endif
- o_xip <= ~i_data[3];
+ o_xip <= i_data[3];
end
- 6'b01000?: begin // Read EV-Config register
+ 5'b1000?: begin // Read EV-Config register
ctcmd_word[31:24] <= 8'h65;
end
- 6'b01001?: begin // Write EV-Config register (Requires WEL)
+ 5'b1001?: begin // Write EV-Config register (Requires WEL)
ctcmd_word[31:24] <= 8'h61;
// o_quad <= (~i_data[7]);
`ifdef CT_SAFE
@@ -1247,32 +1240,24 @@
ctdat_word <= { i_data[7:0], 24'h00 };
`endif
end
- 6'b01010?: begin // Read Lock register
+ 5'b1010?: begin // Read Lock register
ctcmd_word[31:0] <= { 8'he8, i_sector_address, 2'b00 };
ctcmd_len <= 2'b11;
ctdat_wr <= 1'b0; // Read, not write
end
- 6'b01011?: begin // Write Lock register (Requires WEL)
+ 5'b1011?: begin // Write Lock register (Requires WEL)
ctcmd_word[31:0] <= { 8'he5, i_sector_address, 2'b00 };
ctcmd_len <= 2'b11;
ctdat_wr <= 1'b1; // Write
end
- 6'b01100?: begin // Read Flag Status register
+ 5'b1100?: begin // Read Flag Status register
ctcmd_word[31:24] <= 8'h70;
ctdat_wr <= 1'b0; // Read, not write
end
- 6'b01101?: begin // Write/Clear Flag Status register (No WEL required)
+ 5'b1101?: begin // Write/Clear Flag Status register (No WEL required)
ctcmd_word[31:24] <= 8'h50;
ctdat_skip <= 1'b1;
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
ctcmd_word[31:24] <= 8'h05;
ctdat_wr <= 1'b0; // Read, not write
@@ -1279,8 +1264,7 @@
r_ctdat_len <= 1'b0; // 8-bit data
end
endcase
- end else if (i_leave_xip)
- o_xip <= 1'b0;
+ end
assign o_quad = 1'b1;
/rtl/wbqspiflash.v
1,4 → 1,4
//////////////////////////////////////////////////////////////////////////////// |
/////////////////////////////////////////////////////////////////////////// |
// |
// Filename: wbspiflash.v |
// |
24,12 → 24,12
// (19 bits): Data (R/w, but expect writes to take a while) |
// |
// |
// Creator: Dan Gisselquist, Ph.D. |
// Creator: Dan Gisselquist |
// Gisselquist Technology, LLC |
// |
//////////////////////////////////////////////////////////////////////////////// |
/////////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2015,2017, Gisselquist Technology, LLC |
// Copyright (C) 2015, Gisselquist Technology, LLC |
// |
// This program is free software (firmware): you can redistribute it and/or |
// modify it under the terms of the GNU General Public License as published |
42,7 → 42,7
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with this program. (It's in the $(ROOT)/doc directory. Run make with no |
// with this program. (It's in the $(ROOT)/doc directory, run make with no |
// target there if the PDF file isn't present.) If not, see |
// <http://www.gnu.org/licenses/> for a copy. |
// |
50,46 → 50,45
// http://www.gnu.org/licenses/gpl.html |
// |
// |
//////////////////////////////////////////////////////////////////////////////// |
/////////////////////////////////////////////////////////////////////////// |
// |
`include "flash_config.v" |
`default_nettype none |
// |
`define WBQSPI_RESET 5'h0 |
`define WBQSPI_RESET_QUADMODE 5'h1 |
`define WBQSPI_IDLE 5'h2 |
`define WBQSPI_RDIDLE 5'h3 // Idle, but in fast read mode |
`define WBQSPI_WBDECODE 5'h4 |
`define WBQSPI_RD_DUMMY 5'h5 |
`define WBQSPI_QRD_ADDRESS 5'h6 |
`define WBQSPI_QRD_DUMMY 5'h7 |
`define WBQSPI_READ_CMD 5'h8 |
`define WBQSPI_READ_DATA 5'h9 |
`define WBQSPI_WAIT_TIL_RDIDLE 5'h10 |
`define WBQSPI_READ_ID_CMD 5'h11 |
`define WBQSPI_READ_ID 5'h12 |
`define WBQSPI_READ_STATUS 5'h13 |
`define WBQSPI_READ_CONFIG 5'h14 |
`define WBQSPI_WAIT_TIL_IDLE 5'h15 |
`define WBQSPI_RESET 0 |
`define WBQSPI_RESET_QUADMODE 1 |
`define WBQSPI_IDLE 2 |
`define WBQSPI_RDIDLE 3 // Idle, but in fast read mode |
`define WBQSPI_WBDECODE 4 |
`define WBQSPI_RD_DUMMY 5 |
`define WBQSPI_QRD_ADDRESS 6 |
`define WBQSPI_QRD_DUMMY 7 |
`define WBQSPI_READ_CMD 8 |
`define WBQSPI_READ_DATA 9 |
`define WBQSPI_WAIT_TIL_RDIDLE 10 |
`define WBQSPI_READ_ID_CMD 11 |
`define WBQSPI_READ_ID 12 |
`define WBQSPI_READ_STATUS 13 |
`define WBQSPI_READ_CONFIG 14 |
`define WBQSPI_WAIT_TIL_IDLE 15 |
// |
// |
`ifndef READ_ONLY |
// |
`define WBQSPI_WAIT_WIP_CLEAR 5'h16 |
`define WBQSPI_CHECK_WIP_CLEAR 5'h17 |
`define WBQSPI_CHECK_WIP_DONE 5'h18 |
`define WBQSPI_WEN 5'h19 |
`define WBQSPI_PP 5'h20 // Program page |
`define WBQSPI_QPP 5'h21 // Program page, 4 bit mode |
`define WBQSPI_WR_DATA 5'h22 |
`define WBQSPI_WR_BUS_CYCLE 5'h23 |
`define WBQSPI_WRITE_STATUS 5'h24 |
`define WBQSPI_WRITE_CONFIG 5'h25 |
`define WBQSPI_ERASE_WEN 5'h26 |
`define WBQSPI_ERASE_CMD 5'h27 |
`define WBQSPI_ERASE_BLOCK 5'h28 |
`define WBQSPI_CLEAR_STATUS 5'h29 |
`define WBQSPI_IDLE_CHECK_WIP 5'h30 |
`define WBQSPI_WAIT_WIP_CLEAR 16 |
`define WBQSPI_CHECK_WIP_CLEAR 17 |
`define WBQSPI_CHECK_WIP_DONE 18 |
`define WBQSPI_WEN 19 |
`define WBQSPI_PP 20 // Program page |
`define WBQSPI_QPP 21 // Program page, 4 bit mode |
`define WBQSPI_WR_DATA 22 |
`define WBQSPI_WR_BUS_CYCLE 23 |
`define WBQSPI_WRITE_STATUS 24 |
`define WBQSPI_WRITE_CONFIG 25 |
`define WBQSPI_ERASE_WEN 26 |
`define WBQSPI_ERASE_CMD 27 |
`define WBQSPI_ERASE_BLOCK 28 |
`define WBQSPI_CLEAR_STATUS 29 |
`define WBQSPI_IDLE_CHECK_WIP 30 |
// |
`endif |
|
103,11 → 102,11
o_qspi_sck, o_qspi_cs_n, o_qspi_mod, o_qspi_dat, i_qspi_dat, |
o_interrupt); |
parameter ADDRESS_WIDTH=22; |
input wire i_clk_100mhz; |
input i_clk_100mhz; |
// Wishbone, inputs first |
input wire i_wb_cyc, i_wb_data_stb, i_wb_ctrl_stb, i_wb_we; |
input wire [(ADDRESS_WIDTH-3):0] i_wb_addr; |
input wire [31:0] i_wb_data; |
input i_wb_cyc, i_wb_data_stb, i_wb_ctrl_stb, i_wb_we; |
input [(ADDRESS_WIDTH-3):0] i_wb_addr; |
input [31:0] i_wb_data; |
// then outputs |
output reg o_wb_ack; |
output reg o_wb_stall; |
116,7 → 115,7
output wire o_qspi_sck, o_qspi_cs_n; |
output wire [1:0] o_qspi_mod; |
output wire [3:0] o_qspi_dat; |
input wire [3:0] i_qspi_dat; |
input [3:0] i_qspi_dat; |
// Interrupt line |
output reg o_interrupt; |
// output wire [31:0] o_debug; |
147,29 → 146,12
write_protect = 1'b1; |
end |
|
wire [23:0] w_wb_addr; |
generate |
if (ADDRESS_WIDTH>=24) |
assign w_wb_addr = { i_wb_addr[21:0], 2'b00 }; |
else |
assign w_wb_addr = { {(24-ADDRESS_WIDTH){1'b0}}, i_wb_addr, 2'b00 }; |
endgenerate |
|
// Repeat for spif_addr |
reg [(ADDRESS_WIDTH-3):0] spif_addr; |
wire [23:0] w_spif_addr; |
generate |
if (ADDRESS_WIDTH>=24) |
assign w_spif_addr = { spif_addr[21:0], 2'b00 }; |
else |
assign w_spif_addr = { {(24-ADDRESS_WIDTH){1'b0}}, spif_addr, 2'b00 }; |
endgenerate |
|
reg [7:0] last_status; |
reg quad_mode_enabled; |
reg spif_cmd, spif_override; |
reg [(ADDRESS_WIDTH-3):0] spif_addr; |
reg [31:0] spif_data; |
reg [4:0] state; |
reg [5:0] state; |
reg spif_ctrl, spif_req; |
wire [(ADDRESS_WIDTH-17):0] spif_sector; |
assign spif_sector = spif_addr[(ADDRESS_WIDTH-3):14]; |
211,9 → 193,7
begin |
// Okay, so here's the problem: we don't know whether or not |
// the Xilinx loader started us up in Quad Read I/O idle mode. |
// So, thus we need to toggle the clock and CS_n, with fewer |
// clocks than are necessary to transmit a word. |
// |
// So, thus we need to |
// Not ready to handle the bus yet, so stall any requests |
o_wb_ack <= 1'b0; |
o_wb_stall <= 1'b1; |
244,7 → 224,7
spi_spd <= 1'b0; |
spi_dir <= 1'b0; // Write (for now, 'cause of cmd) |
// Data register access |
if (i_wb_data_stb) |
if ((i_wb_data_stb)&&(i_wb_cyc)) |
begin |
|
if (i_wb_we) // Request to write a page |
285,11 → 265,15
spi_wr <= 1'b1; // Write cmd to device |
if (quad_mode_enabled) |
begin |
spi_in <= { 8'heb, w_wb_addr }; |
spi_in <= { 8'heb, |
{(24-ADDRESS_WIDTH){1'b0}}, |
i_wb_addr[(ADDRESS_WIDTH-3):0], 2'b00 }; |
state <= `WBQSPI_QRD_ADDRESS; |
spi_len <= 2'b00; // single byte, cmd only |
end else begin |
spi_in <= { 8'h0b, w_wb_addr }; |
spi_in <= { 8'h0b, |
{(24-ADDRESS_WIDTH){1'b0}}, |
i_wb_addr[(ADDRESS_WIDTH-3):0], 2'b00 }; |
state <= `WBQSPI_RD_DUMMY; |
spi_len <= 2'b11; // cmd+addr,32bits |
end |
302,7 → 286,7
o_wb_stall <= 1'b1; |
`endif |
end |
end else if ((i_wb_ctrl_stb)&&(i_wb_we)) |
end else if ((i_wb_cyc)&&(i_wb_ctrl_stb)&&(i_wb_we)) |
begin |
`ifdef READ_ONLY |
o_wb_ack <= 1'b1; |
368,7 → 352,7
end |
endcase |
`endif |
end else if (i_wb_ctrl_stb) // &&(~i_wb_we)) |
end else if ((i_wb_cyc)&&(i_wb_ctrl_stb)) // &&(~i_wb_we)) |
begin |
case(i_wb_addr[1:0]) |
2'b00: begin // Read local register |
444,14 → 428,15
spi_hold <= 1'b0; |
spi_spd<= 1'b1; |
spi_dir <= 1'b0; // Write (for now) |
if ((i_wb_data_stb)&&(~i_wb_we)) |
if ((i_wb_cyc)&&(i_wb_data_stb)&&(~i_wb_we)) |
begin // Continue our read ... send the new address / mode |
o_wb_stall <= 1'b1; |
spi_wr <= 1'b1; |
spi_len <= 2'b10; // Write address, but not mode byte |
spi_in <= { w_wb_addr, 8'ha0 }; |
spi_in <= { {(24-ADDRESS_WIDTH){1'b0}}, |
i_wb_addr[(ADDRESS_WIDTH-3):0], 2'b00, 8'ha0 }; |
state <= `WBQSPI_QRD_DUMMY; |
end else if((i_wb_ctrl_stb)&&(~i_wb_we)&&(i_wb_addr[1:0] == 2'b00)) |
end else if((i_wb_cyc)&&(i_wb_ctrl_stb)&&(~i_wb_we)&&(i_wb_addr[1:0] == 2'b00)) |
begin |
// A local read that doesn't touch the device, so leave |
// the device in its current state |
463,7 → 448,7
quad_mode_enabled, |
{(29-ADDRESS_WIDTH){1'b0}}, |
erased_sector, 14'h000 }; |
end else if(((i_wb_ctrl_stb)||(i_wb_data_stb))) |
end else if((i_wb_cyc)&&((i_wb_ctrl_stb)||(i_wb_data_stb))) |
begin // Need to release the device from quad mode for all else |
o_wb_ack <= 1'b0; |
o_wb_stall <= 1'b1; |
660,7 → 645,8
o_wb_stall <= 1'b1; |
|
spi_wr <= 1'b1; // Non-stop |
spi_in <= { w_spif_addr, 8'ha0 }; |
spi_in <= { {(24-ADDRESS_WIDTH){1'b0}}, |
spif_addr[(ADDRESS_WIDTH-3):0], 2'b00, 8'ha0 }; |
spi_len <= 2'b10; // Write address, not mode byte |
spi_spd <= 1'b1; |
spi_dir <= 1'b0; // Still writing |
702,7 → 688,7
end else if (state == `WBQSPI_READ_DATA) |
begin |
// Pipelined read support |
spi_wr <=((i_wb_data_stb)&&(~i_wb_we)&&(i_wb_addr== (spif_addr+1))); |
spi_wr <=((i_wb_cyc)&&(i_wb_data_stb)&&(~i_wb_we)&&(i_wb_addr== (spif_addr+1))); |
spi_in <= 32'h00; |
spi_len <= 2'b11; |
// Don't adjust the speed here, it was set in the setup |
726,7 → 712,8
o_wb_ack <= spif_req; |
o_wb_stall <= (~spi_wr); |
// adjust endian-ness to match the PC |
o_wb_data <= spi_out; |
o_wb_data <= { spi_out[7:0], spi_out[15:8], |
spi_out[23:16], spi_out[31:24] }; |
state <= (spi_wr)?`WBQSPI_READ_DATA |
: ((spi_spd) ? `WBQSPI_WAIT_TIL_RDIDLE : `WBQSPI_WAIT_TIL_IDLE); |
spif_req <= spi_wr; |
913,11 → 900,15
spi_wr <= 1'b1; // Write cmd to device |
if (quad_mode_enabled) |
begin |
spi_in <= { 8'heb, w_spif_addr }; |
spi_in <= { 8'heb, |
{(24-ADDRESS_WIDTH){1'b0}}, |
spif_addr[(ADDRESS_WIDTH-3):0], 2'b00 }; |
state <= `WBQSPI_QRD_ADDRESS; |
// spi_len <= 2'b00; // single byte, cmd only |
end else begin |
spi_in <= { 8'h0b, w_spif_addr }; |
spi_in <= { 8'h0b, |
{(24-ADDRESS_WIDTH){1'b0}}, |
spif_addr[(ADDRESS_WIDTH-3):0], 2'b00 }; |
state <= `WBQSPI_RD_DUMMY; |
spi_len <= 2'b11; // Send cmd and addr |
end end |
965,7 → 956,9
begin // We come here under a full stop / full port idle mode |
// Issue our command immediately |
spi_wr <= 1'b1; |
spi_in <= { 8'h02, w_spif_addr }; |
spi_in <= { 8'h02, |
{(24-ADDRESS_WIDTH){1'b0}}, |
spif_addr[(ADDRESS_WIDTH-3):0], 2'b00 }; |
spi_len <= 2'b11; |
spi_hold <= 1'b1; |
spi_spd <= 1'b0; |
981,7 → 974,9
begin // We come here under a full stop / full port idle mode |
// Issue our command immediately |
spi_wr <= 1'b1; |
spi_in <= { 8'h32, w_spif_addr }; |
spi_in <= { 8'h32, |
{(24-ADDRESS_WIDTH){1'b0}}, |
spif_addr[(ADDRESS_WIDTH-3):0], 2'b00 }; |
spi_len <= 2'b11; |
spi_hold <= 1'b1; |
spi_spd <= 1'b0; |
1004,7 → 999,11
o_wb_stall <= 1'b1; |
o_wb_ack <= 1'b0; |
spi_wr <= 1'b1; // write without waiting |
spi_in <= spif_data; |
spi_in <= { |
spif_data[ 7: 0], |
spif_data[15: 8], |
spif_data[23:16], |
spif_data[31:24] }; |
spi_len <= 2'b11; // Write 4 bytes |
spi_hold <= 1'b1; |
if (~spi_busy) |
/rtl/llqspi.v
37,10 → 37,6
// |
// |
/////////////////////////////////////////////////////////////////////////// |
// |
// |
`default_nettype none |
// |
`define QSPI_IDLE 3'h0 |
`define QSPI_START 3'h1 |
`define QSPI_BITS 3'h2 |
60,17 → 56,17
o_word, o_valid, o_busy, |
// QSPI interface |
o_sck, o_cs_n, o_mod, o_dat, i_dat); |
input wire i_clk; |
input i_clk; |
// Chip interface |
// Can send info |
// i_dir = 1, i_spd = 0, i_hold = 0, i_wr = 1, |
// i_word = { 1'b0, 32'info to send }, |
// i_len = # of bytes in word-1 |
input wire i_wr, i_hold; |
input wire [31:0] i_word; |
input wire [1:0] i_len; // 0=>8bits, 1=>16 bits, 2=>24 bits, 3=>32 bits |
input wire i_spd; // 0 -> normal QPI, 1 -> QSPI |
input wire i_dir; // 0 -> read, 1 -> write to SPI |
input i_wr, i_hold; |
input [31:0] i_word; |
input [1:0] i_len; // 0=>8bits, 1=>16 bits, 2=>24 bits, 3=>32 bits |
input i_spd; // 0 -> normal QPI, 1 -> QSPI |
input i_dir; // 0 -> read, 1 -> write to SPI |
output reg [31:0] o_word; |
output reg o_valid, o_busy; |
// Interface with the QSPI lines |
rtl
Property changes :
Deleted: svn:ignore
## -1 +0,0 ##
-obj_dir
Index: doc/spec.pdf
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: doc/src/spec.tex
===================================================================
--- doc/src/spec.tex (revision 14)
+++ doc/src/spec.tex (revision 13)
@@ -45,7 +45,7 @@
\title{Specification}
\author{Dan Gisselquist, Ph.D.}
\email{dgisselq (at) opencores.org}
-\revision{Rev.~0.3}
+\revision{Rev.~0.2}
\begin{document}
\pagestyle{gqtekspecplain}
\titlepage
@@ -67,7 +67,6 @@
copy.
\end{license}
\begin{revisionhistory}
-0.3 & 8/11/2016 & Gisselquist & Added information on the Extended Quad SPI controller\\\hline
0.2 & 5/26/2015 & Gisselquist & Minor spelling changes\\\hline
0.1 & 5/13/2015 & Gisselquist & First Draft \\\hline
\end{revisionhistory}
@@ -82,12 +81,6 @@
JTAG cables, or other proprietary loading capabilities such as Digilent's
Adept program. As a result, all interactions with the board need to take
place using open source tools, and the board must be able to reprogram itself.
-
-That was the beginning of the QSPI flash controller.
-
-The EQSPI flash controller started from a similar need for a board that had
-an EQSPI flash. That particular board was an Arty, and so the EQSPI flash
-controller has been designed around the Arty platform.
\end{preface}
\chapter{Introduction}
@@ -94,55 +87,39 @@
\pagenumbering{arabic}
\setcounter{page}{1}
-This document discusses the design and usage of two cores: a Quad SPI flash
-controller, and a newer Extended Quad SPI flash controller. In general, the
-two are {\em very} similar. However, their construction and register usage
-are subtly different, so the user will need to pay attention to these
-differences.
-
-Both Flash controllers handle all of the necessary queries and accesses to
+The Quad SPI Flash controller handles all necessary queries and accesses to
and from a SPI Flash device that has been augmented with an additional
two data lines and enabled with a mode allowing all four data lines to
work together in the same direction at the same time. Since the interface
was derived from a SPI interface, most of the interaction takes place using
normal SPI protocols and only some commands work at the higher four bits
-at a time speed. This remains true, even though the newer Extended SPI flash
-controller allows control accesses and Dual I/O and Quad I/O speeds: control
-interactions remain at SPI speeds, and only data reads and writes take place
-at the Quad I/O speed.
+at a time speed.
-Both controllers attempt to mask the underlying operation of the
-Flash device behind a wishbone interface, to make it so that reads and writes
+This particular controller attempts to mask the underlying operation of the
+SPI device behind a wishbone interface, to make it so that reads and writes
are as simple as using the wishbone interface. However, the difference
between erasing (turning bits from '0' to '1') and programming (turning bits
from '1' to '0') breaks this model somewhat. Therefore, reads from the
-device act like normal wishbone reads, writes program the device (if the write
-protect is properly removed) and sort of work with the wishbone, while erase
-commands require another register to control. Please read the Operations
-chapter for a detailed description of how to perform these relevant operations.
+device act like normal wishbone reads, writes program the device and
+sort of work with the wishbone, while erase commands require another register
+to control. Please read the Operations chapter for a detailed description
+of how to perform these relevant operations.
-This QSPI controller implements the interface for the Quad SPI flash found on
-the Basys-3 board built by Digilent, Inc, as well as their CMod-S6 board. A
-similar controller has been modified for the flash on the XuLA2-LX25 SoC.
-It is possible that some portions of the interface may be specific to the
-Spansion S25FL032P chip used on the Basys-3 board, and the
+This controller implements the interface for the Quad SPI flash found on the
+Basys-3 board built by Digilent, Inc. Some portions of the interface may
+be specific to the Spansion S25FL032P chip used on this board, and the
100~MHz system clock found on the board, although there is no reason the
controller needs to be limited to this architecture. It just happens to be
-the one the QSPI controller was designed to and for.
+the one I have been designing to and for.
-The Extended QSPI controller, or EQSPI controller, was designed to control the
-Micron Serial NOR Flash Memory, N25Q128A, found on Digilent's Arty board. As
-with the Spansion chip, it is possible that parts of the interface are specific
-to this board and this chip.
-
-For a description of how the internal of each core work, feel free to browse
+For a description of how the internals of this core work, feel free to browse
through the Architecture chapter.
-The registers that control the cores are discussed in the Registers chapter.
+The registers that control this core are discussed in the Registers chapter.
As required, you can find a wishbone datasheet in Chapt.~\ref{chap:wishbone}.
-The final pertinent information for implementing the cores is found in the
+The final pertinent information for implementing this core is found in the
I/O Ports chapter, Chapt.~\ref{chap:ioports}.
As always, write me if you have any questions or problems.
@@ -149,20 +126,12 @@
\chapter{Architecture}\label{chap:arch}
-The internal architecture of each of these two cores is different, reflecting
-their different chips and goals. The QSPI controller is designed to run using
-a 50~MHz SPI clock, generated from a 100~MHz controller clock. The EQSPI
-controller, however, was designed to prove that a 100~MHz SPI clock could be
-used to drive a flash controller from a 200~MHz controller clock. As a result
-of these clocking differences, the architectures of each are quite different.
-
-\section{QSPI Flash Architecture}
As built, the core consists of only two components: the wishbone quad SPI
flash controller, {\tt wbqspiflash}, and the lower level quad SPI driver,
{\tt llqspi}. The controller issues high level read/write commands to the
lower level driver, which actually implements the Quad SPI protocol.
-Pictorally, this looks something like Fig.~\ref{fig:qspi-arch}.
+Pictorally, this looks something like Fig.~\ref{fig:arch}.
\begin{figure}\begin{center}\begin{pspicture}(-2in,0)(2in,3.5in)
\rput(0,2.5in){
\rput(-0.9in,0){\psline{->}(0,1in)(0,0in)}
@@ -217,7 +186,7 @@
\psline{<->}(0.3in,0.5in)(0.3in,0)}
\rput[l](0.4in,0.25in){Quad SPI I/O lines}
\end{pspicture}\end{center}
-\caption{QSPI Architecture Diagram}\label{fig:qspi-arch}
+\caption{Architecture Diagram}\label{fig:arch}
\end{figure}
This is also what you will find if you browse through the code.
@@ -278,192 +247,14 @@
while the higher level driver maintains the state machine controlling which
commands need to be issued and when.
-\section{EQSPI Flash Architecture}
-The EQSPI flash architecture was an entire redesign. The reason for the
-redesign is quite simple: the QSPI flash controller was just way to complex
-to run at a 200~MHz clock. This new and modified architecture is shown in
-Fig.~\ref{fig:eqspi-arch}.
-\begin{figure}\begin{center}\begin{pspicture}(-2in,-1.2in)(2.75in,5.5in)
-% \rput(0,0){\psframe(-2in,-1.2in)(2.75in,5.5in)}
-\rput(0,4.5in){%
- \rput(-0.9in,0){\psline{->}(0,1in)(0,0in)}
- \rput[b]{90}(-0.92in,0.5in){\tt i\_wb\_cyc}
- \rput(-0.7in,0){\psline{->}(0,1in)(0,0in)}
- \rput[b]{90}(-0.72in,0.5in){\tt i\_wb\_data\_stb}
- \rput(-0.5in,0){\psline{->}(0,1in)(0,0in)}
- \rput[b]{90}(-0.52in,0.5in){\tt i\_wb\_ctrl\_stb}
- \rput(-0.3in,0){\psline{->}(0,1in)(0,0in)}
- \rput[b]{90}(-0.32in,0.5in){\tt i\_wb\_we}
- \rput(-0.1in,0){\psline{->}(0,1in)(0,0in)}
- \rput[b]{90}(-0.12in,0.5in){\tt i\_wb\_addr}
- \rput( 0.1in,0){\psline{->}(0,1in)(0,0in)}
- \rput[b]{90}( 0.08in,0.5in){\tt i\_wb\_data}
- %
- \rput( 0.5in,0){\psline{<-}(0,1in)(0,0in)}
- \rput[b]{90}( 0.48in,0.5in){\tt o\_wb\_ack}
- \rput( 0.7in,0){\psline{<-}(0,1in)(0,0in)}
- \rput[b]{90}( 0.68in,0.5in){\tt o\_wb\_stall}
- \rput( 0.9in,0){\psline{<-}(0,1in)(0,0in)}
- \rput[b]{90}( 0.88in,0.5in){\tt o\_wb\_data}
- \rput( 1.1in,0){\psline{<-}(0,1in)(0,0in)}
- \rput[b]{90}( 1.08in,0.5in){\tt o\_int}}
-\rput(0,4.0in){%
- \rput(0,0){\psframe(-1.2in,0)(1.2in,0.5in)}
- \rput(0,0.25in){\tt qspibus}}
- % Wires
-\rput(0,3.0in){%
- \rput(0,0){\psframe(-2in,0)(-1.05in,0.5in)}
- \rput(-1.5in,0.25in){\tt readqspi}}
-\rput(0,3.0in){%
- \rput(0,0){\psframe(-0.95in,0)(-0.05in,0.5in)}
- \rput(-0.5in,0.25in){\tt writeqspi}}
-\rput(0,3.0in){%
- \rput(0,0){\psframe(0.05in,0)(0.95in,0.5in)}
- \rput(0.5in,0.25in){\tt ctrlspi}}
-\rput(0,3.0in){%
- \rput(0,0){\psframe(1.05in,0)(2in,0.5in)}
- \rput(1.5in,0.25in){\tt idotpqspi}}
-\rput(0,2.0in){%
- \rput(0,0){\pspolygon(-1in,0)(1in,0)(1.5in,0.5in)(-1.5in,0.5in)}
- \rput(0,0.25in){Command Mux}}
-\rput(0,1.0in){
- \rput(-1.0in,0){\psline{->}(0,1in)(0,0in)}
- \rput[b]{90}(-1.02in,0.5in){\tt spi\_wr}
- \rput(-0.8in,0){\psline{->}(0,1in)(0,0in)}
- \rput[b]{90}(-0.82in,0.5in){\tt spi\_hold}
- \rput(-0.6in,0){\psline{->}(0,1in)(0,0in)}
- \rput[b]{90}(-0.62in,0.5in){\tt spi\_in}
- \rput(-0.4in,0){\psline{->}(0,1in)(0,0in)}
- \rput[b]{90}(-0.42in,0.5in){\tt spi\_len}
- \rput(-0.2in,0){\psline{->}(0,1in)(0,0in)}
- \rput[b]{90}(-0.22in,0.5in){\tt spi\_spd}
- \rput( 0.0in,0){\psline{->}(0,1in)(0,0in)}
- \rput[b]{90}(-0.02in,0.5in){\tt spi\_dir}
- \rput( 0.2in,0){\psline{->}(0,1in)(0,0in)}
- \rput[b]{90}( 0.18in,0.5in){\tt spi\_word}
- \rput( 0.6in,0){\psline{<-}(0,1in)(0,0in)}
- \rput[b]{90}( 0.58in,0.5in){\tt spi\_out}
- \rput( 0.8in,0){\psline{<-}(0,1in)(0,0in)}
- \rput[b]{90}( 0.78in,0.5in){\tt spi\_valid}
- \rput( 1.0in,0){\psline{<-}(0,1in)(0,0in)}
- \rput[b]{90}( 0.98in,0.5in){\tt spi\_busy}}
-\rput(0,0.5in){
- \rput(0,0){\psframe(-1.25in,0)(1.25in,0.5in)}
- \rput(0,0.25in){\tt lleqspi}}
- \rput(0,0){
- \rput[b]{90}(-1.02in,0.25in){\tt bmod}
- \psline{->}(-1.0in,0.5in)(-1.0in,-0.35in)(-0.7in,-0.35in)
- \psline{->}(-0.5in,-0.35in)(-0.3in,-0.35in)
- \psline{->}(-0.1in,-0.35in)( 0.1in,-0.35in)
- \psline{->}( 0.3in,-0.35in)( 0.5in,-0.35in)
- \psline{<->}(-0.6in,0.5in)(-0.6in,0)
- \rput[b]{90}(-0.62in,0.25in){\tt dat[0]}
- \psline{<->}(-0.2in,0.5in)(-0.2in,0)
- \rput[b]{90}(-0.22in,0.25in){\tt dat[1]}
- \psline{<->}(0.2in,0.5in)(0.2in,0)
- \rput[b]{90}(0.18in,0.25in){\tt dat[2]}
- \psline{<->}(0.6in,0.5in)(0.6in,0)
- \rput[b]{90}(0.58in,0.25in){\tt dat[3]}
- \psline{->}(1.0in,0.5in)(1.0in,0)
- \rput[b]{90}(0.98in,0.25in){\tt clk/cs}}
- \rput[l](1.1in,0.25in){Top level Interface Wires}
-\rput(0,-0.7in){
- \rput(-0.6in,0){\rput(0,0){\psframe(-0.1in,0)(0.1in,0.7in)}\rput{90}(0,0.35in){\tt xioddr}}
- \rput(-0.2in,0){\rput(0,0){\psframe(-0.1in,0)(0.1in,0.7in)}\rput{90}(0,0.35in){\tt xioddr}}
- \rput( 0.2in,0){\rput(0,0){\psframe(-0.1in,0)(0.1in,0.7in)}\rput{90}(0,0.35in){\tt xioddr}}
- \rput( 0.6in,0){\rput(0,0){\psframe(-0.1in,0)(0.1in,0.7in)}\rput{90}(0,0.35in){\tt xioddr}}
- \rput( 1.0in,0){\rput(0,0){\psframe(-0.1in,0)(0.1in,0.7in)}\rput{90}(0,0.35in){\tt xioddr}}
- \rput(0,0){\psline{<->}(-0.6in,-0.5in)(-0.6in,0)
- \psline{<->}(-0.2in,-0.5in)(-0.2in,0)
- \psline{<->}(0.2in,-0.5in)(0.2in,0)
- \psline{<->}(0.6in,-0.5in)(0.6in,0)
- \psline{<-}(1.0in,-0.5in)(1.0in,0)}
- \rput[l](1.1in,-0.25in){Quad SPI I/O lines}}
-\end{pspicture}\end{center}
-\caption{EQSPI Architecture Diagram}\label{fig:eqspi-arch}
-\end{figure}
-All of the various modules of this architecture, save the {\tt lleqspi} and
-{\tt xioddr} modules, are found in the {\tt eqspiflash.v} file.
-
-The goal of this architecture was to reduce the amount of logic necessary to
-process the many various requests this controller allows.
-
-At the top, all requests to the controller come from the bus straight into the
-{\tt qspibus} module. The purpose of this module is to parse the various
-commands to their respective modules. One command, however, never gets
-parsed: the request to read from the erase register. This register returns
-the status of the controller, and particularly whether or not it is still
-busy with the last erase or write command.
-
-The top level controller has the ability to latch a bus request. Such requests
-are then issued to the lower level controllers. However, they remain latched
-in the top level controller until the lower controller acknowledges them, at
-which point the bus may advance to its next request. Depending on the lower
-level controller, this may not occurr until the lower level transaction is
-complete, or nearly so.
-
-The lower level controllers also communicate with the command multiplexer
-beneath them. Each controller has a request line, whereby it requests access
-to the lowerest level controller. Once granted, the controller maintains
-control of that lowest level until it is released. In this fashion, for
-example, the {\tt readqspi} controller implements the execute in place
-functionality: it reads from the interface, then maintains the interface.
-If another driver requests the interface, the read controller reactivates
-itself and returns the interface to a non--XIP mode.
-
-Now, of these four controllers, the {\tt readqspi} controller handles reads
-from the device. Reads are always done in Quad SPI mode, if so enabled,
-and the device is left in XIP mode until another controller requests the
-interface. XIP mode is left by reading a 32'bit value from the device at
-address zero.
-
-The {\tt writeqspi} controller handles both program and erase requests.
-Upon completion of either request, the {\tt writeqspi} controller holds on
-to the interface perpetually reading from the status register until the device
-is no longer busy.
-
-The {\tt ctrlspi} controller handles requests to read and write the various
-control registers internal to the device. These include the status register,
-the non--volatile configuration register, the volatile configuration register,
-the extended volatile configuration register, the flags register, and the
-lock registers associated with the most recently selected sector (set in the
-erase register). Writes to these registers, though, aren't quite so simple:
-One must first disable the write protect in the erase control register,
-thus setting the Write Enable Latch of the device, before the device
-will accept write requests.
-
-Finally, the {\tt idotpqspi} controller handles the logic associated with the
-ID memory internal to the controller, as well as both reading and writing the
-One Time Programmable (OTP) registers, and eventually locking the OTP registers
-so that they can no longer be read or written. As with the {\tt writeqspi}
-module, write requests do not release the port until the write has completed.
-Reading the erase register will provide the status on this operation.
-
-Moving down in the architecture to the command multiplexer, this portion is
-really not that remarkable. It takes one clock for requests to go through the
-command multiplexer and get to the lower level controller, and it grants
-and releases control to the various controllers.
-
-The {\tt lleqspi} controller is the lower level controller for this device.
-It's operation mirrors that of the {\tt llqspi} lower--level controller from
-the QSPI flash. The biggest difference is that the Micron chip requires a
-particular recovery time following any command other than a read command
-leaving the chip in the XIP mode.
-
-What is new in this controller is the requirement for the output ports to
-be connected to the I/O banks via {\tt ODDR} and {\tt IDDR} modules. These
-are contained within the {\tt xioddr} modules. Since the wires can change
-direction, the {\tt bmod} pair of wires provides an indication of which
-direction the various bits of the port are moving--either as inputs or outputs.
-
\chapter{Operation}\label{chap:ops}
This implementation attempts to encapsulate (hide) the details of the chip
from the user, so that the user does not need to know about the various
subcommands going to and from the chip. The original goal was to make the
chip act like any other read/write memory, however the difference between
-erasing and programming a flash chip made this impossible. Therefore a
-separate register is provided to control the erase any given sector, while
-reads and writes may proceed (almost) as normal.
+erasing and programming the chip made this impossible. Therefore a separate
+register is given to erase any given sector, while reads and writes may proceed
+(almost) as normal.
The wishbone bus that this controller works with, however, is a 32--bit
bus. Address one on the bus addresses a completely different 32--bit word
@@ -476,31 +267,19 @@
From a high level perspective, this core provides read/write access to the
device either via the wishbone (read and program), or through a control
register found on the wishbone (the EREG). Programming the device consists of
-first clearing the write protect, and then erasing the region of interest.
-This will set all the bits to `1' in that region. After erasing the region,
-the write protect may again be cleared, and then the region can then be
-programmed, setting some of the `1' bits to '0's. When neither erase nor
-program operation is going on, the device may be read. The section will
-describe each of those operations in detail.
+first erasing the region of interest. This will set all the bits to '1' in
+that region. After erasing the region, the region can then be programmed,
+setting some of the '1' bits to '0's. When neither erase nor program
+operation is going on, the device may be read. The section will describe
+each of those operations in detail.
To erase a sector of the device, two writes are required to the EREG register.
The first write turns off the write protect bit, whereas the second write
-commands the erase itself. The first write should equal \hbox{0x1000\_0000}
-for the QSPI controller and \hbox{0x4000\_0000} for the EQSPI controller.
-After this write, the EQSPI controller will issue a Write Enable command to the
-device. For the QSPI controller, the second write should be any address within
-the sector to be erased together with setting the high bit of the register.
-This is equivalent to setting it to \hbox{0x8000\_0000} plus the address. The
-EQSPI flash driver is subtly different in that it requires a {\em key} to erase.
-Hence, for the EQSPI flash driver, one must write \hbox{0xc000\_01be} plus the
-first address in the sector to accomplish the same result. Further, the
-EQSPI flash controller allows the erasing of 4~kB subsegments. To do this,
-the second write must also set the subsector bit, so it looks like writing
-\hbox{0xd000\_01be} plus the first address in the subsector. After
-this second write, the QSPI controller will issue a write--enable
-command to the device (the EQSPI controller will have already issued the
-write--enable), followed by a sector erase command. In summary, for the
-QSPI flash:
+commands the erase itself. The first write should equal \hbox{0x1000\_0000},
+the second should be any address within the sector to be erased together
+with setting the high bit of the register or \hbox{0x8000\_0000} plus the
+address. After this second write, the controller will issue a write--enable
+command to the device, followed by a sector erase command. In summary,
\begin{enumerate}
\item Disable write protect by writing \hbox{\tt 0x1000\_0000} to the EREG
register
@@ -508,30 +287,18 @@
address to the EREG register. (Remember, this is the {\em word
address} of interest, not the {\em byte address}.)
\end{enumerate}
-and for the EQSPI flash:
-\begin{enumerate}
-\item Disable write protect by writing \hbox{\tt 0x4000\_0000} to the EREG
- register
-\item Command the sector (64~kB) erase by writing \hbox{\tt 0xc000\_01be} plus
- the first address in the segment to the EREG register.
- In the case of a subsegment (4~kB) erase command, write
- \hbox{\tt 0xd000\_01be} plus the first address in the subsegment to
- the EREG register.
-\end{enumerate}
-
While the device is erasing, the controller will idle while checking the
status register over and over again. Should you wish to read from the EREG
-during this time, the high order bit of the EREG register will be set indicating
-that a write is in progress (WIP). Once the erase is complete, this bit will
-clear, the interrupt line will be strobed high, and other operations may take
-then place on the part. Any attempt to perform another operation on the part
-prior to that time will stall the bus until the erase is complete.
+during this time, the high order bit of the EREG register will be set.
+Once the erase is complete, this bit will clear, the interrupt line will
+be strobed high, and other operations may take then place on the part. Any
+attempt to perform another operation on the part prior to that time will stall
+the bus until the erase is complete.
Once an area has been erased, it may then be programmed. To program the device,
first disable the write protect by writing a {\tt 0x1000\_0000} to the EREG
-register for the QSPI controller, or {\tt 0x4000\_0000} for the EQSPI
-controller. After that, you may then write to the area in question whatever
+register. After that, you may then write to the area in question whatever
values you wish to program. One 256~byte (64~bus word) page may be programmed
at a time. Pages start on even boundaries, such as addresses {\tt 0x040},
{\tt 0x080}, {\tt 0x0100}, etc. To program a whole page at a time, write the
@@ -541,15 +308,13 @@
In summary,
\begin{enumerate}
\item Disable the write protect by writing a {\tt 0x1000\_0000} to the EREG
- register when using the QSPI flash controller, or {\tt 0x4000\_0000}
- for the EQSPI flash controller.
+ register.
\item Write the page of interest to the data memory of the device.
The first address should start at the beginning of a page (bottom six
bits zero), and end at the end of the page (bottom six bits one, top
bits identical). Writes of less than a page are okay. Writes crossing
- page boundaries will stall the bus, while waiting for the first write
- to complete before attempting to start the second write.
+ page boundaries will stall the device.
\end{enumerate}
While the device is programming a page, the controller will idle while
@@ -559,42 +324,29 @@
the EREG register will be cleared and the interrupt line strobed. Prior to this
time, any other bus operation will stall the bus until the write completes.
-Reads are simple for the QSPI flash controller, you just read from the device
-and the device does everything you expect. Reads may be pipelined. To use
-the QSPI mode of transferring 4--bits at a time, when using the QSPI controller,
-you must first either read (or set) the quad mode bit in the configuration
-register. This will enable Quad--I/O mode reads. Once enabled, reads will
-take place four bits at a time from the bus.
+Reads are simple, you just read from the device and the device does everything
+you expect. Reads may be pipelined. Further, if the device is ever commanded
+to read the configuration register, revealing that the quad SPI mode is
+enabled, then reads will take place four bits at a time from the bus.
+In general, it will take 72 device clocks (at 50~MHz) to read the first word
+from memory, and 32 for every pipelined word read thereafter provided that
+the reads are in memory order. Likewise, in quad SPI mode, it will
+instead take 28 device clocks to read the first word, and 8 device clocks
+to read every word thereafter again provided that the subsequent pipelined
+reads are in memory order.
-Using the EQSPI flash controller, reads are almost as simple, but with a couple
-of caveats. The first caveat is that the controller defaults to Quad I/O mode,
-and will not leave it. The problem is that this mode depends upon a variable
-number of dummy cycles set to 8. Hence, before issuing reads from the data
-section of the device, the number of dummy cycles will need to be set in either
-the volatile or non--volatile configuration register.
-
-
-% When using the QSPI controller,
-% it will take 72 device clocks (at 50~MHz) to read the first word
-% from memory using the QSPI controller, and 32 for every pipelined word read
-% thereafter provided that the reads are in memory order. Likewise, in quad
-% SPI mode, it will instead take 28 device clocks to read the first word,
-% and 8 device clocks to read every word thereafter again provided that the
-% subsequent pipelined reads are in memory order.
-
-Both controllers provide for a special mode following a read, where the
+The Quad SPI device provides for a special mode following a read, where the
next read may start immediately in Quad I/O mode following a 12~clock
-setup for the QSPI controller, or 16~clocks for the EQSPI controller. Both
-controllers leaves the device in this mode following any initial
+setup. This controller leaves the device in this mode following any initial
read. Therefore, back to back reads as part of separate bus cycles will only
-take 20~clocks (24 for EQSPI) to read the first word, and 8~clocks per word
-thereafter. Other commands, however, such as erasing, writing, reading from
-the status, configuration, or ID registers, will require a 32~device
-clock operation before entering.
+take 20~clocks to read the first word, and 8~clocks per word thereafter.
+Other commands, however, such as erasing, writing, reading from the status,
+configuration, or ID registers, will take require a 32~device clock operation
+before entering.
\section{Low Level}
-At a lower level, the QSPI core implements the following Quad SPI commands:
+At a lower level, this core implements the following Quad SPI commands:
\begin{enumerate}
\item FAST\_READ, when a read is requested and Quad mode has not been enabled.
\item QIOR, or quad I/O high performance read mode. This is the default read
@@ -630,9 +382,7 @@
\chapter{Registers}\label{chap:regs}
-\section{QSPI Controller}
-
-The QSPI controller supports four control registers. These are the EREG
+This implementation supports four control registers. These are the EREG
register, the configuration register, the status register, and the device ID,
as shown and listed in Table.~\ref{tbl:reglist}.
\begin{table}[htbp]
@@ -644,10 +394,10 @@
Status & 2 & 8 & R/W & The devices status register.\\\hline
ID & 3 & 16 & R & Reads the 16-bit ID from the device.\\\hline
\end{reglist}
-\caption{List of QSPI Registers}\label{tbl:reglist}
+\caption{List of Registers}\label{tbl:reglist}
\end{center}\end{table}
-\subsection{EREG Register}
+\section{EREG Register}
The EREG register was designed to be a replacement for all of the device
registers, leaving all the other registers a part of a lower level access
used only in debugging the device. This would've been the case, save that
@@ -720,7 +470,7 @@
would work. Thus, to erase a sector, write the sector address, together with
an erase bit, to this register.
-\subsection{Config Register}
+\section{Config Register}
The Quad Flash device also has a non--volatile configuration register, as
shown in Tbl.~\ref{tbl:confbits}. Writes to this register are program events,
@@ -760,7 +510,7 @@
Further information on this register is available in the device data sheet.
-\subsection{Status Register}
+\section{Status Register}
The definitions of the bits in the status register are shown in
Tbl.~\ref{tbl:statbits}. For operating this core, only the write in progress
bit is relevant. All other bits should be set to zero.
@@ -792,7 +542,7 @@
\caption{Status bit definitions}\label{tbl:statbits}
\end{center}\end{table}
-\subsection{Device ID}
+\section{Device ID}
Reading from the Device ID register causes the core controller to issue
a RDID {\tt 0x9f} command. The bytes returned are first the manufacture
@@ -815,17 +565,15 @@
\begin{center}
\begin{wishboneds}
Revision level of wishbone & WB B4 spec \\\hline
-Type of interface & Slave, (Pipelind) Read/Write \\\hline
+Type of interface & Slave, (Block) Read/Write \\\hline
Port size & 32--bit \\\hline
Port granularity & 32--bit \\\hline
Maximum Operand Size & 32--bit \\\hline
Data transfer ordering & Little Endian \\\hline
-Clock constraints & Must be 100~MHz or slower (QSPI)\\\cline{2-2}
- & Must be 200~MHz or slower (EQSPI)\\\hline
+Clock constraints & Must be 100~MHz or slower \\\hline
Signal Names & \begin{tabular}{ll}
Signal Name & Wishbone Equivalent \\\hline
- {\tt i\_clk\_100mhz} & {\tt CLK\_I} { (QSPI)} \\
- {\tt i\_clk\_200mhz} & {\tt CLK\_I} { (EQSPI)}\\
+ {\tt i\_clk\_100mhz} & {\tt CLK\_I} \\
{\tt i\_wb\_cyc} & {\tt CYC\_I} \\
{\tt i\_wb\_ctrl\_stb} & {\tt STB\_I} \\
{\tt i\_wb\_data\_stb} & {\tt STB\_I} \\
@@ -837,51 +585,24 @@
{\tt o\_wb\_data} & {\tt DAT\_O}
\end{tabular}\\\hline
\end{wishboneds}
-\caption{Wishbone Datasheet for the (E)QSPI Flash controller}\label{tbl:wishbone}
+\caption{Wishbone Datasheet for the Quad SPI Flash controller}\label{tbl:wishbone}
\end{center}\end{table}
-The EQSPI flash controller has a further simplified wishbone usage: the strobe
-lines, whether {\tt i\_wb\_ctrl\_stb} or {\tt i\_wb\_data\_stb}, must be
-guaranteed low any time {\tt i\_wb\_cyc} is low. This simplifies transaction
-processing internal to the controller, and is part of the method of getting the
-controller running at 200~MHz.
-
-\section{EQSPI Controller}
-\subsection{EREG Register}
-\subsection{Status Register}
-\subsection{Non--Volatile Configuration Register}
-\subsection{Volatile Configuration Register}
-\subsection{Extended Volatile Configuration Register}
-\subsection{Sector Lock Register}
-\subsection{Flag Status Register}
-\subsection{Identification memory}
-\subsection{One--Time Programmable Memory}
-
\chapter{Clocks}\label{chap:clocks}
-The QSPI core is based upon the Basys--3 design. The Basys--3 development board
+This core is based upon the Basys--3 design. The Basys--3 development board
contains one external 100~MHz clock. This clock is divided by two to create
the 50~MHz clock used to drive the device. According to the data sheet,
it should be possible to run this core at up to 160~MHz, however I have not
-tested it at such speeds. See Table.~\ref{tbl:qspi-clocks}.
-\begin{table}[htbp]\begin{center}\begin{clocklist}
+tested it at such speeds. See Table.~\ref{tbl:clocks}.
+\begin{table}[htbp]
+\begin{center}
+\begin{clocklist}
i\_clk\_100mhz & External & 160 & & System clock.\\\hline
\end{clocklist}
-\caption{List of QSPI Controller Clocks}\label{tbl:qspi-clocks}
+\caption{List of Clocks}\label{tbl:clocks}
\end{center}\end{table}
-The EQSPI core is based upon a very similar Arty design, but one that instead
-uses a 200~MHz core clock frequency. In a fashion similar to the QSPI
-controller, this clock is divided down to create a 100~MHz clock to command
-the device. Hence, the EQSPI clock is much faster, as shown in
-Table.~\ref{tbl:eqspi-clocks}.
-\begin{table}[htbp]\begin{center}\begin{clocklist}
-i\_clk\_200mhz & External & 200 & & System clock.\\\hline
-\end{clocklist}
-\caption{List of EQSPI Controller Clocks}\label{tbl:eqspi-clocks}
-\end{center}\end{table}
-
-
\chapter{I/O Ports}\label{chap:ioports}
There are two interfaces that this device supports: a wishbone interface, and
the interface to the Quad--SPI flash itself. Both of these have their own
@@ -925,7 +646,7 @@
an error for both strobe lines to be on at the same time.
With respect to the Quad SPI interface itself, one piece of glue logic
-is necessary to tie the QSPI flash I/O to the in/out port at the top
+is necessary to tie the Quad SPI flash I/O to the in/out port at the top
level of the device. Specifically, these two lines must be added somewhere:
\begin{tabbing}
assign {\tt io\_qspi\_dat} = \= (\~{\tt qspi\_mod[1]})?(\{2'b11,1'bz,{\tt qspi\_dat[0]}\}) \hbox{\em // Serial mode} \\
@@ -938,8 +659,6 @@
mode, the hold and write protect lines are effectively eliminated in this
design in favor of faster speed I/O (i.e., Quad I/O).
-The EQSPI controller is similar, but the glue logic is more involved.
-
\begin{table}[htbp]
\begin{center}
\begin{portlist}
@@ -965,8 +684,7 @@
\begin{table}[htbp]
\begin{center}
\begin{portlist}
-i\_clk\_100mhz & 1 & Input & The 100~MHz clock driving all QSPI
- interactions.\\\hline
+i\_clk\_100mhz & 1 & Input & The 100~MHz clock driving all interactions.\\\hline
o\_interrupt & 1 & Output & An strobed interrupt line indicating the end of
any erase or write transaction. This line will be high for exactly
one clock cycle, indicating that the core is again available for