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 11 to Rev 14
    Reverse comparison

Rev 11 → Rev 14

/eqspiflash.v
63,7 → 63,8
// 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.-14. Unused, mapped to Asynch-read-ID
// 13. Reset Enable
// 14. Reset Memory
// 15. OTP control word
// Write zero to permanently lock OTP
// Read to determine if OTP is permanently locked
178,7 → 179,7
bus_pipewr, bus_endwr, bus_ctreq, bus_idreq,
bus_other_req,
// Live parameters
w_xip, w_quad, w_idloaded;
w_xip, w_quad, w_idloaded, w_leave_xip;
reg bus_wip;
qspibus preproc(i_clk_200mhz, i_rst,
i_wb_cyc, i_wb_data_stb, i_wb_ctrl_stb,
218,7 → 219,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_quad, w_xip, w_leave_xip);
 
//
// Write/Erase flash module
268,12 → 269,12
wire [1:0] ct_spi_len;
//
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_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_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_spd = 1'b0;
 
504,6 → 505,8
||(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;
510,7 → 513,6
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))
529,14 → 531,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: o_idreq <= 1'b1; //
5'he: o_idreq <= 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: lcl_ctreq <= 1'b1; //
5'he: lcl_ctreq <= 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)
559,9 → 561,9
lcl_wrreq <= 1'b0;
end
 
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)))
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))
o_piperd <= 1'b0;
if ((i_data_stb)&&(~o_wb_stall))
pipeable <= (~i_we);
581,6 → 583,7
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;
612,9 → 615,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
701,7 → 704,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_data_ack, o_data, i_quad, i_xip, o_leave_xip);
input i_clk;
input i_readreq, i_piperd, i_other_req;
input [21:0] i_addr;
717,6 → 720,7
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;
786,13 → 790,13
rd_state <= `RD_GO_TO_IDLE;
end
`RD_QUAD_READ_DATA: begin
o_qspi_req <= 1'b1;
o_spi_dir <= 1'b1;
o_spi_spd <= 1'b1;
o_spi_len <= 2'b11;
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_spi_recycle <= (r_leave_xip)? 1'b1: 1'b0;
invalid_ack_pipe[0] <= (!r_requested);
r_requested <= (r_requested)||(accepted);
r_requested <= (r_requested)||(accepted); // Make sure at least one request goes through
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);
868,6 → 872,7
end
 
assign o_spi_hold = 1'b0;
assign o_leave_xip = r_leave_xip;
 
endmodule
 
1119,12 → 1124,13
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, o_xip, o_quad);
o_bus_ack, o_data_ack, o_data,
i_leave_xip, o_xip, o_quad);
input i_clk;
// From the WB bus controller
input i_req;
input i_wr;
input [2:0] i_addr;
input [3:0] i_addr;
input [31:0] i_data;
input [21:0] i_sector_address;
// To/from the arbiter
1144,6 → 1150,7
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;
 
