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

Subversion Repositories wbddr3

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /wbddr3
    from Rev 7 to Rev 8
    Reverse comparison

Rev 7 → Rev 8

/trunk/bench/cpp/ddrsdram_tb.cpp
83,7 → 83,6
m_core->o_ddr_data);
 
bool writeout = (!m_core->v__DOT__reset_override);
writeout = true;
 
if (writeout) {
int cmd;
138,6 → 137,7
(m_core->v__DOT__bus_new),
(m_core->v__DOT__bus_subaddr[8]));
 
/*
// Reset logic
printf(" RST(%06x%s[%d] - %08x->%08x)",
m_core->v__DOT__reset_timer,
145,6 → 145,7
(m_core->v__DOT__reset_address),
(m_core->v__DOT__reset_instruction),
(m_core->v__DOT__reset_cmd));
*/
 
printf(" %s%03x[%d]%04x:%d",
(m_core->v__DOT__r_pending)?"R":" ",
431,6 → 432,11
for(int i=0; i<141195; i++)
tb->wb_tick();
 
// Let's short circuit the test, and only test *some* of the memory
// space. It'll probably be good enough, and it'll finish while I'm
// waiting ...
mlen = 1<<16;
 
printf("Getting some memory ...\n");
rdbuf = new unsigned[mlen];
mbuf = new unsigned[mlen]; // Match buffer
487,8 → 493,9
}
}
 
