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

Subversion Repositories qspiflash

[/] [qspiflash/] [trunk/] [bench/] [cpp/] [eqspiflash_tb.cpp] - Rev 16

Compare with Previous | Blame | View Log

////////////////////////////////////////////////////////////////////////////////
//
// Filename: 	eqspiflash_tb.cpp
//
// Project:	Wishbone Controlled Quad SPI Flash Controller
//
// Purpose:	To determine whether or not the eqspiflash module works.  Run
//		this with no arguments, and check whether or not the last line
//	contains "SUCCESS" or not.  If it does contain "SUCCESS", then the
//	module passes all tests found within here.
//
// Creator:	Dan Gisselquist, Ph.D.
//		Gisselquist Technology, LLC
//
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015-2016, 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
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// 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
// target there if the PDF file isn't present.)  If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License:	GPL, v3, as defined and found on www.gnu.org,
//		http://www.gnu.org/licenses/gpl.html
//
//
////////////////////////////////////////////////////////////////////////////////
//
//
#include "verilated.h"
#include "verilated_vcd_c.h"
#include "Veqspiflash.h"
#include "eqspiflashsim.h"
 
#define	QSPIFLASH	0x0400000
const int	BOMBCOUNT = 2048;
 
class	EQSPIFLASH_TB {
	unsigned long		m_tickcount;
	Veqspiflash	*m_core;
	EQSPIFLASHSIM	*m_flash;
	bool		m_bomb;
	VerilatedVcdC*	m_trace;
 
public:
 
	EQSPIFLASH_TB(void) {
		Verilated::traceEverOn(true);
		m_core = new Veqspiflash;
		m_flash= new EQSPIFLASHSIM(24,true);
		m_trace= NULL;
	}
 
	unsigned operator[](const int index) { return (*m_flash)[index]; }
	void	setflash(unsigned addr, unsigned v) {
		m_flash->set(addr, v);
	}
	void	load(const char *fname) {
		m_flash->load(0,fname);
	}
 
	void	trace(const char *fname) {
		if (!m_trace) {
			m_trace = new VerilatedVcdC;
			m_core->trace(m_trace, 99);
			m_trace->open(fname);
		}
	}
 
