OpenCores
URL https://opencores.org/ocsvn/qspiflash/qspiflash/trunk

Subversion Repositories qspiflash

[/] [qspiflash/] [trunk/] [rtl/] [wbqspiflash.v] - Diff between revs 4 and 7

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 4 Rev 7
Line 49... Line 49...
// License:     GPL, v3, as defined and found on www.gnu.org,
// License:     GPL, v3, as defined and found on www.gnu.org,
//              http://www.gnu.org/licenses/gpl.html
//              http://www.gnu.org/licenses/gpl.html
//
//
//
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
 
//
 
`include "flash_config.v"
 
//
`define WBQSPI_RESET            0
`define WBQSPI_RESET            0
`define WBQSPI_RESET_QUADMODE   1
`define WBQSPI_RESET_QUADMODE   1
`define WBQSPI_IDLE             2
`define WBQSPI_IDLE             2
`define WBQSPI_RDIDLE           3       // Idle, but in fast read mode
`define WBQSPI_RDIDLE           3       // Idle, but in fast read mode
`define WBQSPI_WBDECODE         4
`define WBQSPI_WBDECODE         4
`define WBQSPI_WAIT_WIP_CLEAR   5
`define WBQSPI_RD_DUMMY         5
`define WBQSPI_CHECK_WIP_CLEAR  6
`define WBQSPI_QRD_ADDRESS      6
`define WBQSPI_CHECK_WIP_DONE   7
`define WBQSPI_QRD_DUMMY        7
`define WBQSPI_WEN              8
`define WBQSPI_READ_CMD         8
`define WBQSPI_PP               9       // Program page
`define WBQSPI_READ_DATA        9
`define WBQSPI_QPP              10      // Program page, 4 bit mode
`define WBQSPI_WAIT_TIL_RDIDLE  10
`define WBQSPI_WR_DATA          11
`define WBQSPI_READ_ID_CMD      11
`define WBQSPI_WR_BUS_CYCLE     12
`define WBQSPI_READ_ID          12
`define WBQSPI_RD_DUMMY         13
`define WBQSPI_READ_STATUS      13
`define WBQSPI_QRD_ADDRESS      14
`define WBQSPI_READ_CONFIG      14
`define WBQSPI_QRD_DUMMY        15
`define WBQSPI_WAIT_TIL_IDLE    15
`define WBQSPI_READ_CMD         16
//
`define WBQSPI_READ_DATA        17
//
`define WBQSPI_WAIT_TIL_RDIDLE  18
`ifndef READ_ONLY
`define WBQSPI_READ_ID_CMD      19
//
`define WBQSPI_READ_ID          20
`define WBQSPI_WAIT_WIP_CLEAR   16
`define WBQSPI_READ_STATUS      21
`define WBQSPI_CHECK_WIP_CLEAR  17
`define WBQSPI_READ_CONFIG      22
`define WBQSPI_CHECK_WIP_DONE   18
`define WBQSPI_WRITE_STATUS     23
`define WBQSPI_WEN              19
`define WBQSPI_WRITE_CONFIG     24
`define WBQSPI_PP               20      // Program page
`define WBQSPI_ERASE_WEN        25
`define WBQSPI_QPP              21      // Program page, 4 bit mode
`define WBQSPI_ERASE_CMD        26
`define WBQSPI_WR_DATA          22
`define WBQSPI_ERASE_BLOCK      27
`define WBQSPI_WR_BUS_CYCLE     23
`define WBQSPI_CLEAR_STATUS     28
`define WBQSPI_WRITE_STATUS     24
`define WBQSPI_IDLE_CHECK_WIP   29
`define WBQSPI_WRITE_CONFIG     25
`define WBQSPI_WAIT_TIL_IDLE    30
`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
 
 
module  wbqspiflash(i_clk_100mhz,
module  wbqspiflash(i_clk_100mhz,
                // Internal wishbone connections
                // Internal wishbone connections
                i_wb_cyc, i_wb_data_stb, i_wb_ctrl_stb, i_wb_we,
                i_wb_cyc, i_wb_data_stb, i_wb_ctrl_stb, i_wb_we,
                i_wb_addr, i_wb_data,
                i_wb_addr, i_wb_data,
                // Wishbone return values
                // Wishbone return values
                o_wb_ack, o_wb_stall, o_wb_data,
                o_wb_ack, o_wb_stall, o_wb_data,
                // Quad Spi connections to the external device
                // Quad Spi connections to the external device
                o_qspi_sck, o_qspi_cs_n, o_qspi_mod, o_qspi_dat, i_qspi_dat,
                o_qspi_sck, o_qspi_cs_n, o_qspi_mod, o_qspi_dat, i_qspi_dat,
                o_interrupt);
                o_interrupt);
 
        parameter       ADDRESS_WIDTH=22;
        input                   i_clk_100mhz;
        input                   i_clk_100mhz;
        // Wishbone, inputs first
        // Wishbone, inputs first
        input                   i_wb_cyc, i_wb_data_stb, i_wb_ctrl_stb, i_wb_we;
        input                   i_wb_cyc, i_wb_data_stb, i_wb_ctrl_stb, i_wb_we;
        input           [19:0]   i_wb_addr;
        input           [(ADDRESS_WIDTH-3):0]    i_wb_addr;
        input           [31:0]   i_wb_data;
        input           [31:0]   i_wb_data;
        // then outputs
        // then outputs
        output  reg             o_wb_ack;
        output  reg             o_wb_ack;
        output  reg             o_wb_stall;
        output  reg             o_wb_stall;
        output  reg     [31:0]   o_wb_data;
        output  reg     [31:0]   o_wb_data;
