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/rtl
    from Rev 7 to Rev 4
    Reverse comparison

Rev 7 → Rev 4

/flash_config.v File deleted
/wbqspiflash.v
51,46 → 51,37
//
//
///////////////////////////////////////////////////////////////////////////
//
`include "flash_config.v"
//
`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 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
`define WBQSPI_WAIT_WIP_CLEAR 5
`define WBQSPI_CHECK_WIP_CLEAR 6
`define WBQSPI_CHECK_WIP_DONE 7
`define WBQSPI_WEN 8
`define WBQSPI_PP 9 // Program page
`define WBQSPI_QPP 10 // Program page, 4 bit mode
`define WBQSPI_WR_DATA 11
`define WBQSPI_WR_BUS_CYCLE 12
`define WBQSPI_RD_DUMMY 13
`define WBQSPI_QRD_ADDRESS 14
`define WBQSPI_QRD_DUMMY 15
`define WBQSPI_READ_CMD 16
`define WBQSPI_READ_DATA 17
`define WBQSPI_WAIT_TIL_RDIDLE 18
`define WBQSPI_READ_ID_CMD 19
`define WBQSPI_READ_ID 20
`define WBQSPI_READ_STATUS 21
`define WBQSPI_READ_CONFIG 22
`define WBQSPI_WRITE_STATUS 23
`define WBQSPI_WRITE_CONFIG 24
`define WBQSPI_ERASE_WEN 25
`define WBQSPI_ERASE_CMD 26
`define WBQSPI_ERASE_BLOCK 27
`define WBQSPI_CLEAR_STATUS 28
`define WBQSPI_IDLE_CHECK_WIP 29
`define WBQSPI_WAIT_TIL_IDLE 30
 
module wbqspiflash(i_clk_100mhz,
// Internal wishbone connections
101,11 → 92,10
// Quad Spi connections to the external device
o_qspi_sck, o_qspi_cs_n, o_qspi_mod, o_qspi_dat, i_qspi_dat,
o_interrupt);
parameter ADDRESS_WIDTH=22;
input i_clk_100mhz;
// Wishbone, inputs first
input i_wb_cyc, i_wb_data_stb, i_wb_ctrl_stb, i_wb_we;
input [(ADDRESS_WIDTH-3):0] i_wb_addr;
input [19:0] i_wb_addr;
input [31:0] i_wb_data;
// then outputs
output reg o_wb_ack;
118,7 → 108,6
input [3:0] i_qspi_dat;
// Interrupt line
output reg o_interrupt;
// output wire [31:0] o_debug;
 
reg spi_wr, spi_hold, spi_spd, spi_dir;
reg [31:0] spi_in;
128,7 → 117,6
wire w_qspi_sck, w_qspi_cs_n;
wire [3:0] w_qspi_dat;
wire [1:0] w_qspi_mod;
// wire [22:0] spi_dbg;
llqspi lldriver(i_clk_100mhz,
spi_wr, spi_hold, spi_in, spi_len, spi_spd, spi_dir,
spi_out, spi_valid, spi_busy,
137,11 → 125,11
 
// Erase status tracking
reg write_in_progress, write_protect;
reg [(ADDRESS_WIDTH-17):0] erased_sector;
reg [5:0] erased_sector;
reg dirty_sector;
initial begin
write_in_progress = 1'b0;
erased_sector = 0;
erased_sector = 6'h00;
dirty_sector = 1'b1;
write_protect = 1'b1;
end
149,15 → 137,13
reg [7:0] last_status;
reg quad_mode_enabled;
reg spif_cmd, spif_override;
reg [(ADDRESS_WIDTH-3):0] spif_addr;
reg [19:0] spif_addr;
reg [31:0] spif_data;
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];
wire [5:0] spif_sector;
assign spif_sector = spif_addr[19:14];
 
// assign o_debug = { spi_wr, spi_spd, spi_hold, state, spi_dbg };
 