	void	tick(void) {
		// m_core->i_clk_82mhz = 0;
		// m_core->eval();
		m_core->i_qspi_dat = (*m_flash)(m_core->o_qspi_cs_n,
			m_core->o_qspi_sck, m_core->o_qspi_dat);
 
		m_core->i_clk_82mhz = 1;
		m_core->eval();
// #define	DEBUGGING_OUTPUT
#ifdef	DEBUGGING_OUTPUT
		printf("%08lx-WB: %s %s/%s %s %s[%s%s%s%s%s] %s %s@0x%08x[%08x/%08x] -- SPI %s%s[%x/%x](%d,%d)",
			m_tickcount,
			(m_core->i_wb_cyc)?"CYC":"   ",
			(m_core->i_wb_data_stb)?"DSTB":"    ",
			(m_core->i_wb_ctrl_stb)?"CSTB":"    ",
			(m_core->o_wb_stall)?"STALL":"     ",
			(m_core->o_wb_ack)?"ACK":"   ",
			(m_core->v__DOT__bus_wb_ack)?"BS":"  ",
			(m_core->v__DOT__rd_data_ack)?"RD":"  ",
			(m_core->v__DOT__ew_data_ack)?"EW":"  ",
			(m_core->v__DOT__id_data_ack)?"ID":"  ",
			(m_core->v__DOT__ct_data_ack)?"CT":"  ",
			(m_core->o_cmd_accepted)?"BUS":"   ",
			(m_core->i_wb_we)?"W":"R",
			(m_core->i_wb_addr), (m_core->i_wb_data),
			(m_core->o_wb_data),
			(!m_core->o_qspi_cs_n)?"CS":"  ",
			(m_core->o_qspi_sck)?"CK":"  ",
			(m_core->o_qspi_dat), (m_core->i_qspi_dat),
			(m_core->o_qspi_dat)&1, ((m_core->i_qspi_dat)&2)?1:0);
 
		/// printf("%08lx-EQ: ", m_tickcount);
		printf("EQ: ");
		if (m_core->v__DOT__owned) {
			switch(m_core->v__DOT__owner&3) {
			case 0: printf("RD"); break;
			case 1: printf("EW"); break;
			case 2: printf("ID"); break;
			case 3: printf("CT"); break;
			}
		} else printf("  ");
 
		printf(" REQ[%s%s%s%s]",
			(m_core->v__DOT__rd_qspi_req)?"RD":"  ",
			(m_core->v__DOT__ew_qspi_req)?"EW":"  ",
			(m_core->v__DOT__id_qspi_req)?"ID":"  ",
			(m_core->v__DOT__ct_qspi_req)?"CT":"  ");
 
		printf(" %s[%s%2d%s%s0x%08x]",
			(m_core->v__DOT__spi_wr)?"CMD":"   ",
			(m_core->v__DOT__spi_hold)?"HLD":"   ",
			(m_core->v__DOT__spi_len+1)*8,
			(m_core->v__DOT__spi_dir)?"RD":"WR",
			(m_core->v__DOT__spi_spd)?"Q":" ",
			(m_core->v__DOT__spi_word));
 
		printf(" STATE[%2x%s,%2x%s,%2x%s,%2x%s]",
			m_core->v__DOT__rdproc__DOT__rd_state,
				(m_core->v__DOT__rd_spi_wr)?"W":" ",
			m_core->v__DOT__ewproc__DOT__wr_state,
				(m_core->v__DOT__ew_spi_wr)?"W":" ",
			m_core->v__DOT__idotp__DOT__id_state,
				(m_core->v__DOT__id_spi_wr)?"W":" ",
			m_core->v__DOT__ctproc__DOT__ctstate,
				(m_core->v__DOT__ct_spi_wr)?"W":" ");
 
		printf(" LL:[%s%s%d(%08x)->%08x]",
			(m_core->v__DOT__spi_busy)?"BSY":"   ",
			(m_core->v__DOT__spi_valid)?"VAL":"   ",
			(m_core->v__DOT__lowlvl__DOT__state),
			(m_core->v__DOT__lowlvl__DOT__r_input),
			(m_core->v__DOT__spi_out));
 
		// printf(" 0x%08x,%02x ", m_core->v__DOT__id_data, 
			// m_core->v__DOT__bus_addr);
		printf(" %s%08x@%08x",
			(m_core->v__DOT__bus_wr)?"W":"R",
			m_core->v__DOT__bus_data, m_core->v__DOT__bus_addr);
 
		if (m_core->v__DOT__idotp__DOT__id_state == 5)
			printf(" %s[%2x]%s",
				(m_core->v__DOT__idotp__DOT__last_addr)?"LST":"   ",
				(m_core->v__DOT__idotp__DOT__lcl_id_addr),
				(m_core->v__DOT__idotp__DOT__id_loaded)?"LOD":"   ");
 
 
		printf(" %s[%08x]",
			(m_core->v__DOT__idotp__DOT__nxt_data_ack)
			?"NXT":"   ", m_core->v__DOT__idotp__DOT__nxt_data);
		printf(" %s[%x]",
			(m_core->v__DOT__idotp__DOT__set_val)?"SET":"   ",
			(m_core->v__DOT__idotp__DOT__set_addr));
 
		printf(" RD:IACK[%x]",
			(m_core->v__DOT__rdproc__DOT__invalid_ack_pipe));
		printf(" CT:IACK[%x]",
			(m_core->v__DOT__ctproc__DOT__invalid_ack_pipe));
 
		{
			unsigned counts = m_flash->counts_till_idle();
			if (counts)
				printf(" %8dI ", counts);
		}
		printf("%s%s%s%s",
			(m_core->v__DOT__rdproc__DOT__accepted)?"RD-ACC":"",
			(m_core->v__DOT__ewproc__DOT__accepted)?"EW-ACC":"",
			(m_core->v__DOT__idotp__DOT__accepted)?"ID-ACC":"",
			(m_core->v__DOT__ctproc__DOT__accepted)?"CT-ACC":"");
 
 
		printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
			(m_core->v__DOT__preproc__DOT__pending)?" PENDING":"",
			(m_core->v__DOT__preproc__DOT__lcl_key)?" KEY":"",
			(m_core->v__DOT__preproc__DOT__ctreg_stb)?" CTSTB":"",
			(m_core->v__DOT__bus_ctreq)?" BUSCTRL":"",
			(m_core->v__DOT__bus_other_req)?" BUSOTHER":"",
			(m_core->v__DOT__preproc__DOT__wp)?" WP":"",
			(m_core->v__DOT__bus_wip)?" WIP":"",
			// (m_core->v__DOT__preproc__DOT__lcl_reg)?" LCLREG":"",
			// (m_core->v__DOT__w_xip)?" XIP":"",
			// (m_core->v__DOT__w_quad)?" QUAD":"",
			(m_core->v__DOT__bus_piperd)?" RDPIPE":"",
			(m_core->v__DOT__preproc__DOT__wp)?" WRWP":"",
			(m_core->v__DOT__ewproc__DOT__cyc)?" WRCYC":"",
			(m_core->v__DOT__bus_pipewr)?" WRPIPE":"",
			(m_core->v__DOT__bus_endwr)?" ENDWR":"",
			(m_core->v__DOT__ct_ack)?" CTACK":"",
			(m_core->v__DOT__rd_bus_ack)?" RDACK":"",
			(m_core->v__DOT__id_bus_ack)?" IDACK":"",
			(m_core->v__DOT__ew_bus_ack)?" EWACK":"",
			(m_core->v__DOT__preproc__DOT__lcl_ack)?" LCLACK":"",
			(m_core->v__DOT__rdproc__DOT__r_leave_xip)?" LVXIP":"",
			(m_core->v__DOT__preproc__DOT__new_req)?" NREQ":"");
 