Line 106... Line 116...
        output  wire    [1:0]    o_qspi_mod;
        output  wire    [1:0]    o_qspi_mod;
        output  wire    [3:0]    o_qspi_dat;
        output  wire    [3:0]    o_qspi_dat;
        input           [3:0]    i_qspi_dat;
        input           [3:0]    i_qspi_dat;
        // Interrupt line
        // Interrupt line
        output  reg             o_interrupt;
        output  reg             o_interrupt;
 
        // output       wire    [31:0]  o_debug;
 
 
        reg             spi_wr, spi_hold, spi_spd, spi_dir;
        reg             spi_wr, spi_hold, spi_spd, spi_dir;
        reg     [31:0]   spi_in;
        reg     [31:0]   spi_in;
        reg     [1:0]    spi_len;
        reg     [1:0]    spi_len;
        wire    [31:0]   spi_out;
        wire    [31:0]   spi_out;
        wire            spi_valid, spi_busy;
        wire            spi_valid, spi_busy;
        wire            w_qspi_sck, w_qspi_cs_n;
        wire            w_qspi_sck, w_qspi_cs_n;
        wire    [3:0]    w_qspi_dat;
        wire    [3:0]    w_qspi_dat;
        wire    [1:0]    w_qspi_mod;
        wire    [1:0]    w_qspi_mod;
 
        // wire [22:0]  spi_dbg;
        llqspi  lldriver(i_clk_100mhz,
        llqspi  lldriver(i_clk_100mhz,
                        spi_wr, spi_hold, spi_in, spi_len, spi_spd, spi_dir,
                        spi_wr, spi_hold, spi_in, spi_len, spi_spd, spi_dir,
                                spi_out, spi_valid, spi_busy,
                                spi_out, spi_valid, spi_busy,
                        w_qspi_sck, w_qspi_cs_n, w_qspi_mod, w_qspi_dat,
                        w_qspi_sck, w_qspi_cs_n, w_qspi_mod, w_qspi_dat,
                                i_qspi_dat);
                                i_qspi_dat);
 
 
        // Erase status tracking
        // Erase status tracking
        reg             write_in_progress, write_protect;
        reg             write_in_progress, write_protect;
        reg     [5:0]    erased_sector;
        reg     [(ADDRESS_WIDTH-17):0]   erased_sector;
        reg             dirty_sector;
        reg             dirty_sector;
        initial begin
        initial begin
                write_in_progress = 1'b0;
                write_in_progress = 1'b0;
                erased_sector = 6'h00;
                erased_sector = 0;
                dirty_sector  = 1'b1;
                dirty_sector  = 1'b1;
                write_protect = 1'b1;
                write_protect = 1'b1;
        end
        end
 
 
        reg     [7:0]    last_status;
        reg     [7:0]    last_status;
        reg             quad_mode_enabled;
        reg             quad_mode_enabled;
        reg             spif_cmd, spif_override;
        reg             spif_cmd, spif_override;
        reg     [19:0]   spif_addr;
        reg     [(ADDRESS_WIDTH-3):0]    spif_addr;
        reg     [31:0]   spif_data;
        reg     [31:0]   spif_data;
        reg     [5:0]    state;
        reg     [5:0]    state;
        reg             spif_ctrl, spif_req;
        reg             spif_ctrl, spif_req;
        wire    [5:0]    spif_sector;
        wire    [(ADDRESS_WIDTH-17):0]   spif_sector;
        assign  spif_sector = spif_addr[19:14];
        assign  spif_sector = spif_addr[(ADDRESS_WIDTH-3):14];
 
 
 
        // assign       o_debug = { spi_wr, spi_spd, spi_hold, state, spi_dbg };
 
 
        initial state = `WBQSPI_RESET;
        initial state = `WBQSPI_RESET;
        initial o_wb_ack   = 1'b0;
        initial o_wb_ack   = 1'b0;
        initial o_wb_stall = 1'b1;
        initial o_wb_stall = 1'b1;
        initial spi_wr     = 1'b0;
        initial spi_wr     = 1'b0;