// Third test: Vector writes going through all memory, an prime number
// Third test: Vector writes going through all memory, in prime numbers
// of values at a time, followed by reads via a different prime number
uload(mlen, rdbuf); // Get some new values
for(int i=0; i<(int)mlen; i+=nw) {
int ln = ((int)mlen-i>nw)?nw:mlen-i;
tb->wb_write(i, nw, &rdbuf[i]);
502,7 → 509,7
goto test_failure;
} for(int i=0; i<(int)mlen; i+=nr) {
int ln = ((int)mlen-i>nr)?nr:mlen-i;
tb->wb_write(i, nr, &mbuf[i]);
tb->wb_read(i, nr, &mbuf[i]);
for(int j=0; j<ln; j++) {
if (mbuf[i+j] != rdbuf[i+j]) {
printf("P-READ[%06x] = %08x (Expecting %08x) FAILED\n",
513,7 → 520,31
goto test_failure;
}
 
// Fourth test: Singular writes though all of memory, skipping by some
// prime address increment each time, followed by reads via a different
// prime numbered increment.
uload(mlen, rdbuf); // Get some new values
for(int i=0; i<(int)mlen; i++) {
int loc = (i*13)&0x3ffffff;
tb->wb_write(loc, rdbuf[loc]);
if ((*tb)[loc] != rdbuf[loc]) {
printf("R-WRITE[%06x] = %08x (Expecting %08x) FAILED\n",
i, (*tb)[loc], rdbuf[loc]);
goto test_failure;
} if (tb->bombed())
goto test_failure;
} for(int i=0; i<(int)mlen; i++) {
int loc = (i*19)&0x3ffffff;
mbuf[loc] = tb->wb_read(loc);
if (mbuf[loc] != rdbuf[loc]) {
printf("R-READ[%06x] = %08x (Expecting %08x) FAILED\n",
loc, mbuf[loc], rdbuf[loc]);
goto test_failure;
} if (tb->bombed())
goto test_failure;
}
 
 
printf("SUCCESS!!\n");
exit(0);
test_failure:
/trunk/bench/cpp/ddrsdramsim.cpp
50,6 → 50,12
switch(cmd) {
case DDR_PRECHARGE:
m_state = 6;
// While the specification allows precharging an already
// precharged bank, we can keep that from happening
// here:
// assert(m_state&7);
// Only problem is, this will currently break our
// refresh logic.
break;
case DDR_ACTIVATE:
m_state = 1;
217,10 → 223,6
 
m_clocks_since_refresh++;
assert(m_clocks_since_refresh < (int)ckREFIn);
printf("Clocks to refresh should be %4d-%4d = %4d = 0x%04x\n",
ckREFIn, m_clocks_since_refresh,
ckREFIn- m_clocks_since_refresh,
ckREFIn- m_clocks_since_refresh);
switch(cmd) {
case DDR_MRSET:
assert(0&&"Modes should only be set in reset startup");
260,7 → 262,7
for(int i=0; i<NBANKS; i++)
if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
unsigned caddr = m_bank[ba].m_row;
caddr <<= 13;
caddr <<= 3;
caddr |= ba;
caddr <<= 10;
caddr |= addr;
302,7 → 304,7
for(int i=0; i<NBANKS; i++)
if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
unsigned caddr = m_bank[ba].m_row;
caddr <<= 13;
caddr <<= 3;
caddr |= ba;
caddr <<= 10;
caddr |= addr;
311,25 → 313,26
 
BUSTIMESLOT *tp;
tp = &m_bus[(m_busloc+ckCL+0)&(NTIMESLOTS-1)];
int offset = (m_busloc+ckCL+1)&(NTIMESLOTS-1);
tp = &m_bus[(offset)&(NTIMESLOTS-1)];
tp->m_data = m_mem[caddr];
tp->m_addr = caddr;
tp->m_used = 1;
tp->m_read = 1;
tp = &m_bus[(m_busloc+ckCL+1)&(NTIMESLOTS-1)];
tp = &m_bus[(offset+1)&(NTIMESLOTS-1)];
tp->m_data = m_mem[caddr+1];
tp->m_addr = caddr+1;
tp->m_used = 1;
tp->m_read = 1;
 
tp = &m_bus[(m_busloc+ckCL+2)&(NTIMESLOTS-1)];
tp = &m_bus[(offset+2)&(NTIMESLOTS-1)];
tp->m_data = m_mem[caddr+2];
tp->m_addr = caddr+2;
tp->m_used = 1;
tp->m_read = 1;
 
tp = &m_bus[(m_busloc+ckCL+3)&(NTIMESLOTS-1)];
tp = &m_bus[(offset+3)&(NTIMESLOTS-1)];
tp->m_data = m_mem[caddr+3];
tp->m_addr = caddr+3;
tp->m_used = 1;
/trunk/rtl/wbddrsdram.v
380,7 → 380,7
end else if (need_close_bank)
begin
bank_status[close_bank_cmd[16:14]]
<= { bank_status[close_bank_cmd[16:14]][2:0], 1'b1 };
<= { bank_status[close_bank_cmd[16:14]][2:0], 1'b0 };
// bank_status[close_bank_cmd[16:14]][0] <= 1'b0;
end else if (need_open_bank)
begin
394,7 → 394,7
else if (maybe_close_next_bank)
begin
bank_status[maybe_close_cmd[16:14]]
<= { bank_status[maybe_close_cmd[16:14]][2:0], 1'b1 };
<= { bank_status[maybe_close_cmd[16:14]][2:0], 1'b0 };
end else if (maybe_open_next_bank)
begin
bank_status[maybe_open_cmd[16:14]]
407,9 → 407,12
 
always @(posedge i_clk)
// if (cmd[22:19] == `DDR_ACTIVATE)
if (need_open_bank)
if (w_this_opening_bank)
bank_address[activate_bank_cmd[16:14]]
<= activate_bank_cmd[13:0];
else if (!w_this_maybe_open)
bank_address[maybe_open_cmd[16:14]]
<= maybe_open_cmd[13:0];
 
//
//
457,7 → 460,7
wire [16:0] w_ckREFIn, w_ckREFRst;
assign w_ckREFIn[ 12: 0] = CKREFI4-5*CKRFC-2-10;
assign w_ckREFIn[ 16:13] = 4'h0;
assign w_ckREFRst[12: 0] = CKRFC-2-6;
assign w_ckREFRst[12: 0] = CKRFC-2-12;
assign w_ckREFRst[16:13] = 4'h0;
 
always @(posedge i_clk)
490,7 → 493,7
4'h9: refresh_instruction <= { 3'h6, `DDR_NOOP, w_ckRFC };
4'ha: refresh_instruction <= { 3'h4, `DDR_REFRESH, 17'h00 };
4'hb: refresh_instruction <= { 3'h6, `DDR_NOOP, w_ckRFC };
4'hc: refresh_instruction <= { 3'h6, `DDR_NOOP, w_ckRFC };
4'hc: refresh_instruction <= { 3'h2, `DDR_NOOP, w_ckREFRst };
default:
refresh_instruction <= { 3'h1, `DDR_NOOP, 17'h00 };
endcase
/trunk/doc/spec.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/trunk/doc/src/spec.tex
143,6 → 143,29
% This section describes the architecture of the block. A block level diagram
% should be included describing the top level of the design.
 
\section{Strategies}
\subsection{Bank}
Currently, banks are activated (opened) when needed and only precharged
(closed) upon refresh request. Further, upon any read or write from one bank,
the next bank is activated as well, under the assumption that the next bank
will be needed soon. This is necessary to allow pipeline access with no stalls
through the memory controller.
 
This means that, upon any bank miss, a bank precharge followed by bank activate
command will be necessary.
 
\subsection{Refresh}
The current build will pause all operations for four subsequent refreshes,
at roughly every 4 refresh intervals, and then allow operations to resume.
This pause is independent of anything going on, and includes a mandatory
wait for any writes to finish, followed by a precharge command---regardless of
whether or not such is required.
 
This is non-optimal, and ripe for optimizing later. A better strategy might
be to do singular refreshes after any single refresh period assuming the bus
is free, to only issue a precharge if the bus is busy, and to only wait
prior to that precharge if a write is busy. This will be a later optimization.
 
\chapter{Operation}
 
% This section describes the operation of the core. Specific sequences, such

powered by: WebSVN 2.1.0

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