OpenCores
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 3 to Rev 4
    Reverse comparison

Rev 3 → Rev 4

/bench/cpp/qspiflashsim.cpp
212,7 → 212,7
assert(m_quad_mode);
if (m_count == 24) {
if (m_debug) printf("QSPI: Entering from Quad-Read Idle to Quad-Read\n");
printf("QSPI: QI/O Idle Addr = %02x\n", m_ireg&0x0ffffff);
if (m_debug) printf("QSPI: QI/O Idle Addr = %02x\n", m_ireg&0x0ffffff);
m_addr = (m_ireg) & 0x0ffffff;
assert((m_addr & 0xfc00000)==0);
m_state = QSPIF_QUAD_READ;
415,8 → 415,7
// printf("QSPI/QR: MODE BYTE = %02x\n", m_mode_byte);
} else if ((m_count >= 32+16)&&(0 == (m_sreg&0x01))) {
QOREG(m_mem[m_addr++]);
printf("QSPIF[%08x]/QR = %02x\n",
m_addr-1, m_oreg & 0x0ff);
// printf("QSPIF[%08x]/QR = %02x\n", m_addr-1, m_oreg & 0x0ff);
} else m_oreg = 0;
break;
case QSPIF_PP:
/rtl/wbqspiflash.v
52,7 → 52,7
//
///////////////////////////////////////////////////////////////////////////
`define WBQSPI_RESET 0
`define WBQSPI_RESET_WEN 1
`define WBQSPI_RESET_QUADMODE 1
`define WBQSPI_IDLE 2
`define WBQSPI_RDIDLE 3 // Idle, but in fast read mode
`define WBQSPI_WBDECODE 4
114,10 → 114,13
reg [1:0] spi_len;
wire [31:0] spi_out;
wire spi_valid, spi_busy;
wire w_qspi_sck, w_qspi_cs_n;
wire [3:0] w_qspi_dat;
wire [1:0] w_qspi_mod;
llqspi lldriver(i_clk_100mhz,
spi_wr, spi_hold, spi_in, spi_len, spi_spd, spi_dir,
spi_out, spi_valid, spi_busy,
o_qspi_sck, o_qspi_cs_n, o_qspi_mod, o_qspi_dat,
w_qspi_sck, w_qspi_cs_n, w_qspi_mod, w_qspi_dat,
i_qspi_dat);
 
// Erase status tracking
133,11 → 136,10
 
