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 |