URL
https://opencores.org/ocsvn/qspiflash/qspiflash/trunk
Subversion Repositories qspiflash
Compare Revisions
- This comparison shows the changes necessary to convert path
/qspiflash/trunk
- from Rev 14 to Rev 15
- ↔ Reverse comparison
Rev 14 → Rev 15
/bench/cpp/qspiflashsim.cpp
1,25 → 1,24
/////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
// Filename: spiflashsim.cpp |
// Filename: qspiflashsim.cpp |
// |
// Project: Wishbone Controlled Quad SPI Flash Controller |
// |
// Purpose: This library simulates the operation of a Quad-SPI commanded |
// flash, such as the S25FL032P used on the Basys-3 development |
// board by Digilent. As such, it is defined by 32 Mbits of |
// memory (4 Mbyte). |
// board by Digilent. |
// |
// This simulator is useful for testing in a Verilator/C++ |
// environment, where this simulator can be used in place of |
// the actual hardware. |
// |
// 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 |
32,7 → 31,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. |
// |
40,16 → 39,17
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#include <stdio.h> |
#include <string.h> |
#include <assert.h> |
#include <stdlib.h> |
#include <stdint.h> |
|
#include "qspiflashsim.h" |
|
#define MEMBYTES (1<<22) |
|
static const unsigned DEVID = 0x0115, |
DEVESD = 0x014, |
MICROSECONDS = 100, |
66,8 → 66,10
// tPP = 1200 * MICROSECONDS, |
// tSE = 1500 * MILLISECONDS; |
|
QSPIFLASHSIM::QSPIFLASHSIM(void) { |
m_mem = new char[MEMBYTES]; |
QSPIFLASHSIM::QSPIFLASHSIM(const int lglen, bool debug) { |
m_membytes = (1<<lglen); |
m_memmask = (m_membytes - 1); |
m_mem = new char[m_membytes]; |
m_pmem = new char[256]; |
m_state = QSPIF_IDLE; |
m_last_sck = 1; |
78,19 → 80,21
m_quad_mode = false; |
m_mode_byte = 0; |
|
memset(m_mem, 0x0ff, MEMBYTES); |
memset(m_mem, 0x0ff, m_membytes); |
} |
|
void QSPIFLASHSIM::load(const unsigned addr, const char *fname) { |
FILE *fp; |
size_t len; |
int nr = 0; |
|
if (addr >= MEMBYTES) |
if (addr >= m_membytes) |
return; |
len = MEMBYTES-addr*4; |
// If not given, then length is from the given address until the end |
// of the flash memory |
len = m_membytes-addr*4; |
|
if (NULL != (fp = fopen(fname, "r"))) { |
int nr = 0; |
nr = fread(&m_mem[addr], sizeof(char), len, fp); |
fclose(fp); |
if (nr == 0) { |
101,8 → 105,17
fprintf(stderr, "SPI-FLASH: Could not open %s\n", fname); |
perror("O/S Err:"); |
} |
|
for(unsigned i=nr; i<m_membytes; i++) |
m_mem[i] = 0x0ff; |
} |
|
void QSPIFLASHSIM::load(const uint32_t offset, const char *data, const uint32_t len) { |
uint32_t moff = (offset & (m_memmask)); |
|
memcpy(&m_mem[moff], data, len); |
} |
|
#define QOREG(A) m_oreg = ((m_oreg & (~0x0ff))|(A&0x0ff)) |
|
int QSPIFLASHSIM::operator()(const int csn, const int sck, const int dat) { |
165,7 → 178,7
m_state = QSPIF_IDLE; |
m_sreg &= (~QSPIF_WEL_FLAG); |
m_sreg |= (QSPIF_WIP_FLAG); |
for(int i=0; i<MEMBYTES; i++) |
for(unsigned i=0; i<m_membytes; i++) |
m_mem[i] = 0x0ff; |
} else if (m_state == QSPIF_DEEP_POWER_DOWN) { |
m_write_count = tDP; |
219,8 → 232,8
if (m_count == 24) { |
if (m_debug) printf("QSPI: Entering from Quad-Read Idle to Quad-Read\n"); |
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_addr = (m_ireg) & m_memmask; |
assert((m_addr & (~(m_memmask)))==0); |
m_state = QSPIF_QUAD_READ; |
} m_oreg = 0; |
} else if (m_count == 8) { |
362,7 → 375,7
break; |
case QSPIF_RDID: |
if (m_count == 32) { |
m_addr = m_ireg & 0x0ffffff; |
m_addr = m_ireg & m_memmask; |
if (m_debug) printf("READID, ADDR = %08x\n", m_addr); |
QOREG((DEVID>>8)); |
if (m_debug) printf("QSPI: READING ID, %02x\n", (DEVID>>8)&0x0ff); |
386,10 → 399,10
break; |
case QSPIF_FAST_READ: |
if (m_count == 32) { |
m_addr = m_ireg & 0x0ffffff; |
m_addr = m_ireg & m_memmask; |
if (m_debug) printf("FAST READ, ADDR = %08x\n", m_addr); |
QOREG(0x0c3); |
assert((m_addr & 0xfc00000)==0); |
assert((m_addr & (~(m_memmask)))==0); |
} else if ((m_count >= 40)&&(0 == (m_sreg&0x01))) { |
//if (m_count == 40) |
//printf("DUMMY BYTE COMPLETE ...\n"); |
402,10 → 415,10
// that changes the timings, else we'd use quad_Read |
// below |
if (m_count == 32) { |
m_addr = m_ireg & 0x0ffffff; |
m_addr = m_ireg & m_memmask; |
// printf("FAST READ, ADDR = %08x\n", m_addr); |
// printf("QSPI: QUAD READ, ADDR = %06x\n", m_addr); |
assert((m_addr & 0xfc00000)==0); |
assert((m_addr & (~(m_memmask)))==0); |
} else if (m_count == 32+24) { |
m_mode_byte = (m_ireg>>16) & 0x0ff; |
// printf("QSPI: MODE BYTE = %02x\n", m_mode_byte); |
426,9 → 439,9
break; |
case QSPIF_PP: |
if (m_count == 32) { |
m_addr = m_ireg & 0x0ffffff; |
m_addr = m_ireg & m_memmask; |
if (m_debug) printf("QSPI: PAGE-PROGRAM ADDR = %06x\n", m_addr); |
assert((m_addr & 0xfc00000)==0); |
assert((m_addr & (~(m_memmask)))==0); |
// m_page = m_addr >> 8; |
for(int i=0; i<256; i++) |
m_pmem[i] = 0x0ff; |
439,10 → 452,10
} break; |
case QSPIF_QPP: |
if (m_count == 32) { |
m_addr = m_ireg & 0x0ffffff; |
m_addr = m_ireg & m_memmask; |
m_quad_mode = true; |
if (m_debug) printf("QSPI/QR: PAGE-PROGRAM ADDR = %06x\n", m_addr); |
assert((m_addr & 0xfc00000)==0); |
assert((m_addr & (~(m_memmask)))==0); |
// m_page = m_addr >> 8; |
for(int i=0; i<256; i++) |
m_pmem[i] = 0x0ff; |
/bench/cpp/qspiflashsim.h
1,6 → 1,6
/////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// Filename: spiflashsim.h |
// Filename: qspiflashsim.h |
// |
// Project: Wishbone Controlled Quad SPI Flash Controller |
// |
9,12 → 9,12
// board by Digilent. As such, it is defined by 32 Mbits of |
// memory (4 Mbyte). |
// |
// 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 |
27,7 → 27,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. |
// |
35,7 → 35,9
// http://www.gnu.org/licenses/gpl.html |
// |
// |
/////////////////////////////////////////////////////////////////////////// |
//////////////////////////////////////////////////////////////////////////////// |
// |
// |
#ifndef QSPIFLASHSIM_H |
#define QSPIFLASHSIM_H |
|
67,15 → 69,33
char *m_mem, *m_pmem; |
int m_last_sck; |
unsigned m_write_count, m_ireg, m_oreg, m_sreg, m_addr, |
m_count, m_config, m_mode_byte, m_creg; |
m_count, m_config, m_mode_byte, m_creg, m_membytes, |
m_memmask; |
bool m_quad_mode, m_debug; |
|
public: |
QSPIFLASHSIM(void); |
QSPIFLASHSIM(const int lglen = 24, bool debug = false); |
void load(const char *fname) { load(0, fname); } |
void load(const unsigned addr, const char *fname); |
void load(const uint32_t offset, const char *data, const uint32_t len); |
void debug(const bool dbg) { m_debug = dbg; } |
bool debug(void) const { return m_debug; } |
unsigned operator[](const int index) { |
unsigned char *cptr = (unsigned char *)&m_mem[index<<2]; |
unsigned v; |
v = (*cptr++); |
v = (v<<8)|(*cptr++); |
v = (v<<8)|(*cptr++); |
v = (v<<8)|(*cptr); |
|
return v; } |
void set(const unsigned addr, const unsigned val) { |
unsigned char *cptr = (unsigned char *)&m_mem[addr<<2]; |
*cptr++ = (val>>24); |
*cptr++ = (val>>16); |
*cptr++ = (val>> 8); |
*cptr = (val); |
return;} |
int operator()(const int csn, const int sck, const int dat); |
}; |
|