reg [7:0] last_status;
reg quad_mode_enabled;
reg spif_cmd;
reg spif_cmd, spif_override;
reg [19:0] spif_addr;
reg [31:0] spif_data;
reg [5:0] state;
reg [5:0] spif_return;
reg spif_ctrl, spif_req;
wire [5:0] spif_sector;
assign spif_sector = spif_addr[19:14];
150,6 → 152,8
initial quad_mode_enabled = 1'b0;
initial o_interrupt = 1'b0;
always @(posedge i_clk_100mhz)
begin
spif_override <= 1'b0;
if (state == `WBQSPI_RESET)
begin
// From a reset, we should
159,46 → 163,38
// immediately ....
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
spi_wr <= 1'b0;
spi_hold <= 1'b0;
spi_spd <= 1'b0;
spi_dir <= 1'b0;
last_status <= 8'h00;
if (spi_len < 2'b11)
spi_len <= spi_len + 1;
state <= `WBQSPI_IDLE;
state <= `WBQSPI_RESET_QUADMODE;
spif_req <= 1'b0;
/*
// This next bit of logic is confusing ...
// I wish to enable quad SPI mode automatically. However, this is
// a configuration register thing, so once written it never needs to
// be adjusted again. Further, some bits within the configuration
// register cannot be undone, and my inkling might be to set those.
// Finally, the configuration register affects the control of the
// block protect registers in the status register. So ...
// let's just leave these registers alone, or command them from the
// UART-wishbone interface.
else if (~spi_busy)
begin
spi_wr <= 1'b1;
spi_len <= 2'b00; // 1 byte
spi_in <= { 8'h06, 24'h000 };
end
end else if (state == `WBQSPI_RESET_WEN)
spif_override <= 1'b1;
last_status <= 8'hfc; //
// This guarantees that we aren't starting in quad
// I/O mode, where the FPGA configuration scripts may
// have left us.
end else if (state == `WBQSPI_RESET_QUADMODE)
begin
spi_wr <= 1'b0;
if ((~spi_busy)&&(~spi_wr)&&(o_qspi_cs_n))
// 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
// Not ready to handle the bus yet, so stall any requests
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
 
// Do something ...
if (last_status == 8'h00)
begin
spi_wr <= 1'b1;
spi_spd <= 1'b0;
spi_len <= 2'b10; // 3 bytes
// Command, status, config, then don't care
spi_in <= { 8'h01, 8'h00, 8'h0b, 8'h00 };
spi_dir <= 1'b0;
quad_mode_enabled <= 1'b1;
state <= `WBQSPI_WAIT_TIL_IDLE;
write_in_progress <= 1'b1;
spif_override <= 1'b0;
state <= `WBQSPI_IDLE;
end else begin
last_status <= last_status - 8'h1;
spif_override <= 1'b1;
spif_cmd <= last_status[3]; // Toggle CS_n
spif_ctrl <= last_status[0]; // Toggle clock too
end
*/
end else if (state == `WBQSPI_IDLE)
begin
o_interrupt <= 1'b0;
403,7 → 399,7
begin // Continue our read ... send the new address / mode
o_wb_stall <= 1'b1;
spi_wr <= 1'b1;
spi_len <= 2'b10;
spi_len <= 2'b10; // Write address, but not mode byte
spi_in <= { 2'h0, i_wb_addr[19:0], 2'h0, 8'ha0 };
state <= `WBQSPI_QRD_DUMMY;
end else if((i_wb_cyc)&&(i_wb_ctrl_stb)&&(~i_wb_we)&&(i_wb_addr[1:0] == 2'b00))
631,10 → 627,12
if (quad_mode_enabled)
begin
spi_in <= { 8'heb, 2'b00, spif_addr[19:0], 2'b00 };
state <= `WBQSPI_QRD_DUMMY;
state <= `WBQSPI_QRD_ADDRESS;
// spi_len <= 2'b00; // single byte, cmd only
end else begin
spi_in <= { 8'h0b, 2'b00, spif_addr[19:0], 2'b00 };
state <= `WBQSPI_RD_DUMMY;
spi_len <= 2'b11; // Send cmd and addr
end end
4'b10??: begin // Write data to ... anywhere
spi_wr <= 1'b1;
674,8 → 672,8
o_wb_stall <= 1'b1;
spif_req<= (spif_req) && (i_wb_cyc);
if ((~spi_busy)&&(o_qspi_cs_n)&&(~spi_wr)) // Let's come to a full stop
// state <= (quad_mode_enabled)?`WBQSPI_QPP:`WBQSPI_PP;
state <= `WBQSPI_PP;
state <= (quad_mode_enabled)?`WBQSPI_QPP:`WBQSPI_PP;
// state <= `WBQSPI_PP;
end else if (state == `WBQSPI_PP)
begin // We come here under a full stop / full port idle mode
// Issue our command immediately
794,7 → 792,7
 
spi_wr <= 1'b1; // Non-stop
spi_in <= { 2'b0, spif_addr, 2'b0, 8'ha0 };
spi_len <= 2'b11; // Write all 32 bits bits
spi_len <= 2'b10; // Write address, not mode byte
spi_spd <= 1'b1;
spi_dir <= 1'b0; // Still writing
spi_hold <= 1'b0;
836,12 → 834,23
begin
// Pipelined read support
spi_wr <=((i_wb_cyc)&&(i_wb_data_stb)&&(~i_wb_we)&&(i_wb_addr== (spif_addr+1)));
// spi_wr <= 1'b0; // No pipelined read support
spi_in <= 32'h00;
spi_len <= 2'b11;
// Don't adjust the speed here, it was set in the setup
spi_dir <= 1'b1; // Now we get to read
spi_hold <= 1'b0;
spi_dir <= 1'b1; // Now we get to read
// Don't let the device go to idle until the bus cycle ends.
// This actually prevents a *really* nasty race condition,
// where the strobe comes in after the lower level device
// has decided to stop waiting. The write is then issued,
// but no one is listening. By leaving the device open,
// the device is kept in a state where a valid strobe
// here will be useful. Of course, we don't accept
// all commands, just reads. Further, the strobe needs
// to be high for two clocks cycles without changing
// anything on the bus--one for us to notice it and pull
// our head out of the sand, and a second for whoever
// owns the bus to realize their command went through.
spi_hold <= 1'b1;
spif_req<= (spif_req) && (i_wb_cyc);
if ((spi_valid)&&(~spi_in[31]))
begin // Single pulse acknowledge and write data out
853,8 → 862,16
state <= (spi_wr)?`WBQSPI_READ_DATA
: ((spi_spd) ? `WBQSPI_WAIT_TIL_RDIDLE : `WBQSPI_WAIT_TIL_IDLE);
spif_req <= spi_wr;
spi_hold <= (~spi_wr);
if (spi_wr)
spif_addr <= i_wb_addr;
end else if (~i_wb_cyc)
begin // FAIL SAFE: If the bus cycle ends, forget why we're
// here, just go back to idle
state <= ((spi_spd) ? `WBQSPI_WAIT_TIL_RDIDLE : `WBQSPI_WAIT_TIL_IDLE);
spi_hold <= 1'b0;
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
end else begin
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
895,7 → 912,7
o_wb_ack <= 1'b0; // Assuming we're still waiting
o_wb_stall <= 1'b1;
 
spi_wr <= 1'b0; // No more writes, we'ev already written the cmd
spi_wr <= 1'b0; // No more writes, we've already written the cmd
spi_hold <= 1'b0;
spif_req <= (spif_req) && (i_wb_cyc);
 
908,7 → 925,7
o_wb_data <= spi_out[31:0];
o_wb_ack <= spif_req;
spif_req <= 1'b0;
end else if ((~spi_busy)&&(~o_qspi_cs_n))
end else if ((~spi_busy)&&(o_qspi_cs_n))
begin
state <= `WBQSPI_IDLE;
o_wb_stall <= 1'b0;
1097,5 → 1114,11
o_wb_ack <= 1'b0; // Shouldn't be acking anything here
end
end
end
 
// Command and control during the reset sequence
assign o_qspi_cs_n = (spif_override)?spif_cmd :w_qspi_cs_n;
assign o_qspi_sck = (spif_override)?spif_ctrl:w_qspi_sck;
assign o_qspi_mod = (spif_override)? 2'b01 :w_qspi_mod;
assign o_qspi_dat = (spif_override)? 4'b00 :w_qspi_dat;
endmodule
/rtl/llqspi.v
37,12 → 37,13
//
//
///////////////////////////////////////////////////////////////////////////
`define QSPI_IDLE 0
`define QSPI_START 1
`define QSPI_BITS 2
`define QSPI_READY 3
`define QSPI_STOP 4
`define QSPI_STOP_B 5
`define QSPI_IDLE 3'h0
`define QSPI_START 3'h1
`define QSPI_BITS 3'h2
`define QSPI_READY 3'h3
`define QSPI_HOLDING 3'h4
`define QSPI_STOP 3'h5
`define QSPI_STOP_B 3'h6
 
// Modes
`define QSPI_MOD_SPI 2'b00
266,7 → 267,7
// high clocks) of the data. Data is valid during
// this state. Here we chose to either STOP or
// continue and transmit more.
o_sck <= (i_hold); // Stay here on hold, no clocks
o_sck <= (i_hold); // No clocks while holding
if((~o_busy)&&(i_wr))// Acknowledge a new request
begin
state <= `QSPI_BITS;
303,13 → 304,10
r_input <= { r_input[26:0], i_dat };
o_word <= { r_input[27:0], i_dat };
end
end else if (i_hold)
begin // Stay here, holding the clock high, if the user
// has more data, but it isn't ready yet.
o_busy <= 1'b0;
end else begin
o_sck <= 1'b1;
state <= `QSPI_STOP;
state <= (i_hold)?`QSPI_HOLDING : `QSPI_STOP;
o_busy <= (~i_hold);
 
// Read a bit upon any transition
o_valid <= 1'b1;
323,6 → 321,45
o_word <= { r_input[27:0], i_dat };
end
end
end else if (state == `QSPI_HOLDING)
begin
// We need this state so that the o_valid signal
// can get strobed with our last result. Otherwise
// we could just sit in READY waiting for a new command.
//
// Incidentally, the change producing this state was
// the result of a nasty race condition. See the
// commends in wbqspiflash for more details.
//
o_valid <= 1'b0;
o_cs_n <= 1'b0;
o_busy <= 1'b0;
if((~o_busy)&&(i_wr))// Acknowledge a new request
begin
state <= `QSPI_BITS;
o_busy <= 1'b1;
o_sck <= 1'b0;
 
// Read the new request off the bus
r_spd <= i_spd;
r_dir <= i_dir;
// Set up the first bits on the bus
o_mod<=(i_spd)?{ 1'b1, i_dir } : `QSPI_MOD_SPI;
if (i_spd)
begin
o_dat <= i_word[31:28];
r_word <= { i_word[27:0], 4'h0 };
spi_len<= { 1'b0, i_len, 3'b100 };
end else begin
o_dat <= { 3'b110, i_word[31] };
r_word <= { i_word[30:0], 1'b0 };
spi_len<= { 1'b0, i_len, 3'b111 };
end
end else begin
o_sck <= 1'b1;
state <= (i_hold)?`QSPI_HOLDING : `QSPI_STOP;
o_busy <= (~i_hold);
end
end else if (state == `QSPI_STOP)
begin
o_sck <= 1'b1; // Stop the clock

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.