		printf("%s%s%s",
			(m_core->v__DOT__bus_idreq)?" BUSID":"",
			(m_core->v__DOT__id_bus_ack)?" BUSAK":"",
			(m_core->v__DOT__idotp__DOT__id_read_request)?" IDRD":"");
 
		if (m_core->v__DOT__rdproc__DOT__r_requested)
			fputs(" RD:R_REQUESTED", stdout);
		if (m_core->v__DOT__rdproc__DOT__r_leave_xip)
			fputs(" RD:R_LVXIP", stdout);
 
 
		printf("\n");
#endif
 
		if ((m_trace)&&(m_tickcount>0))	m_trace->dump(10*m_tickcount-2);
		m_core->i_clk_82mhz = 1;
		m_core->eval();
		if (m_trace)	m_trace->dump(10*m_tickcount);
		m_core->i_clk_82mhz = 0;
		m_core->eval();
		if (m_trace)	m_trace->dump(10*m_tickcount+5);
 
		m_tickcount++;
 
		/*
		if ((m_core->o_wb_ack)&&(!m_core->i_wb_cyc)) {
			printf("SETTING ERR TO TRUE!!!!!  ACK w/ no CYC\n");
			// m_bomb = true;
		}
		*/
	}
 
	void wb_tick(void) {
		printf("WB-TICK()\n");
		m_core->i_wb_cyc   = 0;
		m_core->i_wb_data_stb = 0;
		m_core->i_wb_ctrl_stb = 0;
		tick();
	}
 
	unsigned wb_read(unsigned a) {
		int		errcount = 0;
		unsigned	result;
 
		printf("WB-READ(%08x)\n", a);
 
		m_core->i_wb_cyc = 1;
		m_core->i_wb_data_stb = (a & QSPIFLASH)?1:0;
		m_core->i_wb_ctrl_stb = !(m_core->i_wb_data_stb);
		m_core->i_wb_we  = 0;
		m_core->i_wb_addr= a & 0x03fffff;
 
		if (m_core->o_wb_stall) {
			while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall))
				tick();
		} tick();
 
		m_core->i_wb_data_stb = 0;
		m_core->i_wb_ctrl_stb = 0;
 
		while((errcount++ <  BOMBCOUNT)&&(!m_core->o_wb_ack))
			tick();
 
 
		result = m_core->o_wb_data;
 
		// Release the bus?
		m_core->i_wb_cyc = 0;
		m_core->i_wb_data_stb = 0;
		m_core->i_wb_ctrl_stb = 0;
 
		if(errcount >= BOMBCOUNT) {
			printf("RD-SETTING ERR TO TRUE!!!!!\n");
			m_bomb = true;
		} else if (!m_core->o_wb_ack) {
			printf("SETTING ERR TO TRUE--NO ACK, NO TIMEOUT\n");
			m_bomb = true;
		}
		tick();
 
		return result;
	}
 
	void	wb_read(unsigned a, int len, unsigned *buf) {
		int		errcount = 0;
		int		THISBOMBCOUNT = BOMBCOUNT * len;
		int		cnt, rdidx, inc;
 
		printf("WB-READ(%08x, %d)\n", a, len);
 
		while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall))
			wb_tick();
 
		if (errcount >= BOMBCOUNT) {
			m_bomb = true;
			return;
		}
 
		errcount = 0;
 
		m_core->i_wb_cyc = 1;
		m_core->i_wb_data_stb = (a & QSPIFLASH)?1:0;
		m_core->i_wb_ctrl_stb = !(m_core->i_wb_data_stb);
		m_core->i_wb_we  = 0;
		m_core->i_wb_addr= a & 0x03fffff;
 
		rdidx =0; cnt = 0;
		inc = (m_core->i_wb_data_stb);
 
		do {
			int	s;
			s = (m_core->o_wb_stall==0)?0:1;
			tick();
			if (!s)
				m_core->i_wb_addr += inc;
			cnt += (s==0)?1:0;
			if (m_core->o_wb_ack)
				buf[rdidx++] = m_core->o_wb_data;
		} while((cnt < len)&&(errcount++ < THISBOMBCOUNT));
 
		m_core->i_wb_data_stb = 0;
		m_core->i_wb_ctrl_stb = 0;
 
		while((rdidx < len)&&(errcount++ < THISBOMBCOUNT)) {
			tick();
			if (m_core->o_wb_ack)
				buf[rdidx++] = m_core->o_wb_data;
		}
 
		// Release the bus?
		m_core->i_wb_cyc = 0;
 
		if(errcount >= THISBOMBCOUNT) {
			printf("RDI-SETTING ERR TO TRUE!!!!! (errcount=%08x, THISBOMBCOUNT=%08x)\n", errcount, THISBOMBCOUNT);
			m_bomb = true;
		} else if (!m_core->o_wb_ack) {
			printf("SETTING ERR TO TRUE--NO ACK, NO TIMEOUT\n");
			m_bomb = true;
		}
		tick();
	}
 
	void	wb_write(unsigned a, unsigned int v) {
		int errcount = 0;
 
		printf("WB-WRITE(%08x) = %08x\n", a, v);
		m_core->i_wb_cyc = 1;
		m_core->i_wb_data_stb = (a & QSPIFLASH)?1:0;
		m_core->i_wb_ctrl_stb = !(m_core->i_wb_data_stb);
		m_core->i_wb_we  = 1;
		m_core->i_wb_addr= a & 0x03fffff;
		m_core->i_wb_data= v;
 
		if (m_core->o_wb_stall)
			while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall))
				tick();
		tick();
 
		m_core->i_wb_data_stb = 0;
		m_core->i_wb_ctrl_stb = 0;
 
		while((errcount++ <  BOMBCOUNT)&&(!m_core->o_wb_ack))
			tick();
 
		// Release the bus?
		m_core->i_wb_cyc = 0;
		m_core->i_wb_data_stb = 0;
		m_core->i_wb_ctrl_stb = 0;
 
		if(errcount >= BOMBCOUNT) {
			printf("WB-SETTING ERR TO TRUE!!!!!\n");
			m_bomb = true;
		} tick();
	}
 
	void	wb_write(unsigned a, unsigned int ln, unsigned int *buf) {
		unsigned errcount = 0, nacks = 0;
 
		m_core->i_wb_cyc = 1;
		m_core->i_wb_data_stb = (a & QSPIFLASH)?1:0;
		m_core->i_wb_ctrl_stb = !(m_core->i_wb_data_stb);
		for(unsigned stbcnt=0; stbcnt<ln; stbcnt++) {
			m_core->i_wb_we  = 1;
			m_core->i_wb_addr= (a+stbcnt) & 0x03fffff;
			m_core->i_wb_data= buf[stbcnt];
			errcount = 0;
 
			while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall)) {
				tick(); if (m_core->o_wb_ack) nacks++;
			}
			// Tick, now that we're not stalled.  This is the tick
			// that gets accepted.
			tick(); if (m_core->o_wb_ack) nacks++;
		}
 
		m_core->i_wb_data_stb = 0;
		m_core->i_wb_ctrl_stb = 0;
 
		errcount = 0;
		while((nacks < ln)&&(errcount++ < BOMBCOUNT)) {
			tick();
			if (m_core->o_wb_ack) {
				nacks++;
				errcount = 0;
			}
		}
 
		// Release the bus
		m_core->i_wb_cyc = 0;
		m_core->i_wb_data_stb = 0;
		m_core->i_wb_ctrl_stb = 0;
 
		if(errcount >= BOMBCOUNT) {
			printf("WBI-SETTING ERR TO TRUE!!!!!\n");
			m_bomb = true;
		} tick();
	}
 
	void	wb_write_slow(unsigned a, unsigned int ln, unsigned int *buf,
			int slowcounts) {
		unsigned errcount = 0, nacks = 0;
 
		m_core->i_wb_cyc = 1;
		m_core->i_wb_data_stb = (a & QSPIFLASH)?1:0;
		m_core->i_wb_ctrl_stb = !(m_core->i_wb_data_stb);
		for(unsigned stbcnt=0; stbcnt<ln; stbcnt++) {
			m_core->i_wb_we  = 1;
			m_core->i_wb_addr= (a+stbcnt) & 0x03fffff;
			m_core->i_wb_data= buf[stbcnt];
			errcount = 0;
 
			while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall)) {
				tick(); if (m_core->o_wb_ack) nacks++;
			}
 
			// Tick, now that we're not stalled.  This is the tick
			// that gets accepted.
			tick(); if (m_core->o_wb_ack) nacks++;
 
 
			m_core->i_wb_data_stb = 0;
			m_core->i_wb_ctrl_stb = 0;
			for(int j=0; j<slowcounts; j++) {
				tick(); if (m_core->o_wb_ack) nacks++;
			}
 
			// Turn our strobe signal back on again, after we just
			// turned it off.
			m_core->i_wb_data_stb = (a & QSPIFLASH)?1:0;
			m_core->i_wb_ctrl_stb = !(m_core->i_wb_data_stb);
		}
 
		m_core->i_wb_data_stb = 0;
		m_core->i_wb_ctrl_stb = 0;
 
		errcount = 0;
		while((nacks < ln)&&(errcount++ < BOMBCOUNT)) {
			tick();
			if (m_core->o_wb_ack) {
				nacks++;
				errcount = 0;
			}
		}
 
		// Release the bus
		m_core->i_wb_cyc = 0;
		m_core->i_wb_data_stb = 0;
		m_core->i_wb_ctrl_stb = 0;
 
		if(errcount >= BOMBCOUNT) {
			printf("WBS-SETTING ERR TO TRUE!!!!!\n");
			m_bomb = true;
		} tick();
	}
 
	bool	bombed(void) const { return m_bomb; }
 
};
 