initial state = `WBQSPI_RESET;
initial o_wb_ack = 1'b0;
initial o_wb_stall = 1'b1;
229,11 → 215,6
 
if (i_wb_we) // Request to write a page
begin
`ifdef READ_ONLY
o_wb_ack <= 1'b1;
o_wb_stall <= 1'b0;
end else
`else
if((~write_protect)&&(~write_in_progress))
begin // 00
spi_wr <= 1'b1;
258,7 → 239,6
o_wb_stall <= 1'b1;
end
end else if (~write_in_progress)
`endif
begin // Read access, normal mode(s)
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
265,19 → 245,14
spi_wr <= 1'b1; // Write cmd to device
if (quad_mode_enabled)
begin
spi_in <= { 8'heb,
{(24-ADDRESS_WIDTH){1'b0}},
i_wb_addr[(ADDRESS_WIDTH-3):0], 2'b00 };
spi_in <= { 8'heb, 2'b00, i_wb_addr[19:0], 2'b00 };
state <= `WBQSPI_QRD_ADDRESS;
spi_len <= 2'b00; // single byte, cmd only
end else begin
spi_in <= { 8'h0b,
{(24-ADDRESS_WIDTH){1'b0}},
i_wb_addr[(ADDRESS_WIDTH-3):0], 2'b00 };
spi_in <= { 8'h0b, 2'b00, i_wb_addr[19:0], 2'b00 };
state <= `WBQSPI_RD_DUMMY;
spi_len <= 2'b11; // cmd+addr,32bits
end
`ifndef READ_ONLY
end else begin
// A write is in progress ... need to stall
// the bus until the write is complete.
284,14 → 259,9
state <= `WBQSPI_WAIT_WIP_CLEAR;
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
`endif
end
end else if ((i_wb_cyc)&&(i_wb_ctrl_stb)&&(i_wb_we))
begin
`ifdef READ_ONLY
o_wb_ack <= 1'b1;
o_wb_stall <= 1'b0;
`else
o_wb_stall <= 1'b1;
case(i_wb_addr[1:0])
2'b00: begin // Erase command register
351,7 → 321,6
o_wb_stall <= 1'b0;
end
endcase
`endif
end else if ((i_wb_cyc)&&(i_wb_ctrl_stb)) // &&(~i_wb_we))
begin
case(i_wb_addr[1:0])
372,7 → 341,7
dirty_sector, spi_busy,
~write_protect,
quad_mode_enabled,
{(29-ADDRESS_WIDTH){1'b0}},
7'h00,
erased_sector, 14'h000 };
end end
2'b01: begin // Read configuration register
403,7 → 372,6
o_wb_stall <= 1'b1;
end
endcase
`ifndef READ_ONLY
end else if ((~i_wb_cyc)&&(write_in_progress))
begin
state <= `WBQSPI_IDLE_CHECK_WIP;
413,7 → 381,6
 
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
`endif
end
end else if (state == `WBQSPI_RDIDLE)
begin
433,8 → 400,7
o_wb_stall <= 1'b1;
spi_wr <= 1'b1;
spi_len <= 2'b10; // Write address, but not mode byte
spi_in <= { {(24-ADDRESS_WIDTH){1'b0}},
i_wb_addr[(ADDRESS_WIDTH-3):0], 2'b00, 8'ha0 };
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))
begin
446,7 → 412,7
dirty_sector, spi_busy,
~write_protect,
quad_mode_enabled,
{(29-ADDRESS_WIDTH){1'b0}},
7'h00,
erased_sector, 14'h000 };
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
479,11 → 445,6
begin
if (spif_cmd) // Request to write a page
begin
`ifdef READ_ONLY
o_wb_ack <= spif_req;
o_wb_stall <= 1'b0;
state <= `WBQSPI_IDLE;
`else
if((~write_protect)&&(~write_in_progress))
begin // 00
spi_wr <= 1'b1;
510,20 → 471,13
end
// end else if (~write_in_progress) // always true
// but ... we wouldn't get here on a normal read access
`endif
end else begin
// Something's wrong, we should never
// get here
// Something's wrong, we should never get here
// Attempt to go to idle to recover
state <= `WBQSPI_IDLE;
end
end else if ((spif_ctrl)&&(spif_cmd))
begin
`ifdef READ_ONLY
o_wb_ack <= spif_req;
o_wb_stall <= 1'b0;
state <= `WBQSPI_IDLE;
`else
o_wb_stall <= 1'b1;
case(spif_addr[1:0])
2'b00: begin // Erase command register
575,7 → 529,6
state <= `WBQSPI_IDLE;
end
endcase
`endif
end else begin // on (~spif_we)
case(spif_addr[1:0])
2'b00: begin // Read local register
615,10 → 568,203
endcase
end
end
//
//
// READ DATA section: for both data and commands
//
end else if (state == `WBQSPI_WAIT_WIP_CLEAR)
begin
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
spi_wr <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if (~spi_busy)
begin
spi_wr <= 1'b1;
spi_in <= { 8'h05, 24'h0000 };
spi_hold <= 1'b1;
spi_len <= 2'b01; // 16 bits write, so we can read 8
state <= `WBQSPI_CHECK_WIP_CLEAR;
spi_spd <= 1'b0; // Slow speed
spi_dir <= 1'b0;
end
end else if (state == `WBQSPI_CHECK_WIP_CLEAR)
begin
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
// Repeat as often as necessary until we are clear
spi_wr <= 1'b1;
spi_in <= 32'h0000; // Values here are actually irrelevant
spi_hold <= 1'b1;
spi_len <= 2'b00; // One byte at a time
spi_spd <= 1'b0; // Slow speed
spi_dir <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if ((spi_valid)&&(~spi_out[0]))
begin
state <= `WBQSPI_CHECK_WIP_DONE;
spi_wr <= 1'b0;
spi_hold <= 1'b0;
write_in_progress <= 1'b0;
last_status <= spi_out[7:0];
end
end else if (state == `WBQSPI_CHECK_WIP_DONE)
begin
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
// Let's let the SPI port come back to a full idle,
// and the chip select line go low before continuing
spi_wr <= 1'b0;
spi_len <= 2'b00;
spi_hold <= 1'b0;
spi_spd <= 1'b0; // Slow speed
spi_dir <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if ((o_qspi_cs_n)&&(~spi_busy)) // Chip select line is high, we can continue
begin
spi_wr <= 1'b0;
spi_hold <= 1'b0;
 
casez({ spif_cmd, spif_ctrl, spif_addr[1:0] })
4'b00??: begin // Read data from ... somewhere
spi_wr <= 1'b1; // Write cmd to device
if (quad_mode_enabled)
begin
spi_in <= { 8'heb, 2'b00, spif_addr[19:0], 2'b00 };
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;
spi_len <= 2'b00; // 8 bits
// Send a write enable command
spi_in <= { 8'h06, 24'h00 };
state <= `WBQSPI_WEN;
end
4'b0110: begin // Read status register
state <= `WBQSPI_READ_STATUS;
spi_wr <= 1'b1;
spi_len <= 2'b01; // 8 bits out, 8 bits in
spi_in <= { 8'h05, 24'h00};
end
4'b0111: begin
state <= `WBQSPI_READ_ID_CMD;
spi_wr <= 1'b1;
spi_len <= 2'b00;
spi_in <= { 8'h9f, 24'h00};
end
default: begin //
o_wb_stall <= 1'b1;
o_wb_ack <= spif_req;
state <= `WBQSPI_WAIT_TIL_IDLE;
end
endcase
// spif_cmd <= i_wb_we;
// spif_addr <= i_wb_addr;
// spif_data <= i_wb_data;
// spif_ctrl <= (i_wb_ctrl_stb)&&(~i_wb_data_stb);
// spi_wr <= 1'b0; // Keep the port idle, unless told otherwise
end
end else if (state == `WBQSPI_WEN)
begin // We came here after issuing a write enable command
spi_wr <= 1'b0;
o_wb_ack <= 1'b0;
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;
end else if (state == `WBQSPI_PP)
begin // We come here under a full stop / full port idle mode
// Issue our command immediately
spi_wr <= 1'b1;
spi_in <= { 8'h02, 2'h0, spif_addr, 2'b00 };
spi_len <= 2'b11;
spi_hold <= 1'b1;
spi_spd <= 1'b0;
spi_dir <= 1'b0; // Writing
spif_req<= (spif_req) && (i_wb_cyc);
 
// Once we get busy, move on
if (spi_busy)
state <= `WBQSPI_WR_DATA;
if (spif_sector == erased_sector)
dirty_sector <= 1'b1;
end else if (state == `WBQSPI_QPP)
begin // We come here under a full stop / full port idle mode
// Issue our command immediately
spi_wr <= 1'b1;
spi_in <= { 8'h32, 2'h0, spif_addr, 2'b00 };
spi_len <= 2'b11;
spi_hold <= 1'b1;
spi_spd <= 1'b0;
spi_dir <= 1'b0; // Writing
spif_req<= (spif_req) && (i_wb_cyc);
 
// Once we get busy, move on
if (spi_busy)
begin
// spi_wr is irrelevant here ...
// Set the speed value once, but wait til we get busy
// to do so.
spi_spd <= 1'b1;
state <= `WBQSPI_WR_DATA;
end
if (spif_sector == erased_sector)
dirty_sector <= 1'b1;
end else if (state == `WBQSPI_WR_DATA)
begin
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
spi_wr <= 1'b1; // write without waiting
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)
begin
o_wb_ack <= spif_req; // Ack when command given
state <= `WBQSPI_WR_BUS_CYCLE;
end
spif_req<= (spif_req) && (i_wb_cyc);
end else if (state == `WBQSPI_WR_BUS_CYCLE)
begin
o_wb_ack <= 1'b0; // Turn off our ack and stall flags
o_wb_stall <= 1'b1;
spi_wr <= 1'b0;
spi_hold <= 1'b1;
write_in_progress <= 1'b1;
spif_req<= (spif_req) && (i_wb_cyc);
if (~i_wb_cyc)
begin
state <= `WBQSPI_WAIT_TIL_IDLE;
spi_hold <= 1'b0;
end else if (spi_wr)
begin // Give the SPI a chance to get busy on the last write
// Do nothing here.
end else if ((i_wb_data_stb)&&(i_wb_we)
&&(i_wb_addr == (spif_addr+1))
&&(i_wb_addr[19:6]==spif_addr[19:6]))
begin
spif_cmd <= 1'b1;
spif_data <= i_wb_data;
spif_addr <= i_wb_addr;
spif_ctrl <= 1'b0;
spif_req<= 1'b1;
// We'll keep the bus stalled on this request
// for a while
state <= `WBQSPI_WR_DATA;
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b0;
end else if ((i_wb_data_stb|i_wb_ctrl_stb)&&(~o_wb_ack)) // Writing out of bounds
begin
spi_hold <= 1'b0;
spi_wr <= 1'b0;
state <= `WBQSPI_WAIT_TIL_IDLE;
end // Otherwise we stay here
end else if (state == `WBQSPI_RD_DUMMY)
begin
o_wb_ack <= 1'b0;
645,8 → 791,7
o_wb_stall <= 1'b1;
 
spi_wr <= 1'b1; // Non-stop
spi_in <= { {(24-ADDRESS_WIDTH){1'b0}},
spif_addr[(ADDRESS_WIDTH-3):0], 2'b00, 8'ha0 };
spi_in <= { 2'b0, spif_addr, 2'b0, 8'ha0 };
spi_len <= 2'b10; // Write address, not mode byte
spi_spd <= 1'b1;
spi_dir <= 1'b0; // Still writing
805,7 → 950,7
dirty_sector, spi_busy,
~write_protect,
quad_mode_enabled,
{(29-ADDRESS_WIDTH){1'b0}},
7'h00,
erased_sector, 14'h000 };
end else begin
o_wb_data <= { 24'h00, spi_out[7:0] };
836,217 → 981,6
o_wb_stall <= 1'b0;
spif_req <= 1'b0;
end
 
//
//
// Write/erase data section
//
`ifndef READ_ONLY
end else if (state == `WBQSPI_WAIT_WIP_CLEAR)
begin
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
spi_wr <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if (~spi_busy)
begin
spi_wr <= 1'b1;
spi_in <= { 8'h05, 24'h0000 };
spi_hold <= 1'b1;
spi_len <= 2'b01; // 16 bits write, so we can read 8
state <= `WBQSPI_CHECK_WIP_CLEAR;
spi_spd <= 1'b0; // Slow speed
spi_dir <= 1'b0;
end
end else if (state == `WBQSPI_CHECK_WIP_CLEAR)
begin
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
// Repeat as often as necessary until we are clear
spi_wr <= 1'b1;
spi_in <= 32'h0000; // Values here are actually irrelevant
spi_hold <= 1'b1;
spi_len <= 2'b00; // One byte at a time
spi_spd <= 1'b0; // Slow speed
spi_dir <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if ((spi_valid)&&(~spi_out[0]))
begin
state <= `WBQSPI_CHECK_WIP_DONE;
spi_wr <= 1'b0;
spi_hold <= 1'b0;
write_in_progress <= 1'b0;
last_status <= spi_out[7:0];
end
end else if (state == `WBQSPI_CHECK_WIP_DONE)
begin
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
// Let's let the SPI port come back to a full idle,
// and the chip select line go low before continuing
spi_wr <= 1'b0;
spi_len <= 2'b00;
spi_hold <= 1'b0;
spi_spd <= 1'b0; // Slow speed
spi_dir <= 1'b0;
spif_req<= (spif_req) && (i_wb_cyc);
if ((o_qspi_cs_n)&&(~spi_busy)) // Chip select line is high, we can continue
begin
spi_wr <= 1'b0;
spi_hold <= 1'b0;
 
casez({ spif_cmd, spif_ctrl, spif_addr[1:0] })
4'b00??: begin // Read data from ... somewhere
spi_wr <= 1'b1; // Write cmd to device
if (quad_mode_enabled)
begin
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,
{(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
4'b10??: begin // Write data to ... anywhere
spi_wr <= 1'b1;
spi_len <= 2'b00; // 8 bits
// Send a write enable command
spi_in <= { 8'h06, 24'h00 };
state <= `WBQSPI_WEN;
end
4'b0110: begin // Read status register
state <= `WBQSPI_READ_STATUS;
spi_wr <= 1'b1;
spi_len <= 2'b01; // 8 bits out, 8 bits in
spi_in <= { 8'h05, 24'h00};
end
4'b0111: begin
state <= `WBQSPI_READ_ID_CMD;
spi_wr <= 1'b1;
spi_len <= 2'b00;
spi_in <= { 8'h9f, 24'h00};
end
default: begin //
o_wb_stall <= 1'b1;
o_wb_ack <= spif_req;
state <= `WBQSPI_WAIT_TIL_IDLE;
end
endcase
// spif_cmd <= i_wb_we;
// spif_addr <= i_wb_addr;
// spif_data <= i_wb_data;
// spif_ctrl <= (i_wb_ctrl_stb)&&(~i_wb_data_stb);
// spi_wr <= 1'b0; // Keep the port idle, unless told otherwise
end
end else if (state == `WBQSPI_WEN)
begin // We came here after issuing a write enable command
spi_wr <= 1'b0;
o_wb_ack <= 1'b0;
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;
end else if (state == `WBQSPI_PP)
begin // We come here under a full stop / full port idle mode
// Issue our command immediately
spi_wr <= 1'b1;
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;
spi_dir <= 1'b0; // Writing
spif_req<= (spif_req) && (i_wb_cyc);
 
// Once we get busy, move on
if (spi_busy)
state <= `WBQSPI_WR_DATA;
if (spif_sector == erased_sector)
dirty_sector <= 1'b1;
end else if (state == `WBQSPI_QPP)
begin // We come here under a full stop / full port idle mode
// Issue our command immediately
spi_wr <= 1'b1;
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;
spi_dir <= 1'b0; // Writing
spif_req<= (spif_req) && (i_wb_cyc);
 
// Once we get busy, move on
if (spi_busy)
begin
// spi_wr is irrelevant here ...
// Set the speed value once, but wait til we get busy
// to do so.
spi_spd <= 1'b1;
state <= `WBQSPI_WR_DATA;
end
if (spif_sector == erased_sector)
dirty_sector <= 1'b1;
end else if (state == `WBQSPI_WR_DATA)
begin
o_wb_stall <= 1'b1;
o_wb_ack <= 1'b0;
spi_wr <= 1'b1; // write without waiting
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)
begin
o_wb_ack <= spif_req; // Ack when command given
state <= `WBQSPI_WR_BUS_CYCLE;
end
spif_req<= (spif_req) && (i_wb_cyc);
end else if (state == `WBQSPI_WR_BUS_CYCLE)
begin
o_wb_ack <= 1'b0; // Turn off our ack and stall flags
o_wb_stall <= 1'b1;
spi_wr <= 1'b0;
spi_hold <= 1'b1;
write_in_progress <= 1'b1;
spif_req<= (spif_req) && (i_wb_cyc);
if (~i_wb_cyc)
begin
state <= `WBQSPI_WAIT_TIL_IDLE;
spi_hold <= 1'b0;
end else if (spi_wr)
begin // Give the SPI a chance to get busy on the last write
// Do nothing here.
end else if ((i_wb_data_stb)&&(i_wb_we)
&&(i_wb_addr == (spif_addr+1))
&&(i_wb_addr[(ADDRESS_WIDTH-3):6]==spif_addr[(ADDRESS_WIDTH-3):6]))
begin
spif_cmd <= 1'b1;
spif_data <= i_wb_data;
spif_addr <= i_wb_addr;
spif_ctrl <= 1'b0;
spif_req<= 1'b1;
// We'll keep the bus stalled on this request
// for a while
state <= `WBQSPI_WR_DATA;
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b0;
end else if ((i_wb_data_stb|i_wb_ctrl_stb)&&(~o_wb_ack)) // Writing out of bounds
begin
spi_hold <= 1'b0;
spi_wr <= 1'b0;
state <= `WBQSPI_WAIT_TIL_IDLE;
end // Otherwise we stay here
end else if (state == `WBQSPI_WRITE_CONFIG)
begin // We enter immediately after commanding a WEN
o_wb_ack <= 1'b0;
1102,7 → 1036,7
// together with setting our copy of the WIP bit
write_in_progress <= 1'b1;
// keeping track of which sector we just erased
erased_sector <= spif_data[(ADDRESS_WIDTH-3):14];
erased_sector <= spif_data[19:14];
// and marking this erase sector as no longer dirty
dirty_sector <= 1'b0;
 
1166,7 → 1100,6
o_wb_ack <= 1'b0;
state <= `WBQSPI_IDLE;
end
`endif // !READ_ONLY
end else // if (state == `WBQSPI_WAIT_TIL_IDLE) or anything else
begin
spi_wr <= 1'b0;
/llqspi.v
76,10 → 76,6
output reg [3:0] o_dat;
input [3:0] i_dat;
 
// output wire [22:0] o_dbg;
// assign o_dbg = { state, spi_len,
// o_busy, o_valid, o_cs_n, o_sck, o_mod, o_dat, i_dat };
 
// Timing:
//
// Tick Clk BSY/WR CS_n BIT/MO STATE

powered by: WebSVN 2.1.0

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