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 8 to Rev 9
- ↔ Reverse comparison
Rev 8 → Rev 9
/trunk/bench/cpp/ddrsdram_tb.cpp
122,13 → 122,11
(m_core->i_ddr_data), |
(m_core->o_ddr_data)); |
|
printf(" FIFO[%x,%x](%d,%d,%08x-%08x-%08x)", |
printf(" FIFO[%x,%x](%s,%d,%08x)", |
m_core->v__DOT__bus_fifo_head, |
m_core->v__DOT__bus_fifo_tail, |
m_core->v__DOT__bus_fifo_new[m_core->v__DOT__bus_fifo_tail], |
(m_core->v__DOT__bus_fifo_new[m_core->v__DOT__bus_fifo_tail])?"N":"o", |
m_core->v__DOT__bus_fifo_sub[m_core->v__DOT__bus_fifo_tail], |
m_core->v__DOT__r_data, |
m_core->v__DOT__bus_fifo_data[(m_core->v__DOT__bus_fifo_head-1)&15], |
m_core->v__DOT__bus_fifo_data[m_core->v__DOT__bus_fifo_tail]); |
|
printf(" BUS[%03x/%03x/%03x/%d]", |
147,12 → 145,30
(m_core->v__DOT__reset_cmd)); |
*/ |
|
printf(" %s%03x[%d]%04x:%d", |
(m_core->v__DOT__r_pending)?"R":" ", |
printf(" R_%s%03x[%d]%04x:%d/%08x", |
(!m_core->v__DOT__r_pending)?"_" |
:(m_core->v__DOT__r_we)?"W":"R", |
(m_core->v__DOT__r_row), |
(m_core->v__DOT__r_bank), |
(m_core->v__DOT__r_col),0); |
// (m_core->v__DOT__r_sub)); |
(m_core->v__DOT__r_col), |
(m_core->v__DOT__r_sub), |
(m_core->v__DOT__r_data)); |
|
printf(" S_%s%03x[%d]%04x:%d/%08x%s%s%s", |
(!m_core->v__DOT__s_pending)?"_" |
:(m_core->v__DOT__s_we)?"W":"R", |
(m_core->v__DOT__s_row), |
(m_core->v__DOT__s_bank), |
(m_core->v__DOT__s_col), |
(m_core->v__DOT__s_sub), |
(m_core->v__DOT__s_data), |
(m_core->v__DOT__s_match)?"M":" ", |
(m_core->v__DOT__pipe_stall)?"P":" ", |
"-" |
//(m_core->v__DOT__s_stall)?"S":" " |
); |
|
|
printf(" %s%s%s", |
"B", |
// (m_core->v__DOT__all_banks_closed)?"b":"B", |
172,7 → 188,7
extern int gbl_state, gbl_counts; |
printf(" %2d:%08x ", gbl_state, gbl_counts); |
|
printf(" %s%s%s%s%s%s%s:%08x:%08x", |
printf(" %s%s%s%s%s%s:%08x:%08x", |
(m_core->v__DOT__reset_override)?"R":" ", |
(m_core->v__DOT__need_refresh)?"N":" ", |
(m_core->v__DOT__need_close_bank)?"C":" ", |
179,7 → 195,6
(m_core->v__DOT__need_open_bank)?"O":" ", |
(m_core->v__DOT__valid_bank)?"V":" ", |
(m_core->v__DOT__r_move)?"R":" ", |
(m_core->v__DOT__m_move)?"M":" ", |
m_core->v__DOT__activate_bank_cmd, |
m_core->v__DOT__cmd); |
|
251,8 → 266,7
if (m_core->o_wb_stall) { |
while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall)) |
tick(); |
} else |
tick(); |
} tick(); |
|
m_core->i_wb_stb = 0; |
|
423,7 → 437,6
Verilated::commandArgs(argc, argv); |
DDRSDRAM_TB *tb = new DDRSDRAM_TB; |
unsigned *rdbuf, *mbuf; |
int nw = 3, nr = 13; |
unsigned mlen = (1<<(LGMEMSIZE-2)); |
|
printf("Giving the core 140k cycles to start up\n"); |
443,6 → 456,16
printf("Charging my memory with random values\n"); |
uload(mlen, rdbuf); |
|
#define SINGULAR_WRITE |
#define SINGULAR_READ |
#define BIGPIPELINE_WRITE |
#define BIGPIPELINE_READ |
#define PRIMEVEC_WRITE |
#define PRIMEVEC_READ |
#define SKIP_WRITE |
#define SKIP_READ |
|
#ifdef SINGULAR_WRITE |
// First test: singular reads through the memory, followed by |
// singular writes |
printf("Starting the single-read test\n"); |
456,7 → 479,17
} if (tb->bombed()) |
goto test_failure; |
|
} for(int i=0; i<(int)mlen; i++) { |
} |
#else |
#ifdef SINGULAR_READ |
// If we aren't doing the write test, we still need to charge |
// the memory for the read test. Here we do it manually. |
for(int i=0; i<(int)mlen; i++) |
(*tb)[i] = rdbuf[i]; |
#endif // !SINGULAR_WRITE && SINGULAR_READ |
#endif // SINGULAR_WRITE |
#ifdef SINGULAR_READ |
for(int i=0; i<(int)mlen; i++) { |
unsigned v; |
if (rdbuf[i] != (v=tb->wb_read(i))) { |
printf("READ[%06x] = %08x (Expecting %08x)\n", |
466,7 → 499,9
goto test_failure; |
tb->wb_tick(); |
} |
#endif |
|
#ifdef BIGPIPELINE_WRITE |
// Second test: Vector writes going through all memory, followed a |
// massive vector read |
uload(mlen, rdbuf); // Get some new values |
481,7 → 516,16
goto test_failure; |
} |
} |
|
#else |
#ifdef BIGPIPELINE_READ |
uload(mlen, rdbuf); // Get some new values |
// If we aren't doing the write test, we still need to charge |
// the memory for the read test. Here we do it manually. |
for(int i=0; i<(int)mlen; i++) |
(*tb)[i] = rdbuf[i]; |
#endif // BIGPIPELINE_WRITE && BIGPIPELINE_READ |
#endif |
#ifdef BIGPIPELINE_READ |
tb->wb_read( 0, mlen, mbuf); |
if (tb->bombed()) |
goto test_failure; |
492,40 → 536,61
goto test_failure; |
} |
} |
#endif |
|
#ifdef PRIMEVEC_WRITE |
// 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]); |
for(int j=0; j<ln; j++) { |
if ((*tb)[i+j] != rdbuf[i+j]) { |
printf("P-WRITE[%06x] = %08x (Expecting %08x) FAILED\n", |
i, (*tb)[i], rdbuf[i]); |
{ |
int nw = 3; |
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]); |
for(int j=0; j<ln; j++) { |
if ((*tb)[i+j] != rdbuf[i+j]) { |
printf("P-WRITE[%06x] = %08x (Expecting %08x) FAILED\n", |
i, (*tb)[i], rdbuf[i]); |
goto test_failure; |
} |
} if (tb->bombed()) |
goto test_failure; |
} |
} if (tb->bombed()) |
goto test_failure; |
} for(int i=0; i<(int)mlen; i+=nr) { |
int ln = ((int)mlen-i>nr)?nr:mlen-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", |
i, mbuf[i], rdbuf[i]); |
} |
} |
#else |
#ifdef PRIMEVEC_READ |
uload(mlen, rdbuf); // Get some new values |
// If we aren't doing the write test, we still need to charge |
// the memory for the read test. Here we do it manually. |
for(int i=0; i<(int)mlen; i++) |
(*tb)[i] = rdbuf[i]; |
#endif |
#endif |
#ifdef PRIMEVEC_READ |
{ |
int nr = 13; |
for(int i=0; i<(int)mlen; i+=nr) { |
int ln = ((int)mlen-i>nr)?nr:mlen-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", |
i, mbuf[i], rdbuf[i]); |
goto test_failure; |
} |
} if (tb->bombed()) |
goto test_failure; |
} |
} if (tb->bombed()) |
goto test_failure; |
} |
} |
#endif |
|
#ifdef SKIP_WRITE |
// 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; |
int loc = (i*3889)&(mlen-1); |
tb->wb_write(loc, rdbuf[loc]); |
if ((*tb)[loc] != rdbuf[loc]) { |
printf("R-WRITE[%06x] = %08x (Expecting %08x) FAILED\n", |
533,8 → 598,17
goto test_failure; |
} if (tb->bombed()) |
goto test_failure; |
} for(int i=0; i<(int)mlen; i++) { |
int loc = (i*19)&0x3ffffff; |
} |
#else |
#ifdef SKIP_READ |
uload(mlen, rdbuf); // Get some new values |
for(int i=0; i<(int)mlen; i++) |
(*tb)[i] = rdbuf[i]; |
#endif // !SKIP_WRITE && SKIP_READ |
#endif |
#ifdef SKIP_READ |
for(int i=0; i<(int)mlen; i++) { |
int loc = (i*7477)&(mlen-1); |
mbuf[loc] = tb->wb_read(loc); |
if (mbuf[loc] != rdbuf[loc]) { |
printf("R-READ[%06x] = %08x (Expecting %08x) FAILED\n", |
543,6 → 617,7
} if (tb->bombed()) |
goto test_failure; |
} |
#endif |
|
|
printf("SUCCESS!!\n"); |
/trunk/bench/cpp/ddrsdramsim.cpp
38,6 → 38,7
#include <stdio.h> |
#include <assert.h> |
|
#define PREFIX "DDR3-SDRAM" |
const unsigned ckCL = 5, |
ckRC = 3, |
ckRFC = 320, // Clocks from refresh to activate |
142,7 → 143,7
m_reset_counts++; |
assert(cke); |
if (cmd != DDR_NOOP) { |
printf("DDR3-SDRAM::RESET-CMD[4]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr); |
printf(PREFIX "::RESET-CMD[4]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr); |
assert(m_reset_counts > 3); |
m_reset_counts = 0; |
m_reset_state = 5; |
154,7 → 155,7
m_reset_counts++; |
assert(cke); |
if (cmd != DDR_NOOP) { |
printf("DDR3-SDRAM::RESET-CMD[5]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr); |
printf(PREFIX "::RESET-CMD[5]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr); |
assert(m_reset_counts > 11); |
m_reset_counts = 0; |
m_reset_state = 6; |
165,7 → 166,7
m_reset_counts++; |
assert(cke); |
if (cmd != DDR_NOOP) { |
printf("DDR3-SDRAM::RESET-CMD[6]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr); |
printf(PREFIX "::RESET-CMD[6]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr); |
assert(m_reset_counts > 512); |
m_reset_counts = 0; |
m_reset_state = 7; |
176,7 → 177,7
m_reset_counts++; |
assert(cke); |
if (cmd != DDR_NOOP) { |
printf("DDR3-SDRAM::RESET-CMD[7]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr); |
printf(PREFIX "::RESET-CMD[7]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr); |
assert(m_reset_counts > 3); |
m_reset_counts = 0; |
m_reset_state = 8; |
189,7 → 190,7
assert(cmd == DDR_NOOP); |
if (m_reset_counts > 140) { |
m_reset_state = 16; |
printf("DDR3-SDRAM: Leaving reset state\n"); |
printf(PREFIX ": Leaving reset state\n"); |
} |
break; |
default: |
217,7 → 218,7
m_bank[i].tick(DDR_REFRESH,0); |
|
if (m_nrefresh_issued == nREF) |
printf("DDRSDRAM::Refresh cycle complete\n"); |
printf(PREFIX "::Refresh cycle complete\n"); |
} else { |
// In operational mode!! |
|
248,7 → 249,6
} |
break; |
case DDR_ACTIVATE: |
printf("DDRSIM::ACTIVE, clocks_since_refresh = %d >= %d\n", m_clocks_since_refresh, ckRFC); |
assert(m_clocks_since_refresh >= (int)ckRFC); |
m_bank[ba].tick(DDR_ACTIVATE,addr); |
for(int i=0; i<NBANKS; i++) |
269,14 → 269,11
caddr &= ~7; |
caddr >>= 1; |
|
printf("DDRSDRAM::WRITE ADDR = %04x|%d|%04x|%d -> %06x\n", |
m_bank[ba].m_row, ba, addr, 0, caddr); |
|
BUSTIMESLOT *tp; |
int offset = m_busloc+ckCL+1; |
|
tp = &m_bus[(offset+0)&(NTIMESLOTS-1)]; |
printf("Setting bus timeslots from (now=%d)+%d=%d to now+%d+3\n", m_busloc, ckCL,(m_busloc+ckCL)&(NTIMESLOTS-1), ckCL); |
// printf("Setting bus timeslots from (now=%d)+%d=%d to now+%d+3\n", m_busloc, ckCL,(m_busloc+ckCL)&(NTIMESLOTS-1), ckCL); |
tp->m_addr = caddr ; |
tp->m_used = 1; |
tp->m_read = 0; |
355,12 → 352,6
m_busloc = (m_busloc+1)&(NTIMESLOTS-1); |
|
BUSTIMESLOT *ts = &m_bus[m_busloc]; |
if (ts->m_used) { |
printf("Current timeslot = %2d, used", m_busloc); |
if (ts->m_read) |
printf(", read"); |
printf("\n"); |
} |
unsigned vl = ts->m_data; |
assert( ((!ts->m_used)||(busoe)) |
|| ((ts->m_used)&&(ts->m_read))); |
367,7 → 358,7
|
assert((!ts->m_used)||(ts->m_addr < (unsigned)m_memlen)); |
if ((ts->m_used)&&(!ts->m_read)&&(!dm)) { |
printf("Setting MEM[%08x] = %08x\n", ts->m_addr, data); |
printf(PREFIX "::Setting MEM[%08x] = %08x\n", ts->m_addr, data); |
m_mem[ts->m_addr] = data; |
} |
ts->m_used = 0; |
/trunk/rtl/wbddrsdram.v
6,6 → 6,24
// |
// Purpose: |
// |
/* |
Stall logic: |
1. First clock sets r_* variables. |
2. Second clock sets need_* variables. If need_open, need_close, or |
need_refresh are true, that should also set the o_wb_stall |
variable. Well also move r_* info to s_* (think s=stall) |
3. If stalled, the next command comes from s_*. Otherwise, from r_*. |
4. Bus FIFO fills from s_* |
// |
// |
For every transaction, one of 4 possibilities: |
1. Wait for refresh to complete |
2. Wait for precharge and activate to complete |
3. Wait for activate to complete |
4. Issue RW cmd |
5. Wait for bus transaction to complete |
6. ACK |
*/ |
// Creator: Dan Gisselquist, Ph.D. |
// Gisselquist Technology, LLC |
// |
124,9 → 142,20
reg [1:0] r_sub; |
reg r_move; // It was accepted, and can move to next stage |
|
// The pending transaction, one further into the pipeline. This is |
// the stage where the read/write command is actually given to the |
// interface if we haven't stalled. |
reg [31:0] s_data; |
reg s_pending, s_we, s_match; |
reg [25:0] s_addr; |
reg [13:0] s_row, s_nxt_row; |
reg [2:0] s_bank, s_nxt_bank; |
reg [9:0] s_col; |
reg [1:0] s_sub; |
|
// Can the pending transaction be satisfied with the current (ongoing) |
// transaction? |
reg m_move, m_match, m_continue, m_pending, m_we; |
reg m_move, m_match, m_pending, m_we; |
reg [25:0] m_addr; |
reg [13:0] m_row; |
reg [2:0] m_bank; |
145,10 → 174,12
valid_bank, last_valid_bank; |
reg [(`DDR_CMDLEN-1):0] close_bank_cmd, activate_bank_cmd, |
maybe_close_cmd, maybe_open_cmd, rw_cmd; |
reg [1:0] rw_sub; |
reg rw_we; |
|
wire w_this_closing_bank, w_this_opening_bank, |
w_this_maybe_close, w_this_maybe_open, |
w_this_rw_move, w_this_refresh; |
w_this_rw_move; |
reg last_closing_bank, last_opening_bank; |
// |
// tWTR = 7.5 |
188,9 → 219,10
// the DDR3 SDRAM, or a timer to wait until the next command. Further, the |
// timer commands indicate whether or not the command during the timer is to |
// be set to idle, or whether the command is instead left as it was. |
reg reset_override, reset_ztimer; |
reg reset_override, reset_ztimer, maintenance_override; |
reg [4:0] reset_address; |
reg [(`DDR_CMDLEN-1):0] reset_cmd, cmd, refresh_cmd; |
reg [(`DDR_CMDLEN-1):0] reset_cmd, cmd, refresh_cmd, |
maintenance_cmd; |
reg [24:0] reset_instruction; |
reg [16:0] reset_timer; |
initial reset_override = 1'b1; |
512,7 → 544,8
begin |
bus_active[`BUSNOW:0] <= { bus_active[(`BUSNOW-1):0], 1'b0 }; |
bus_read[`BUSNOW:0] <= { bus_read[(`BUSNOW-1):0], 1'b0 }; // Drive the d-bus? |
bus_new[`BUSNOW:0] <= { bus_new[(`BUSNOW-1):0], 1'b0 }; // Drive the d-bus? |
// Is this a new command? i.e., the start of a transaction? |
bus_new[`BUSNOW:0] <= { bus_new[(`BUSNOW-1):0], 1'b0 }; |
//bus_mask[8:0] <= { bus_mask[7:0], 1'b1 }; // Write this value? |
bus_subaddr[8] <= bus_subaddr[7]; |
bus_subaddr[7] <= bus_subaddr[6]; |
530,9 → 563,9
bus_subaddr[3] <= 2'h0; |
bus_subaddr[2] <= 2'h1; |
bus_subaddr[1] <= 2'h2; |
bus_new[{ 2'b0, (2'h3-r_sub) }] <= 1'b1; |
bus_new[{ 2'b0, rw_sub }] <= 1'b1; |
|
bus_read[3:0] <= (r_we)? 4'h0:4'hf; |
bus_read[3:0] <= (rw_we)? 4'h0:4'hf; |
end |
end |
|
544,19 → 577,30
// Now, let's see, can we issue a read command? |
// |
// |
wire w_s_match; |
assign w_s_match = (s_pending)&&(r_pending)&&(r_we == s_we) |
&&(r_row == s_row)&&(r_bank == s_bank) |
&&(r_col == s_col) |
&&(r_sub > s_sub); |
reg pipe_stall; |
always @(posedge i_clk) |
begin |
if ((i_wb_stb)&&(~o_wb_stall)) |
r_pending <= (i_wb_stb)&&(~o_wb_stall) |
||(r_pending)&&(pipe_stall); |
if (~pipe_stall) |
s_pending <= r_pending; |
if (~pipe_stall) |
begin |
r_pending <= 1'b1; |
pipe_stall <= (r_pending)&&(((!w_r_valid)||(valid_bank))&&(!w_s_match)); |
o_wb_stall <= (r_pending)&&(((!w_r_valid)||(valid_bank))&&(!w_s_match)); |
end else begin // if (pipe_stall) |
pipe_stall <= (s_pending)&&((!w_s_valid)||(valid_bank)||(r_move)||(last_valid_bank)); |
o_wb_stall <= (s_pending)&&((!w_s_valid)||(valid_bank)||(r_move)||(last_valid_bank)); |
end |
if (need_refresh) |
o_wb_stall <= 1'b1; |
end else if ((m_move)||(w_this_rw_move)) |
begin |
r_pending <= 1'b0; |
o_wb_stall <= 1'b0; |
end |
|
if (~o_wb_stall) |
if (~pipe_stall) |
begin |
r_we <= i_wb_we; |
r_addr <= i_wb_addr; |
570,12 → 614,42
r_nxt_row <= (i_wb_addr[11:9]==3'h7)?i_wb_addr[25:12]+14'h1:i_wb_addr[25:12]; |
r_nxt_bank <= i_wb_addr[11:9]+3'h1; |
end |
|
if (~pipe_stall) |
begin |
// Moving one down the pipeline |
s_we <= r_we; |
s_addr <= r_addr; |
s_data <= r_data; |
s_row <= r_row; |
s_bank <= r_bank; |
s_col <= r_col; |
s_sub <= r_sub; |
|
// pre-emptive work |
s_nxt_row <= r_nxt_row; |
s_nxt_bank <= r_nxt_bank; |
|
s_match <= w_s_match; |
end |
end |
|
wire w_need_close_this_bank, w_need_open_bank; |
wire w_need_close_this_bank, w_need_open_bank, |
w_r_valid, w_s_valid; |
assign w_need_close_this_bank = (r_pending)&&(bank_status[r_bank][0]) |
&&(r_row != bank_address[r_bank]); |
assign w_need_open_bank = (r_pending)&&(bank_status[r_bank][1:0]==2'b00); |
&&(r_row != bank_address[r_bank]) |
||(pipe_stall)&&(s_pending)&&(bank_status[s_bank][0]) |
&&(s_row != bank_address[s_bank]); |
assign w_need_open_bank = (r_pending)&&(bank_status[r_bank][1:0]==2'b00) |
||(pipe_stall)&&(s_pending)&&(bank_status[s_bank][1:0]==2'b00); |
assign w_r_valid = (!need_refresh)&&(r_pending) |
&&(bank_status[r_bank][3]) |
&&(bank_address[r_bank]==r_row) |
&&(!bus_active[0]); |
assign w_s_valid = (!need_refresh)&&(s_pending) |
&&(bank_status[s_bank][3]) |
&&(bank_address[s_bank]==s_row) |
&&(!bus_active[0]); |
|
always @(posedge i_clk) |
begin |
606,52 → 680,31
|
|
|
valid_bank <= (r_pending)&&(bank_status[r_bank][3]) |
&&(bank_address[r_bank]==r_row) |
&&(!last_valid_bank)&&(!r_move) |
&&(!bus_active[0]); |
valid_bank <= ((w_r_valid)||(pipe_stall)&&(w_s_valid)) |
&&(!last_valid_bank)&&(!r_move); |
last_valid_bank <= r_move; |
|
rw_cmd[`DDR_CSBIT:`DDR_WEBIT] <= (~r_pending)?`DDR_NOOP:((r_we)?`DDR_WRITE:`DDR_READ); |
rw_cmd[`DDR_WEBIT-1:0] <= { r_bank, 3'h0, 1'b0, r_col }; |
if ((s_pending)&&(pipe_stall)) |
rw_cmd[`DDR_CSBIT:`DDR_WEBIT] <= (s_we)?`DDR_WRITE:`DDR_READ; |
else if (r_pending) |
rw_cmd[`DDR_CSBIT:`DDR_WEBIT] <= (r_we)?`DDR_WRITE:`DDR_READ; |
else |
rw_cmd[`DDR_CSBIT:`DDR_WEBIT] <= `DDR_NOOP; |
if ((s_pending)&&(pipe_stall)) |
rw_cmd[`DDR_WEBIT-1:0] <= { s_bank, 3'h0, 1'b0, s_col }; |
else |
rw_cmd[`DDR_WEBIT-1:0] <= { r_bank, 3'h0, 1'b0, r_col }; |
if ((s_pending)&&(pipe_stall)) |
rw_sub <= 2'b11 - s_sub; |
else |
rw_sub <= 2'b11 - r_sub; |
if ((s_pending)&&(pipe_stall)) |
rw_we <= s_we; |
else |
rw_we <= r_we; |
|
end |
|
|
// Match registers, to see if we can move forward without sending a |
// new command |
reg [2:0] m_clock; |
reg m_timeout; |
always @(posedge i_clk) |
begin |
if (|m_clock) |
m_clock <= m_clock - 3'h1; |
if (!m_timeout) |
m_timeout <= (m_clock[2:1] == 2'b00); |
if (w_this_rw_move) |
begin |
m_pending <= r_pending; |
m_we <= r_we; |
m_addr <= r_addr; |
m_row <= r_row; |
m_bank <= r_bank; |
m_col <= r_col; |
m_sub <= r_sub; |
m_clock<= 3'h7; |
m_timeout <= 1'b0; |
end else if ((m_match)&&(!m_timeout)) |
m_sub <= r_sub; |
|
m_match <= (m_pending)&&(r_pending)&&(r_we == m_we) |
&&(r_row == m_row)&&(r_bank == m_bank) |
&&(r_col == m_col) |
&&(r_sub > m_sub); |
m_continue <= (m_pending)&&(r_pending)&&(r_we == m_we) |
&&(r_row == m_row)&&(r_bank == m_bank) |
&&(r_col == m_col+10'h1); |
// m_nextbank <= (m_pending)&&(r_pending)&&(r_we == m_we) |
// &&(r_row == m_row)&&(r_bank == m_bank); |
end |
|
// |
// |
// Okay, let's look at the last assignment in our chain. It should look |
667,21 → 720,31
else if (reset_ztimer) |
o_ddr_cke <= reset_instruction[`DDR_CKEBIT]; |
|
assign w_this_refresh = (!reset_override)&&(need_refresh) |
&&(refresh_cmd[`DDR_CSBIT:`DDR_WEBIT] == `DDR_REFRESH); |
always @(posedge i_clk) |
if (i_reset) |
maintenance_override <= 1'b1; |
else |
maintenance_override <= (reset_override)||(need_refresh); |
|
assign w_this_closing_bank = (!reset_override)&&(!need_refresh) |
initial maintenance_cmd = { `DDR_NOOP, 17'h00 }; |
always @(posedge i_clk) |
if (i_reset) |
maintenance_cmd <= { `DDR_NOOP, 17'h00 }; |
else |
maintenance_cmd <= (reset_override)?reset_cmd:refresh_cmd; |
|
assign w_this_closing_bank = (!maintenance_override) |
&&(need_close_bank); |
assign w_this_opening_bank = (!reset_override)&&(!need_refresh) |
assign w_this_opening_bank = (!maintenance_override) |
&&(!need_close_bank)&&(need_open_bank); |
assign w_this_rw_move = (!reset_override)&&(!need_refresh) |
assign w_this_rw_move = (!maintenance_override) |
&&(!need_close_bank)&&(!need_open_bank) |
&&(valid_bank)&&(!r_move); |
assign w_this_maybe_close = (!reset_override)&&(!need_refresh) |
assign w_this_maybe_close = (!maintenance_override) |
&&(!need_close_bank)&&(!need_open_bank) |
&&((!valid_bank)||(r_move)) |
&&(maybe_close_next_bank); |
assign w_this_maybe_open = (!reset_override)&&(!need_refresh) |
assign w_this_maybe_open = (!maintenance_override) |
&&(!need_close_bank)&&(!need_open_bank) |
&&((!valid_bank)||(r_move)) |
&&(!maybe_close_next_bank) |
693,13 → 756,10
last_maybe_open <= 1'b0; |
last_maybe_close <= 1'b0; |
r_move <= 1'b0; |
if (reset_override) |
cmd <= reset_cmd[`DDR_CSBIT:0]; |
else if (need_refresh) |
if (maintenance_override) // Command from either reset or |
cmd <= maintenance_cmd; // refresh logic |
else if (need_close_bank) |
begin |
cmd <= refresh_cmd; // The command from the refresh logc |
end else if (need_close_bank) |
begin |
cmd <= close_bank_cmd; |
last_closing_bank <= 1'b1; |
end else if (need_open_bank) |
732,7 → 792,11
|
// The bus R/W FIFO |
wire w_bus_fifo_read_next_transaction; |
assign w_bus_fifo_read_next_transaction = (bus_fifo_sub[bus_fifo_tail]==bus_subaddr[`BUSREG])&&(bus_active[`BUSREG])&&(bus_new[`BUSREG] == bus_fifo_new[bus_fifo_tail]); |
assign w_bus_fifo_read_next_transaction = |
(bus_fifo_sub[bus_fifo_tail]==bus_subaddr[`BUSREG]) |
&&(bus_fifo_tail != bus_fifo_head) |
&&(bus_active[`BUSREG]) |
&&(bus_new[`BUSREG] == bus_fifo_new[bus_fifo_tail]); |
always @(posedge i_clk) |
begin |
pre_ack <= 1'b0; |
743,7 → 807,7
bus_fifo_tail <= 4'h0; |
o_ddr_dm <= 1'b0; |
end else begin |
if ((w_this_rw_move)||(m_move)) |
if ((w_this_rw_move)||((s_pending)&&(s_match)&&(!pipe_stall))) |
bus_fifo_head <= bus_fifo_head + 4'h1; |
|
o_ddr_dm <= (bus_active[`BUSREG])&&(!bus_read[`BUSREG]); |
754,8 → 818,8
o_ddr_dm <= 1'b0; |
end |
end |
bus_fifo_data[bus_fifo_head] <= r_data; |
bus_fifo_sub[bus_fifo_head] <= r_sub; |
bus_fifo_data[bus_fifo_head] <= s_data; |
bus_fifo_sub[bus_fifo_head] <= s_sub; |
bus_fifo_new[bus_fifo_head] <= w_this_rw_move; |
end |
|