int main(int  argc, char **argv) {
	Verilated::commandArgs(argc, argv);
	EQSPIFLASH_TB	*tb = new EQSPIFLASH_TB;
	const char 	*fname = "/dev/urandom";
	unsigned	rdv;
	unsigned	*rdbuf;
	int		 idx = 4;
 
	tb->load(fname);
	rdbuf = new unsigned[4096];
	tb->setflash(0,0);
 
	tb->trace("eqspi.vcd");
 
	tb->wb_tick();
	rdv = tb->wb_read(QSPIFLASH);
	printf("READ[0] = %04x\n", rdv);
	if (rdv != 0)
		goto test_failure;
 
	tb->wb_tick();
	if (tb->bombed())
		goto test_failure;
 
	for(int i=0; (i<1000)&&(!tb->bombed()); i++) {
		unsigned	tblv;
		tblv = (*tb)[i];
		rdv = tb->wb_read(QSPIFLASH+i);
 
		if(tblv != rdv) {
			printf("BOMB: READ[%08x] %08x, EXPECTED %08x\n", QSPIFLASH+i, rdv, tblv);
			goto test_failure;
			break;
		} else printf("MATCH: %08x == %08x\n", rdv, tblv);
	}
 
	printf("SINGLE-READ TEST PASSES\n");
 
	for(int i=0; i<1000; i++)
		rdbuf[i] = -1;
	tb->wb_read(QSPIFLASH+1000, 1000, rdbuf);
	if (tb->bombed())
		goto	test_failure;
	for(int i=0; i<1000; i++) {
		if ((*tb)[i+1000] != rdbuf[i]) {
			printf("BOMB: V-READ[%08x] %08x, EXPECTED %08x\n", QSPIFLASH+1000+i, rdv, (*tb)[i+1000]);
			goto	test_failure;
		}
	} if (tb->bombed())
		goto test_failure;
	printf("VECTOR TEST PASSES!\n");
 
	// Read the status register
	printf("EWCTRL-REG = %02x\n", rdv=tb->wb_read(0));
	if(tb->bombed()) goto test_failure;
	printf("STATUS-REG = %02x\n", rdv=tb->wb_read(1));
	if ((rdv != 0x1c)||(tb->bombed())) goto test_failure;
	printf("NVCONF-REG = %02x\n", tb->wb_read(2)); if(tb->bombed()) goto test_failure;
	printf("VCONFG-REG = %02x\n", tb->wb_read(3)); if(tb->bombed()) goto test_failure;
	printf("EVCONF-REG = %02x\n", tb->wb_read(4)); if(tb->bombed()) goto test_failure;
	printf("LOCK  -REG = %02x\n", tb->wb_read(5)); if(tb->bombed()) goto test_failure;
	printf("FLAG  -REG = %02x\n", tb->wb_read(6)); if(tb->bombed()) goto test_failure;
 
	if (tb->bombed())
		goto test_failure;
 
	printf("ID[%2d]-RG = %08x\n", 0, rdv = tb->wb_read(8+0));
	if (rdv != 0x20ba1810) {
		printf("BOMB: ID[%2d]-RG = %08x != %08x\n", 0, rdv,
			0x20ba1810);
		goto test_failure;
	}
 
	for(int i=1; i<5; i++)
		printf("ID[%2d]-RG = %02x\n", i, tb->wb_read(8+i));
	if (tb->bombed())
		goto test_failure;
 
	for(int i=0; i<16; i++)
		printf("OTP[%2d]-R = %02x\n", i, tb->wb_read(16+i));
	if (tb->bombed())
		goto test_failure;
	printf("OTP[CT]-R = %02x\n", tb->wb_read(15)>>24);
 
	if (tb->bombed())
		goto test_failure;
 
	printf("Attempting to switch in Quad mode\n");
	// tb->wb_write(4, (tb->wb_read(4)&0x07f)); // Adjust EVconfig
 
	for(int i=0; (i<1000)&&(!tb->bombed()); i++) {
		unsigned	tblv;
		tblv = (*tb)[i];
		rdv = tb->wb_read(QSPIFLASH+i);
 
		if(tblv != rdv) {
			printf("BOMB: READ %08x, EXPECTED %08x\n", rdv, tblv);
			goto test_failure;
			break;
		} else printf("MATCH: %08x == %08x\n", rdv, tblv);
	} tb->wb_read(QSPIFLASH+1000, 1000, rdbuf);
	if (tb->bombed())
		goto	test_failure;
	for(int i=0; i<1000; i++) {
		if ((*tb)[i+1000] != rdbuf[i]) {
			printf("BOMB: READ %08x, EXPECTED %08x\n", rdv, (*tb)[i+1000]);
			goto	test_failure;
		}
	} printf("VECTOR TEST PASSES! (QUAD)\n");
 
	printf("Attempting to switch to Quad mode with XIP\n");
	{
		int	nv;
		nv = tb->wb_read(3);
		printf("READ VCONF = %02x\n", nv);
		printf("WRITING VCONF= %02x\n", nv | 0x08);
		tb->wb_write(3, nv|0x08);
	}
	// tb->wb_write(0, 0x22000000);
 
	printf("Attempting to read in Quad mode, using XIP mode\n");
	for(int i=0; (i<1000)&&(!tb->bombed()); i++) {
		unsigned	tblv;
		tblv = (*tb)[i];
		rdv = tb->wb_read(QSPIFLASH+i);
 
		if(tblv != rdv) {
			printf("BOMB: READ %08x, EXPECTED %08x\n", rdv, tblv);
			goto test_failure;
			break;
		} else printf("MATCH: %08x == %08x\n", rdv, tblv);
	}
 
	// Try a vector read
	tb->wb_read(QSPIFLASH+1000, 1000, rdbuf);
	if (tb->bombed())
		goto	test_failure;
	for(int i=0; i<1000; i++) {
		if ((*tb)[i+1000] != rdbuf[i]) {
			printf("BOMB: READ %08x, EXPECTED %08x\n", rdv, (*tb)[i+1000]);
			goto	test_failure;
		}
	} printf("VECTOR TEST PASSES! (QUAD+XIP)\n");
 
	rdbuf[0] = tb->wb_read(QSPIFLASH+1023);
	rdbuf[1] = tb->wb_read(QSPIFLASH+2048);
 
	printf("Turning off write-protect, calling WEL\n");
	tb->wb_write(0, 0x620001be);
	printf("Attempting to erase subsector 1\n");
	tb->wb_write(0, 0xf20005be);
 
	while((tb->wb_read(0)&0x01000000)&&(!tb->bombed()))
		;
	while((tb->wb_read(0)&0x80000000)&&(!tb->bombed()))
		;
	if (tb->bombed())
		goto test_failure;
	if (tb->wb_read(QSPIFLASH+1023) != rdbuf[0])
		goto test_failure;
	if (tb->wb_read(QSPIFLASH+2048) != rdbuf[1])
		goto test_failure;
	tb->wb_read(QSPIFLASH+1024, 1024, rdbuf);
	for(int i=0; i<1024; i++) {
		if (rdbuf[i] != 0xffffffff) {
			printf("BOMB: SUBSECTOR ERASE, EXPECTED[0x%02x] = 0xffffffff != %08x\n", i, rdv);
			goto test_failure;
		} break;
	}
 
	// Try to execute a single write
	// Check that this will work ...
	for(idx=4; idx<4096; idx++) {
		if (0 != (tb->wb_read(QSPIFLASH+idx)&(~0x11111111)))
			break;
	}
	// First, turn the write-enable back on
	tb->wb_write(0, 0x620001be);
	// Now, write the value
	tb->wb_write(QSPIFLASH+idx, 0x11111111);
	while (tb->wb_read(0)&0x01000000)
		;
	while(tb->wb_read(0)&(0x80000000))
		;
	if (0 != (tb->wb_read(QSPIFLASH+idx)&(~0x11111111)))
		goto test_failure;
 
	// Try to write a complete block
	{
		FILE *fp = fopen(fname, "r"); // Open /dev/urandom
		if (4096 != fread(rdbuf, sizeof(unsigned), 4096, fp)) {
			perror("Couldnt read /dev/urandom into buffer!");
			goto test_failure;
		} fclose(fp);
	}
 
	printf("Attempting to write subsector 1\n");
	for(int i=0; i<1024; i+= 64) {
		printf("Turning off write-protect, calling WEL\n");
		tb->wb_write(0, 0x620001be);
 
		printf("Writing from %08x to %08x from rdbuf\n",
			QSPIFLASH+1024+i, QSPIFLASH+1024+i+63);
		// tb->wb_write(QSPIFLASH+1024+i, 64, &rdbuf[i]);
		tb->wb_write_slow(QSPIFLASH+1024+i, 64, &rdbuf[i], 32);
		while(tb->wb_read(0)&(0x80000000))
			;
	}
 
	tb->wb_read(QSPIFLASH+1024, 1024, &rdbuf[1024]);
	for(int i=0; i<1024; i++) {
		if (rdbuf[i] != rdbuf[i+1024]) {
			printf("BOMB: SUBSECTOR PROGRAM, EXPECTED[0x%02x] = 0x%08x != %08x\n", i, rdbuf[i], rdbuf[i+1024]);
			goto test_failure;
		}
	}
 
	// -Try to write an OTP register
	printf("Turning off write-protect, calling WEL\n");
	tb->wb_write( 0, 0x620001be);
	printf("Writing OTP[2]\n");
	tb->wb_write(18, 0x620001be);
	while (tb->wb_read(0)&0x01000000)
		;
	while(tb->wb_read(0)&(0x80000000))
		;
	if (0x620001be != tb->wb_read(18))
		goto test_failure;
 
	// -Try to write protect all OTP register
	printf("Turning off write-protect, calling WEL\n");
	tb->wb_write( 0, 0x620001be);
	printf("Writing OTP[END]\n");
	tb->wb_write(15, 0);
	while (tb->wb_read(0)&0x01000000)
		;
	while(tb->wb_read(0)&(0x80000000))
		;
	if (0 != tb->wb_read(15))
		goto test_failure;
 
	// -Try to write OTP after write protecting all OTP registers
	printf("Turning off write-protect, calling WEL\n");
	tb->wb_write( 0, 0x620001be);
	printf("Writing OTP[7]\n");
	tb->wb_write(16+7, 0);
	while (tb->wb_read(0)&0x01000000)
		;
	while(tb->wb_read(0)&(0x80000000))
		;
 
	// -Verify OTP not written
	if (0 == tb->wb_read(16+7))
		goto test_failure;
 
 
	printf("SUCCESS!!\n");
	exit(0);
test_failure:
	printf("FAIL-HERE\n");
	for(int i=0; i<64; i++)
		tb->tick();
	printf("TEST FAILED\n");
	exit(-1);
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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