Line 213... Line 227...
                if ((i_wb_data_stb)&&(i_wb_cyc))
                if ((i_wb_data_stb)&&(i_wb_cyc))
                begin
                begin
 
 
                        if (i_wb_we) // Request to write a page
                        if (i_wb_we) // Request to write a page
                        begin
                        begin
 
`ifdef  READ_ONLY
 
                                o_wb_ack <= 1'b1;
 
                                o_wb_stall <= 1'b0;
 
                        end else
 
`else
                                if((~write_protect)&&(~write_in_progress))
                                if((~write_protect)&&(~write_in_progress))
                                begin // 00
                                begin // 00
                                        spi_wr <= 1'b1;
                                        spi_wr <= 1'b1;
                                        spi_len <= 2'b00; // 8 bits
                                        spi_len <= 2'b00; // 8 bits
                                        // Send a write enable command
                                        // Send a write enable command
Line 237... Line 256...
                                        state <= `WBQSPI_WAIT_WIP_CLEAR;
                                        state <= `WBQSPI_WAIT_WIP_CLEAR;
                                        o_wb_ack <= 1'b0;
                                        o_wb_ack <= 1'b0;
                                        o_wb_stall <= 1'b1;
                                        o_wb_stall <= 1'b1;
                                end
                                end
                        end else if (~write_in_progress)
                        end else if (~write_in_progress)
 
