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

Subversion Repositories xulalx25soc

[/] [xulalx25soc/] [trunk/] [bench/] [cpp/] [sdramsim.cpp] - Rev 105

Go to most recent revision | Compare with Previous | Blame | View Log

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
 
#include "sdramsim.h"
 
short	SDRAMSIM::operator()(int clk, int cke, int cs_n, int ras_n, int cas_n, int we_n,
		int bs, unsigned addr, int driv, short data) {
	short	result = 0;
 
	if (driv) // If the bus is going out, reads don't make sense ... but
		result = data; // read what we output anyway
	else if (!clk) // If the clock is zero, return our last value
		return m_last_value; // Always called w/clk=1, thus never here
	if (!cke) {
		fprintf(stderr, "This simulation only supports CKE high!\n");
		fprintf(stderr, "\tCKE   = %d\n", cke);
		fprintf(stderr, "\tCS_n  = %d\n", cs_n);
		fprintf(stderr, "\tRAS_n = %d\n", ras_n);
		fprintf(stderr, "\tCAS_n = %d\n", cas_n);
		fprintf(stderr, "\tWE_n  = %d\n", we_n);
		assert(cke);
	}
 
	if (m_pwrup < POWERED_UP_STATE) {
		if (m_clocks_till_idle > 0)
			m_clocks_till_idle--;
		if (m_pwrup == 0) {
			assert((ras_n)&&(cas_n)&&(we_n));
			if (m_clocks_till_idle == 0) {
				m_pwrup++;
				// printf("Successful power up wait, moving to state #1\n");
			}
		} else if (m_pwrup == 1) {
			if ((!cs_n)&&(!ras_n)&&(cas_n)&&(!we_n)&&(addr&0x0400)) {
				// Wait until a precharge all banks command
				m_pwrup++;
				// printf("Successful precharge command, moving to state #2\n");
				m_clocks_till_idle = 8;
			}
		} else if (m_pwrup == 2) {
			// Need 8 auto refresh cycles before or after the mode
			// set command.  We'll insist they be before.
			if (m_clocks_till_idle == 0) {
				m_pwrup++;
				// printf("Successful initial auto-refresh, waiting for mode-set\n");
				for(int i=0; i<m_nrefresh; i++)
					m_refresh_time[i] = MAX_REFRESH_TIME;
			} else
				assert((!cs_n)&&(!ras_n)&&(!cas_n)&&(we_n));
		} else if (m_pwrup == 3) {
			const int tRSC = 2;
			if ((!cs_n)&&(!ras_n)&&(!cas_n)&&(!we_n)){
				// mode set
				// printf("Mode set: %08x\n", addr);
				assert(addr == 0x021);
				m_pwrup++;
				// printf("Successful mode set, moving to state #3, tRSC = %d\n", tRSC);
				m_clocks_till_idle=tRSC;
			}
		} else if (m_pwrup == 4) {
			assert(cs_n);
			if (m_clocks_till_idle == 0) {
				m_pwrup = POWERED_UP_STATE;
				m_clocks_till_idle = 0;
				// printf("Successful settup!  SDRAM switching to operational\n");
			} else if (m_clocks_till_idle == 1) {
				;
			} else assert(0 && "Should never get here!");
		} else if (m_pwrup == 5) {
			if ((!cs_n)&&(!ras_n)&&(!cas_n)&&(we_n)) {
				if (m_clocks_till_idle == 0) {
					m_pwrup = POWERED_UP_STATE;
					m_clocks_till_idle = 0;
 
					for(int i=0; i<m_nrefresh; i++)
						m_refresh_time[i] = MAX_REFRESH_TIME;
				}
			} else {
				assert(0);
			}
		}
		m_next_wr = false;
	} else { // In operation ...
		for(int i=0; i<m_nrefresh; i++)
			m_refresh_time[i]--;
		if (m_refresh_time[m_refresh_loc] < 0) {
			assert(0 && "Failed refresh requirement");
		} for(int i=0; i<NBANKS; i++) {
			m_bank_status[i] >>= 1;
			if (m_bank_status[i]&2)
				m_bank_status[i] |= 4;
			if (m_bank_status[i]&1) { // Bank is open
				m_bank_open_time[i] --;
				if (m_bank_open_time[i] < 0) {
					assert(0 && "Bank held open too long");
				}
			}
		}
 
		if (m_clocks_till_idle)
			m_clocks_till_idle--;
 
		if (m_fail > 0) {
			m_fail--;
			if (m_fail == 0) {
				fprintf(stderr, "Failing on schedule\n");
				exit(-3);
			}
		}
 
		if ((m_clocks_till_idle > 0)&&(m_next_wr)) {
			// printf("SDRAM[%08x] <= %04x\n", m_wr_addr, data & 0x0ffff);
			m_mem[m_wr_addr++] = data;
			result = data;
			m_next_wr = false;
		}
		m_qloc = (m_qloc + 1)&m_qmask;
		result = (driv)?data:m_qdata[(m_qloc)&m_qmask];
		m_qdata[(m_qloc)&m_qmask] = 0;
 
		// if (result != 0)
			// printf("%d RESULT[%3d] = %04x\n", clk, m_qloc, result&0x0ffff);
 
		if ((!cs_n)&&(!ras_n)&&(!cas_n)&&(we_n)) {
			// Auto-refresh command
			m_refresh_time[m_refresh_loc] = MAX_REFRESH_TIME;
			m_refresh_loc++;
			if (m_refresh_loc >= m_nrefresh)
				m_refresh_loc = 0;
			assert((m_bank_status[0]&6) == 0);
			assert((m_bank_status[1]&6) == 0);
			assert((m_bank_status[2]&6) == 0);
			assert((m_bank_status[3]&6) == 0);
		} else if ((!cs_n)&&(!ras_n)&&(cas_n)&&(!we_n)) {
			if (addr&0x0400) {
				// Bank/Precharge All CMD
				for(int i=0; i<NBANKS; i++)
					m_bank_status[i] &= 0x03;
			} else {
				// Precharge/close single bank
				assert(0 == (bs & (~3))); // Assert w/in bounds
				m_bank_status[bs] &= 0x03; // Close the bank
 
				// printf("Precharging bank %d\n", bs);
			}
		} else if ((!cs_n)&&(!ras_n)&&(cas_n)&&(we_n)) {
			// printf("Activating bank %d\n", bs);
			// Activate a bank!
			if (0 != (bs & (~3))) {
				m_fail = 2;
				fprintf(stderr, "ERR: Activating a bank w/ more than 2 bits\n");
				// assert(0 == (bs & (~3))); // Assert w/in bounds
			} else if (m_bank_status[bs] != 0) {
				fprintf(stderr, "ERR: Status of bank [bs=%d] = %d != 0\n",
					bs, m_bank_status[bs]);
				m_fail = 4;
				// assert(m_bank_status[bs]==0); // Assert bank was closed
			}
			m_bank_status[bs] |= 4;
			m_bank_open_time[bs] = MAX_BANKOPEN_TIME;
			m_bank_row[bs] = addr;
		} else if ((!cs_n)&&(ras_n)&&(!cas_n)) {
			// printf("R/W Op\n");
			if (!we_n) {
				// Initiate a write
				assert(0 == (bs & (~3))); // Assert w/in bounds
				assert(m_bank_status[bs]&1); // Assert bank is open
 
				m_wr_addr = m_bank_row[bs];
				m_wr_addr <<= 2;
				m_wr_addr |= bs;
				m_wr_addr <<= 9;
				m_wr_addr |= (addr & 0x01ff);
 
				assert(driv);
				// printf("SDRAM[%08x] <= %04x\n", m_wr_addr, data & 0x0ffff);
				m_mem[m_wr_addr++] = data;
				m_clocks_till_idle = 2;
				m_next_wr = true;
 
				if (addr & 0x0400) { // Auto precharge
					m_bank_status[bs] &= 3;
					m_bank_open_time[bs] = MAX_BANKOPEN_TIME;
				}
			} else { // Initiate a read
				assert(0 == (bs & (~3))); // Assert w/in bounds
				assert(m_bank_status[bs]&1); // Assert bank is open
 
				unsigned	rd_addr;
 
				rd_addr = m_bank_row[bs] & 0x01fff;
				rd_addr <<= 2;
				rd_addr |= bs;
				rd_addr <<= 9;
				rd_addr |= (addr & 0x01ff);
 
				assert(!driv);
				// printf("SDRAM.Q[%2d] %04x <= SDRAM[%08x]\n",
					// (m_qloc+3)&m_qmask,
					// m_mem[rd_addr] & 0x0ffff, rd_addr);
				m_qdata[(m_qloc+3)&m_qmask] = m_mem[rd_addr++];
				// printf("SDRAM.Q[%2d] %04x <= SDRAM[%08x]\n",
					// (m_qloc+4)&m_qmask,
					// m_mem[rd_addr] & 0x0ffff, rd_addr);
				m_qdata[(m_qloc+4)&m_qmask] = m_mem[rd_addr++];
				m_clocks_till_idle = 2;
 
				if (addr & 0x0400) { // Auto precharge
					m_bank_status[bs] &= 3;
					m_bank_open_time[bs] = MAX_BANKOPEN_TIME;
				}
			}
		} else if (cs_n) {
			// Chips not asserted, DESELECT CMD equivalent of a NOOP
		} else if ((ras_n)&&(cas_n)&&(we_n)) {
			// NOOP command
		} else {
			fprintf(stderr, "Unrecognized memory command!\n");
			fprintf(stderr, "\tCS_n  = %d\n", cs_n);
			fprintf(stderr, "\tRAS_n = %d\n", ras_n);
			fprintf(stderr, "\tCAS_n = %d\n", cas_n);
			fprintf(stderr, "\tWE_n  = %d\n", we_n);
			assert(0 && "Unrecognizned command");
		}
	}
 
	return result & 0x0ffff;
}
 
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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