1181,13 → 1188,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[2:0], i_wr, i_data[30] })
5'b00010: begin // Write Disable
casez({ i_addr[3:0], i_wr, i_data[30] })
6'b000010: begin // Write Disable
ctcmd_word[31:24] <= 8'h04;
ctdat_skip <= 1'b1;
ctbus_ack <= 1'b0;
end
5'b00011: begin // Write enable
6'b000011: begin // Write enable
ctcmd_word[31:24] <= 8'h06;
ctdat_skip <= 1'b1;
ctbus_ack <= 1'b0;
1194,7 → 1201,7
end
// 4'b0010?: begin // Read Status register
// 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;
`ifdef CT_SAFE
ctdat_word <= { 6'h00, i_data[1:0], 24'h00 };
1202,11 → 1209,11
ctdat_word <= { i_data[7:0], 24'h00 };
`endif
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;
r_ctdat_len <= 1'b1; // 16-bit data
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;
r_ctdat_len <= 1'b1; // 16-bit data
`ifdef CT_SAFE
1215,10 → 1222,10
ctdat_word <= { i_data[15:0], 16'h00 };
`endif
end
5'b0110?: begin // Read V-Config register
6'b00110?: begin // Read V-Config register
ctcmd_word[31:24] <= 8'h85;
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;
r_ctdat_len <= 1'b0; // 8-bit data
`ifdef CT_SAFE
1226,12 → 1233,12
`else
ctdat_word <= { i_data[7:0], 24'h00 };
`endif
o_xip <= i_data[3];
o_xip <= ~i_data[3];
end
5'b1000?: begin // Read EV-Config register
6'b01000?: begin // Read EV-Config register
ctcmd_word[31:24] <= 8'h65;
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;
// o_quad <= (~i_data[7]);
`ifdef CT_SAFE
1240,24 → 1247,32
ctdat_word <= { i_data[7:0], 24'h00 };
`endif
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_len <= 2'b11;
ctdat_wr <= 1'b0; // Read, not write
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_len <= 2'b11;
ctdat_wr <= 1'b1; // Write
end
5'b1100?: begin // Read Flag Status register
6'b01100?: begin // Read Flag Status register
ctcmd_word[31:24] <= 8'h70;
ctdat_wr <= 1'b0; // Read, not write
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;
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
1264,7 → 1279,8
r_ctdat_len <= 1'b0; // 8-bit data
end
endcase
end
end else if (i_leave_xip)
o_xip <= 1'b0;
 
assign o_quad = 1'b1;
 
/llqspi.v
37,6 → 37,10
//
//
///////////////////////////////////////////////////////////////////////////
//
//
`default_nettype none
//
`define QSPI_IDLE 3'h0
`define QSPI_START 3'h1
`define QSPI_BITS 3'h2
56,17 → 60,17
o_word, o_valid, o_busy,
// QSPI interface
o_sck, o_cs_n, o_mod, o_dat, i_dat);
input i_clk;
input wire 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 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
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
output reg [31:0] o_word;
output reg o_valid, o_busy;
// Interface with the QSPI lines
/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
// Creator: Dan Gisselquist, Ph.D.
// Gisselquist Technology, LLC
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
// Copyright (C) 2015,2017, 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,45 → 50,46
// http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
`include "flash_config.v"
`default_nettype none
//
`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
`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
//
//
`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
`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
//
`endif
 
102,11 → 103,11
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;
input wire 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 [31:0] i_wb_data;
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;
// then outputs
output reg o_wb_ack;
output reg o_wb_stall;
115,7 → 116,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 [3:0] i_qspi_dat;
input wire [3:0] i_qspi_dat;
// Interrupt line
output reg o_interrupt;
// output wire [31:0] o_debug;
146,12 → 147,29
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 [5:0] state;
reg [4:0] state;
reg spif_ctrl, spif_req;
wire [(ADDRESS_WIDTH-17):0] spif_sector;
assign spif_sector = spif_addr[(ADDRESS_WIDTH-3):14];
193,7 → 211,9
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
// So, thus we need to toggle the clock and CS_n, with fewer
// clocks than are necessary to transmit a word.
//
// Not ready to handle the bus yet, so stall any requests
o_wb_ack <= 1'b0;
o_wb_stall <= 1'b1;
224,7 → 244,7
spi_spd <= 1'b0;
spi_dir <= 1'b0; // Write (for now, 'cause of cmd)
// Data register access
if ((i_wb_data_stb)&&(i_wb_cyc))
if (i_wb_data_stb)
begin
 
if (i_wb_we) // Request to write a page
265,15 → 285,11
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, w_wb_addr };
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, w_wb_addr };
state <= `WBQSPI_RD_DUMMY;
spi_len <= 2'b11; // cmd+addr,32bits
end
286,7 → 302,7
o_wb_stall <= 1'b1;
`endif
end
end else if ((i_wb_cyc)&&(i_wb_ctrl_stb)&&(i_wb_we))
end else if ((i_wb_ctrl_stb)&&(i_wb_we))
begin
`ifdef READ_ONLY
o_wb_ack <= 1'b1;
352,7 → 368,7
end
endcase
`endif
end else if ((i_wb_cyc)&&(i_wb_ctrl_stb)) // &&(~i_wb_we))
end else if (i_wb_ctrl_stb) // &&(~i_wb_we))
begin
case(i_wb_addr[1:0])
2'b00: begin // Read local register
428,15 → 444,14
spi_hold <= 1'b0;
spi_spd<= 1'b1;
spi_dir <= 1'b0; // Write (for now)
if ((i_wb_cyc)&&(i_wb_data_stb)&&(~i_wb_we))
if ((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 <= { {(24-ADDRESS_WIDTH){1'b0}},
i_wb_addr[(ADDRESS_WIDTH-3):0], 2'b00, 8'ha0 };
spi_in <= { w_wb_addr, 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))
end else if((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
448,7 → 463,7
quad_mode_enabled,
{(29-ADDRESS_WIDTH){1'b0}},
erased_sector, 14'h000 };
end else if((i_wb_cyc)&&((i_wb_ctrl_stb)||(i_wb_data_stb)))
end else if(((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;
645,8 → 660,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 <= { w_spif_addr, 8'ha0 };
spi_len <= 2'b10; // Write address, not mode byte
spi_spd <= 1'b1;
spi_dir <= 1'b0; // Still writing
688,7 → 702,7
end else if (state == `WBQSPI_READ_DATA)
begin
// Pipelined read support
spi_wr <=((i_wb_cyc)&&(i_wb_data_stb)&&(~i_wb_we)&&(i_wb_addr== (spif_addr+1)));
spi_wr <=((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
712,8 → 726,7
o_wb_ack <= spif_req;
o_wb_stall <= (~spi_wr);
// adjust endian-ness to match the PC
o_wb_data <= { spi_out[7:0], spi_out[15:8],
spi_out[23:16], spi_out[31:24] };
o_wb_data <= spi_out;
state <= (spi_wr)?`WBQSPI_READ_DATA
: ((spi_spd) ? `WBQSPI_WAIT_TIL_RDIDLE : `WBQSPI_WAIT_TIL_IDLE);
spif_req <= spi_wr;
900,15 → 913,11
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 };
spi_in <= { 8'heb, w_spif_addr };
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 };
spi_in <= { 8'h0b, w_spif_addr };
state <= `WBQSPI_RD_DUMMY;
spi_len <= 2'b11; // Send cmd and addr
end end
956,9 → 965,7
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_in <= { 8'h02, w_spif_addr };
spi_len <= 2'b11;
spi_hold <= 1'b1;
spi_spd <= 1'b0;
974,9 → 981,7
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_in <= { 8'h32, w_spif_addr };
spi_len <= 2'b11;
spi_hold <= 1'b1;
spi_spd <= 1'b0;
999,11 → 1004,7
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_in <= spif_data;
spi_len <= 2'b11; // Write 4 bytes
spi_hold <= 1'b1;
if (~spi_busy)
/.
. Property changes : Added: svn:ignore ## -0,0 +1 ## +obj_dir

powered by: WebSVN 2.1.0

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