`endif
                        begin // Read access, normal mode(s)
                        begin // Read access, normal mode(s)
                                o_wb_ack   <= 1'b0;
                                o_wb_ack   <= 1'b0;
                                o_wb_stall <= 1'b1;
                                o_wb_stall <= 1'b1;
                                spi_wr     <= 1'b1;     // Write cmd to device
                                spi_wr     <= 1'b1;     // Write cmd to device
                                if (quad_mode_enabled)
                                if (quad_mode_enabled)
                                begin
                                begin
                                        spi_in <= { 8'heb, 2'b00, i_wb_addr[19:0], 2'b00 };
                                        spi_in <= { 8'heb,
 
                                                {(24-ADDRESS_WIDTH){1'b0}},
 
                                                i_wb_addr[(ADDRESS_WIDTH-3):0], 2'b00 };
                                        state <= `WBQSPI_QRD_ADDRESS;
                                        state <= `WBQSPI_QRD_ADDRESS;
                                        spi_len    <= 2'b00; // single byte, cmd only
                                        spi_len    <= 2'b00; // single byte, cmd only
                                end else begin
                                end else begin
                                        spi_in <= { 8'h0b, 2'b00, i_wb_addr[19:0], 2'b00 };
                                        spi_in <= { 8'h0b,
 
                                                {(24-ADDRESS_WIDTH){1'b0}},
 
                                                i_wb_addr[(ADDRESS_WIDTH-3):0], 2'b00 };
                                        state <= `WBQSPI_RD_DUMMY;
                                        state <= `WBQSPI_RD_DUMMY;
                                        spi_len    <= 2'b11; // cmd+addr,32bits
                                        spi_len    <= 2'b11; // cmd+addr,32bits
                                end
                                end
 
`ifndef READ_ONLY
                        end else begin
                        end else begin
                                // A write is in progress ... need to stall
                                // A write is in progress ... need to stall
                                // the bus until the write is complete.
                                // the bus until the write is complete.
                                state <= `WBQSPI_WAIT_WIP_CLEAR;
                                state <= `WBQSPI_WAIT_WIP_CLEAR;
                                o_wb_ack   <= 1'b0;
                                o_wb_ack   <= 1'b0;
                                o_wb_stall <= 1'b1;
                                o_wb_stall <= 1'b1;
 
`endif
                        end
                        end
                end else if ((i_wb_cyc)&&(i_wb_ctrl_stb)&&(i_wb_we))
                end else if ((i_wb_cyc)&&(i_wb_ctrl_stb)&&(i_wb_we))
                begin
                begin
 
`ifdef  READ_ONLY
 
                        o_wb_ack   <= 1'b1;
 
                        o_wb_stall <= 1'b0;
 
`else
                        o_wb_stall <= 1'b1;
                        o_wb_stall <= 1'b1;
                        case(i_wb_addr[1:0])
                        case(i_wb_addr[1:0])
                        2'b00: begin // Erase command register
                        2'b00: begin // Erase command register
                                write_protect <= ~i_wb_data[28];
                                write_protect <= ~i_wb_data[28];
                                o_wb_stall <= 1'b0;
                                o_wb_stall <= 1'b0;
Line 319... Line 349...
                        2'b11: begin // Write the ID register??? makes no sense
                        2'b11: begin // Write the ID register??? makes no sense
                                o_wb_ack <= 1'b1;
                                o_wb_ack <= 1'b1;
                                o_wb_stall <= 1'b0;
                                o_wb_stall <= 1'b0;
                                end
                                end
                        endcase
                        endcase
 
`endif
                end else if ((i_wb_cyc)&&(i_wb_ctrl_stb)) // &&(~i_wb_we))
                end else if ((i_wb_cyc)&&(i_wb_ctrl_stb)) // &&(~i_wb_we))
                begin
                begin
                        case(i_wb_addr[1:0])
                        case(i_wb_addr[1:0])
                        2'b00: begin // Read local register
                        2'b00: begin // Read local register
                                if (write_in_progress) // Read status
                                if (write_in_progress) // Read status
Line 339... Line 370...
                                        o_wb_stall <= 1'b0;
                                        o_wb_stall <= 1'b0;
                                        o_wb_data <= { write_in_progress,
                                        o_wb_data <= { write_in_progress,
                                                dirty_sector, spi_busy,
                                                dirty_sector, spi_busy,
                                                ~write_protect,
                                                ~write_protect,
                                                quad_mode_enabled,
                                                quad_mode_enabled,
                                                7'h00,
                                                {(29-ADDRESS_WIDTH){1'b0}},
                                                erased_sector, 14'h000 };
                                                erased_sector, 14'h000 };
                                end end
                                end end
                        2'b01: begin // Read configuration register
                        2'b01: begin // Read configuration register
                                state <= `WBQSPI_READ_CONFIG;
                                state <= `WBQSPI_READ_CONFIG;
                                spi_wr <= 1'b1;
                                spi_wr <= 1'b1;
Line 370... Line 401...
 
 
                                o_wb_ack <= 1'b0;
                                o_wb_ack <= 1'b0;
                                o_wb_stall <= 1'b1;
                                o_wb_stall <= 1'b1;
                                end
                                end
                        endcase
                        endcase
 
`ifndef READ_ONLY
                end else if ((~i_wb_cyc)&&(write_in_progress))
                end else if ((~i_wb_cyc)&&(write_in_progress))
                begin
                begin
                        state <= `WBQSPI_IDLE_CHECK_WIP;
                        state <= `WBQSPI_IDLE_CHECK_WIP;
                        spi_wr <= 1'b1;
                        spi_wr <= 1'b1;
                        spi_len <= 2'b01; // 8 bits out, 8 bits in
                        spi_len <= 2'b01; // 8 bits out, 8 bits in
                        spi_in <= { 8'h05, 24'h00};
                        spi_in <= { 8'h05, 24'h00};
 
 
                        o_wb_ack <= 1'b0;
                        o_wb_ack <= 1'b0;
                        o_wb_stall <= 1'b1;
                        o_wb_stall <= 1'b1;
 
`endif
                end
                end
        end else if (state == `WBQSPI_RDIDLE)
        end else if (state == `WBQSPI_RDIDLE)
        begin
        begin
                spi_wr <= 1'b0;
                spi_wr <= 1'b0;
                o_wb_stall <= 1'b0;
                o_wb_stall <= 1'b0;
Line 398... Line 431...
                if ((i_wb_cyc)&&(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
                begin // Continue our read ... send the new address / mode
                        o_wb_stall <= 1'b1;
                        o_wb_stall <= 1'b1;
                        spi_wr <= 1'b1;
                        spi_wr <= 1'b1;
                        spi_len <= 2'b10; // Write address, but not mode byte
                        spi_len <= 2'b10; // Write address, but not mode byte
                        spi_in <= { 2'h0, i_wb_addr[19:0], 2'h0, 8'ha0 };
                        spi_in <= { {(24-ADDRESS_WIDTH){1'b0}},
 
                                        i_wb_addr[(ADDRESS_WIDTH-3):0], 2'b00, 8'ha0 };
                        state <= `WBQSPI_QRD_DUMMY;
                        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_cyc)&&(i_wb_ctrl_stb)&&(~i_wb_we)&&(i_wb_addr[1:0] == 2'b00))
                begin
                begin
                        // A local read that doesn't touch the device, so leave
                        // A local read that doesn't touch the device, so leave
                        // the device in its current state
                        // the device in its current state
Line 410... Line 444...
                        o_wb_ack <= 1'b1;
                        o_wb_ack <= 1'b1;
                        o_wb_data <= { write_in_progress,
                        o_wb_data <= { write_in_progress,
                                        dirty_sector, spi_busy,
                                        dirty_sector, spi_busy,
                                        ~write_protect,
                                        ~write_protect,
                                        quad_mode_enabled,
                                        quad_mode_enabled,
                                        7'h00,
                                        {(29-ADDRESS_WIDTH){1'b0}},
                                        erased_sector, 14'h000 };
                                        erased_sector, 14'h000 };
                end else if((i_wb_cyc)&&((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
                begin // Need to release the device from quad mode for all else
                        o_wb_ack   <= 1'b0;
                        o_wb_ack   <= 1'b0;
                        o_wb_stall <= 1'b1;
                        o_wb_stall <= 1'b1;
Line 443... Line 477...
                        // Data register access
                        // Data register access
                        if (~spif_ctrl)
                        if (~spif_ctrl)
                        begin
                        begin
                                if (spif_cmd) // Request to write a page
                                if (spif_cmd) // Request to write a page
                                begin
                                begin
 
`ifdef  READ_ONLY
 
                                        o_wb_ack <= spif_req;
 
                                        o_wb_stall <= 1'b0;
 
                                        state <= `WBQSPI_IDLE;
 
`else
                                        if((~write_protect)&&(~write_in_progress))
                                        if((~write_protect)&&(~write_in_progress))
                                        begin // 00
                                        begin // 00
                                                spi_wr <= 1'b1;
                                                spi_wr <= 1'b1;
                                                spi_len <= 2'b00; // 8 bits
                                                spi_len <= 2'b00; // 8 bits
                                                // Send a write enable command
                                                // Send a write enable command
Line 469... Line 508...
                                                o_wb_ack <= 1'b0;
                                                o_wb_ack <= 1'b0;
                                                o_wb_stall <= 1'b1;
                                                o_wb_stall <= 1'b1;
                                        end
                                        end
                                // end else if (~write_in_progress) // always true
                                // end else if (~write_in_progress) // always true
                                // but ... we wouldn't get here on a normal read access
                                // but ... we wouldn't get here on a normal read access
 
`endif
                                end else begin
                                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
                                        // Attempt to go to idle to recover
                                        state <= `WBQSPI_IDLE;
                                        state <= `WBQSPI_IDLE;
                                end
                                end
                        end else if ((spif_ctrl)&&(spif_cmd))
                        end else if ((spif_ctrl)&&(spif_cmd))
                        begin
                        begin
 
`ifdef  READ_ONLY
 
                                o_wb_ack   <= spif_req;
 
                                o_wb_stall <= 1'b0;
 
                                state <= `WBQSPI_IDLE;
 
`else
                                o_wb_stall <= 1'b1;
                                o_wb_stall <= 1'b1;
                                case(spif_addr[1:0])
                                case(spif_addr[1:0])
                                2'b00: begin // Erase command register
                                2'b00: begin // Erase command register
                                        o_wb_ack   <= spif_req;
                                        o_wb_ack   <= spif_req;
                                        o_wb_stall <= 1'b0;
                                        o_wb_stall <= 1'b0;
Line 527... Line 573...
                                        o_wb_ack <= spif_req;
                                        o_wb_ack <= spif_req;
                                        o_wb_stall <= 1'b0;
                                        o_wb_stall <= 1'b0;
                                        state <= `WBQSPI_IDLE;
                                        state <= `WBQSPI_IDLE;
                                        end
                                        end
                                endcase
                                endcase
 
`endif
                        end else begin // on (~spif_we)
                        end else begin // on (~spif_we)
                                case(spif_addr[1:0])
                                case(spif_addr[1:0])
                                2'b00: begin // Read local register
                                2'b00: begin // Read local register
                                        // Nonsense case--would've done this
                                        // Nonsense case--would've done this
                                        // already
                                        // already
Line 566... Line 613...
                                        o_wb_stall <= 1'b1;
                                        o_wb_stall <= 1'b1;
                                        end
                                        end
                                endcase
                                endcase
                        end
                        end
                end
                end
        end else if (state == `WBQSPI_WAIT_WIP_CLEAR)
//
        begin
//
                o_wb_stall <= 1'b1;
//      READ DATA section: for both data and commands
                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)
        end else if (state == `WBQSPI_RD_DUMMY)
        begin
        begin
                o_wb_ack   <= 1'b0;
                o_wb_ack   <= 1'b0;
                o_wb_stall <= 1'b1;
                o_wb_stall <= 1'b1;
 
 
Line 789... Line 643...
                // address (24-bits) and mode (8-bits) in quad speed.
                // address (24-bits) and mode (8-bits) in quad speed.
                o_wb_ack   <= 1'b0;
                o_wb_ack   <= 1'b0;
                o_wb_stall <= 1'b1;
                o_wb_stall <= 1'b1;
 
 
                spi_wr <= 1'b1; // Non-stop
                spi_wr <= 1'b1; // Non-stop
                spi_in <= { 2'b0, spif_addr, 2'b0, 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_len <= 2'b10; // Write address, not mode byte
                spi_spd <= 1'b1;
                spi_spd <= 1'b1;
                spi_dir <= 1'b0; // Still writing
                spi_dir <= 1'b0; // Still writing
                spi_hold <= 1'b0;
                spi_hold <= 1'b0;
                spif_req<= (spif_req) && (i_wb_cyc);
                spif_req<= (spif_req) && (i_wb_cyc);
Line 948... Line 803...
                        begin // status, 'cause we're writing
                        begin // status, 'cause we're writing
                                o_wb_data <= { spi_out[0],
                                o_wb_data <= { spi_out[0],
                                        dirty_sector, spi_busy,
                                        dirty_sector, spi_busy,
                                        ~write_protect,
                                        ~write_protect,
                                        quad_mode_enabled,
                                        quad_mode_enabled,
                                        7'h00,
                                        {(29-ADDRESS_WIDTH){1'b0}},
                                        erased_sector, 14'h000 };
                                        erased_sector, 14'h000 };
                        end else begin
                        end else begin
                                o_wb_data <= { 24'h00, spi_out[7:0] };
                                o_wb_data <= { 24'h00, spi_out[7:0] };
                        end
                        end
                end
                end
Line 979... Line 834...
                        state <= `WBQSPI_IDLE;
                        state <= `WBQSPI_IDLE;
                        o_wb_ack   <= spif_req;
                        o_wb_ack   <= spif_req;
                        o_wb_stall <= 1'b0;
                        o_wb_stall <= 1'b0;
                        spif_req <= 1'b0;
                        spif_req <= 1'b0;
                end
                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)
        end else if (state == `WBQSPI_WRITE_CONFIG)
        begin // We enter immediately after commanding a WEN
        begin // We enter immediately after commanding a WEN
                o_wb_ack   <= 1'b0;
                o_wb_ack   <= 1'b0;
                o_wb_stall <= 1'b1;
                o_wb_stall <= 1'b1;
 
 
Line 1034... Line 1100...
                spi_in <= { 8'hd8, 2'h0, spif_data[19:14], 14'h000, 2'b00 };
                spi_in <= { 8'hd8, 2'h0, spif_data[19:14], 14'h000, 2'b00 };
                spi_len <= 2'b11; // 32 bit write
                spi_len <= 2'b11; // 32 bit write
                // together with setting our copy of the WIP bit
                // together with setting our copy of the WIP bit
                write_in_progress <= 1'b1;
                write_in_progress <= 1'b1;
                // keeping track of which sector we just erased
                // keeping track of which sector we just erased
                erased_sector <= spif_data[19:14];
                erased_sector <= spif_data[(ADDRESS_WIDTH-3):14];
                // and marking this erase sector as no longer dirty
                // and marking this erase sector as no longer dirty
                dirty_sector <= 1'b0;
                dirty_sector <= 1'b0;
 
 
                // Wait for a full stop before issuing this command
                // Wait for a full stop before issuing this command
                if ((~spi_busy)&&(~spi_wr)&&(o_qspi_cs_n))
                if ((~spi_busy)&&(~spi_wr)&&(o_qspi_cs_n))
Line 1098... Line 1164...
                begin // We can now go to idle and process a command
                begin // We can now go to idle and process a command
                        o_wb_stall <= 1'b0;
                        o_wb_stall <= 1'b0;
                        o_wb_ack   <= 1'b0;
                        o_wb_ack   <= 1'b0;
                        state <= `WBQSPI_IDLE;
                        state <= `WBQSPI_IDLE;
                end
                end
 
`endif //       !READ_ONLY
        end else // if (state == `WBQSPI_WAIT_TIL_IDLE) or anything else
        end else // if (state == `WBQSPI_WAIT_TIL_IDLE) or anything else
        begin
        begin
                spi_wr     <= 1'b0;
                spi_wr     <= 1'b0;
                spi_hold   <= 1'b0;
                spi_hold   <= 1'b0;
                o_wb_stall <= 1'b1;
                o_wb_stall <= 1'b1;

powered by: WebSVN 2.1.0

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