URL
https://opencores.org/ocsvn/wbddr3/wbddr3/trunk
Subversion Repositories wbddr3
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 13 to Rev 14
- ↔ Reverse comparison
Rev 13 → Rev 14
/wbddr3/trunk/bench/cpp/ddrsdramsim.h
53,7 → 53,9
class BANKINFO { |
public: |
int m_state; |
unsigned m_row, m_wcounter; |
unsigned m_row, m_wcounter, m_min_time_before_precharge, |
m_min_time_before_activate; |
BANKINFO(void); |
void tick(int cmd, unsigned addr=0); |
}; |
|
68,10 → 70,10
m_clocks_since_refresh, m_nrefresh_issued, |
m_last_dqs, m_last_rtt; |
unsigned *m_mem; |
BANKINFO m_bank[8]; |
BUSTIMESLOT *m_bus; |
int cmd(int,int,int,int); |
public: |
BANKINFO m_bank[8]; |
DDRSDRAMSIM(int lglen); |
unsigned operator()(int, int, |
int, int, int, int, |
/wbddr3/trunk/bench/cpp/ddrsdram_tb.cpp
84,14 → 84,17
|
bool writeout = (!m_core->v__DOT__reset_override); |
|
int cmd; |
cmd = (m_core->o_ddr_reset_n?0:32) |
|(m_core->o_ddr_cke?0:16) |
|(m_core->o_ddr_cs_n?8:0) |
|(m_core->o_ddr_ras_n?4:0) |
|(m_core->o_ddr_cas_n?2:0) |
|(m_core->o_ddr_we_n?1:0); |
if ((cmd&0x0f)==DDR_REFRESH) |
writeout = true; |
|
if (writeout) { |
int cmd; |
cmd = (m_core->o_ddr_reset_n?0:32) |
|(m_core->o_ddr_cke?0:16) |
|(m_core->o_ddr_cs_n?8:0) |
|(m_core->o_ddr_ras_n?4:0) |
|(m_core->o_ddr_cas_n?2:0) |
|(m_core->o_ddr_we_n?1:0); |
printf("%08lx-WB: %s/%s %s%s%s %s@0x%08x[%08x/%08x] -- ", |
m_tickcount, |
(m_core->i_wb_cyc)?"CYC":" ", |
178,18 → 181,23
(m_core->v__DOT__need_open_bank)?"O":"K"); |
// :(m_core->v__DOT__maybe_open_next_bank)?"o":"K"); |
for(int i=0; i<8; i++) { |
printf("%s%x@%x%s", |
printf("%s%s%s%x%x@%x%s", |
(m_core->v__DOT__r_bank==i)?"R":"[", |
((m_core->v__DOT__bank_open)&(1<<i))?"+":" ", |
((m_core->v__DOT__bank_closed)&(1<<i))?"-":" ", |
m_core->v__DOT__bank_status[i], |
m_sdram->m_bank[i].m_state&0x0f, |
m_core->v__DOT__bank_address[i], |
(m_core->v__DOT__r_nxt_bank==i)?"N":"]"); |
} |
|
|
/* |
extern int gbl_state, gbl_counts; |
printf(" %2d:%08x ", gbl_state, gbl_counts); |
*/ |
|
printf(" %s%s%s%s%s%s:%08x:%08x", |
printf(" %s%s%s%s%s%s%s%s%s%s%s", |
(m_core->v__DOT__reset_override)?"R":" ", |
(m_core->v__DOT__need_refresh)?"N":" ", |
(m_core->v__DOT__need_close_bank)?"C":" ", |
196,14 → 204,20
(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__activate_bank_cmd, |
m_core->v__DOT__cmd); |
(m_core->v__DOT__maybe_close_next_bank)?"c":" ", |
(m_core->v__DOT__maybe_open_next_bank)?"o":" ", |
(m_core->v__DOT__pre_valid)?"p":" ", |
(m_core->v__DOT__w_r_valid)?"r":" ", |
(m_core->v__DOT__w_s_valid)?"s":" "); |
|
/* |
// Refresh logic |
printf(" F%s%05x:%x/%s", |
(m_core->v__DOT__refresh_ztimer)?"Z":" ", |
m_core->v__DOT__refresh_counter, |
m_core->v__DOT__refresh_addr, |
(m_core->v__DOT__need_refresh)?"N":" "); |
*/ |
|
if (m_core->v__DOT__reset_override) |
printf(" OVERRIDE"); |
225,6 → 239,15
printf("\n"); |
} |
|
// A consistency check ... |
/* |
if (m_core->v__DOT__bus_fifo_head != m_core->v__DOT__bus_fifo_tail) { |
fflush(stdout); |
if (cmd == DDR_REFRESH) |
printf("FAIL: CMD=REFRESH, but head != tail\n"); |
assert(cmd != DDR_REFRESH); |
} */ |
|
m_core->eval(); |
m_core->i_clk = 0; |
m_core->eval(); |
251,6 → 274,7
m_core->i_wb_cyc = 0; |
m_core->i_wb_stb = 0; |
tick(); |
assert(!m_core->o_wb_ack); |
} |
|
unsigned wb_read(unsigned a) { |
276,6 → 300,10
|
|
result = m_core->o_wb_data; |
if (result != (*this)[a]) { |
printf("READ-FAIL\n"); |
assert(result == (*this)[a]); |
} |
|
// Release the bus? |
m_core->i_wb_cyc = 0; |
290,6 → 318,9
} |
tick(); |
|
assert(m_core->v__DOT__bus_fifo_head == m_core->v__DOT__bus_fifo_tail); |
|
assert(!m_core->o_wb_ack); |
return result; |
} |
|
325,8 → 356,16
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; |
if (m_core->o_wb_ack) { |
buf[rdidx] = m_core->o_wb_data; |
printf("WB-READ[%08x] = %08x\n", a+rdidx, |
m_core->o_wb_data); |
if (buf[rdidx] != (*this)[a+rdidx]) { |
printf("READ-FAIL\n"); |
assert(buf[rdidx] == (*this)[a+rdidx]); |
} |
rdidx++; |
} |
} while((cnt < len)&&(errcount++ < THISBOMBCOUNT)); |
|
m_core->i_wb_stb = 0; |
333,8 → 372,16
|
while((rdidx < len)&&(errcount++ < THISBOMBCOUNT)) { |
tick(); |
if (m_core->o_wb_ack) |
buf[rdidx++] = m_core->o_wb_data; |
if (m_core->o_wb_ack) { |
buf[rdidx] = m_core->o_wb_data; |
printf("WB-READ[%08x] = %08x\n", a+rdidx, |
m_core->o_wb_data); |
if (buf[rdidx] != (*this)[a+rdidx]) { |
printf("READ-FAIL\n"); |
assert(buf[rdidx] == (*this)[a+rdidx]); |
} |
rdidx++; |
} |
} |
|
// Release the bus? |
348,6 → 395,8
m_bomb = true; |
} |
tick(); |
assert(m_core->v__DOT__bus_fifo_head == m_core->v__DOT__bus_fifo_tail); |
assert(!m_core->o_wb_ack); |
} |
|
void wb_write(unsigned a, unsigned int v) { |
378,6 → 427,8
printf("SETTING ERR TO TRUE!!!!!\n"); |
m_bomb = true; |
} tick(); |
assert(m_core->v__DOT__bus_fifo_head == m_core->v__DOT__bus_fifo_tail); |
assert(!m_core->o_wb_ack); |
} |
|
void wb_write(unsigned a, unsigned int ln, unsigned int *buf) { |
418,6 → 469,8
printf("SETTING ERR TO TRUE!!!!!\n"); |
m_bomb = true; |
} tick(); |
assert(m_core->v__DOT__bus_fifo_head == m_core->v__DOT__bus_fifo_tail); |
assert(!m_core->o_wb_ack); |
} |
|
bool bombed(void) const { return m_bomb; } |
486,7 → 539,7
a = 1087 + i*1031; |
tb->wb_write(a, rdbuf[a]); |
if ((v=tb->wb_read(a)) != rdbuf[a]) { |
printf("CASE-1, %08x -> MEM[%08x] -> %08x FAILED (R/W not equal)\n", rdbuf[a], a, v); |
printf("CASE-2, %08x -> MEM[%08x] -> %08x FAILED (R/W not equal)\n", rdbuf[a], a, v); |
goto test_failure; |
} |
} |
499,7 → 552,7
a = 1109 + i*1024; |
tb->wb_write(a, rdbuf[a]); |
if ((v=tb->wb_read(a)) != rdbuf[a]) { |
printf("CASE-1, %08x -> MEM[%08x] -> %08x FAILED (R/W not equal)\n", rdbuf[a], a, v); |
printf("CASE-3, %08x -> MEM[%08x] -> %08x FAILED (R/W not equal)\n", rdbuf[a], a, v); |
goto test_failure; |
} |
} |
511,12 → 564,34
for(int i=0; i<8; i++) { |
a = 1109 + i*1024; |
tb->wb_write(a, rdbuf[a]); |
} for(int i=0; i<8; i++) { |
a = 1109 + i*1024; |
if ((v=tb->wb_read(a)) != rdbuf[a]) { |
printf("CASE-1, %08x -> MEM[%08x] -> %08x FAILED (R/W not equal)\n", rdbuf[a], a, v); |
printf("CASE-4, %08x -> MEM[%08x] -> %08x FAILED (R/W not equal)\n", rdbuf[a], a, v); |
goto test_failure; |
} |
} |
} |
|
// And a quick pipeline test |
{ |
unsigned v, mbuf[8], a = 379; |
tb->wb_write(0, 8, &rdbuf[379]); |
for(int i=0; i<8; i++) { |
a = 379+i; |
if ((v=(*tb)[i]) != rdbuf[a]) { |
printf("CASE-5, %08x -> MEM[%08x] -> %08x FAILED (R/W not equal)\n", rdbuf[a], i, v); |
goto test_failure; |
} |
} tb->wb_read(0, 8, mbuf); |
for(int i=0; i<8; i++) { |
a = 379+i; |
if (mbuf[i] != rdbuf[a]) { |
printf("CASE-6, %08x -> MEM[%08x] -> %08x FAILED (R/W not equal)\n", rdbuf[a], i, mbuf[i]); |
goto test_failure; |
} |
} |
} |
#endif |
|
#ifdef SINGULAR_WRITE |
558,6 → 633,7
#ifdef BIGPIPELINE_WRITE |
// Second test: Vector writes going through all memory, followed a |
// massive vector read |
printf("Starting the big-pipeline write test\n"); |
uload(mlen, rdbuf); // Get some new values |
tb->wb_write(0, mlen, rdbuf); |
if (tb->bombed()) |
580,6 → 656,7
#endif // BIGPIPELINE_WRITE && BIGPIPELINE_READ |
#endif |
#ifdef BIGPIPELINE_READ |
printf("Starting the big-pipeline read test\n"); |
tb->wb_read( 0, mlen, mbuf); |
if (tb->bombed()) |
goto test_failure; |
593,6 → 670,7
#endif |
|
#ifdef PRIMEVEC_WRITE |
printf("Starting the prime-vector write test\n"); |
// 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 |
/wbddr3/trunk/bench/cpp/ddrsdramsim.cpp
40,17 → 40,30
|
#define PREFIX "DDR3-SDRAM" |
const unsigned ckCL = 5, |
ckRC = 3, |
ckRC = 10, |
ckRAS = 7, |
ckRFC = 320, // Clocks from refresh to activate |
nREF = 4, |
ckREFI = 1560, // 7.8us @ 200MHz = 7.8e-6 * 200e6 = 1560 |
ckREFI = 1560; // 7.8us @ 200MHz = 7.8e-6 * 200e6 = 1560 |
/* |
const unsigned nREF = 4, |
ckREFIn = nREF*ckREFI - (nREF-1) * ckRFC; |
*/ |
const unsigned nREF = 1, |
ckREFIn = ckREFI; |
|
#include "ddrsdramsim.h" |
|
BANKINFO::BANKINFO(void) { |
m_state = 0; m_row = 0; m_wcounter = 0; m_min_time_before_precharge=0; |
} |
|
void BANKINFO::tick(int cmd, unsigned addr) { |
if (m_wcounter) |
m_wcounter--; |
switch(cmd) { |
case DDR_REFRESH: |
assert(m_state == 0); |
break; |
case DDR_PRECHARGE: |
m_state = 6; |
// While the specification allows precharging an already |
59,11 → 72,30
// assert(m_state&7); |
// Only problem is, this will currently break our |
// refresh logic. |
if (m_min_time_before_precharge != 0) { |
printf("BANK-FAIL: TIME-BEFORE-PRECHARGE = %d (should be zero)\n", m_min_time_before_precharge); |
assert(m_min_time_before_precharge == 0); |
} if (m_min_time_before_activate != 0) { |
printf("BANK-FAIL: TIME-BEFORE-ACTIVATE = %d (should be zero)\n", m_min_time_before_activate); |
assert(m_min_time_before_activate==0); |
} |
break; |
case DDR_ACTIVATE: |
assert(m_wcounter == 0); |
if (((m_state&7)!=0)&&((addr&0x7fff) != m_row)) { |
printf("BANK-FAIL: Attempt to Activate an already active bank without closing it first (m_state = %x)\n", m_state); |
assert((m_state&7)==0); |
} |
if (m_wcounter != 0) { |
printf("BANK-FAIL: ACTIVATE too soon after write (wcounter = %d)\n", m_wcounter); |
assert(m_wcounter == 0); |
} if (m_min_time_before_activate!=0) { |
printf("BANK-FAIL: ACTIVATE too soon after last activate, (ctr=%d)\n", m_min_time_before_activate); |
assert(m_min_time_before_activate==0); |
} |
m_state = 1; |
m_row = addr & 0x7fff; |
m_min_time_before_precharge = ckRAS; |
m_min_time_before_activate = ckRC; |
break; |
case DDR_READ: case DDR_WRITE: |
if (DDR_READ) |
70,15 → 102,27
assert(m_wcounter == 0); |
else |
m_wcounter = 3+4+4; |
printf("BANK::R/W Request, m_state = %d\n", m_state); |
assert((m_state&7) == 7); |
if (m_min_time_before_precharge) |
m_min_time_before_precharge--; |
if (m_min_time_before_activate) |
m_min_time_before_activate--; |
break; |
case DDR_ZQS: |
assert((m_state&7) == 0); |
if (m_min_time_before_precharge) |
m_min_time_before_precharge--; |
if (m_min_time_before_activate) |
m_min_time_before_activate--; |
break; |
case DDR_NOOP: |
m_state <<= 1; |
m_state |= (m_state&2)>>1; |
m_state &= 0x0f; |
if (m_min_time_before_precharge) |
m_min_time_before_precharge--; |
if (m_min_time_before_activate) |
m_min_time_before_activate--; |
break; |
default: |
break; |
135,6 → 179,7
m_reset_counts = 0; |
m_reset_state = 3; |
assert(cmd == DDR_MRSET); |
// Set MR2 |
assert(ba == 2); |
assert(addr == 0x040); |
} break; |
146,8 → 191,9
m_reset_counts = 0; |
m_reset_state = 4; |
assert(cmd == DDR_MRSET); |
// assert(ba == 1); |
// assert(addr == 0x847); |
// Set MR1 |
assert(ba == 1); |
assert(addr == 0x844); |
} break; |
case 4: |
m_reset_counts++; |
158,6 → 204,7
m_reset_counts = 0; |
m_reset_state = 5; |
assert(cmd == DDR_MRSET); |
// Set MR0 |
assert(ba == 0); |
assert(addr == 0x210); |
} break; |
211,6 → 258,8
gbl_counts= m_reset_counts; |
m_nrefresh_issued = nREF; |
m_clocks_since_refresh++; |
for(int i=0; i<NBANKS; i++) |
m_bank[i].tick(cmd, 0); |
} else if (!cke) { |
assert(0&&"Clock not enabled!"); |
} else if ((cmd == DDR_REFRESH)||(m_nrefresh_issued < (int)nREF)) { |
225,7 → 274,7
assert(DDR_NOOP == cmd); |
} |
for(int i=0; i<NBANKS; i++) |
m_bank[i].tick(DDR_REFRESH,0); |
m_bank[i].tick(cmd,0); |
|
if (m_nrefresh_issued == nREF) |
printf(PREFIX "::Refresh cycle complete\n"); |
247,7 → 296,7
assert(0 && "Internal err: Refresh should be handled above"); |
break; |
case DDR_PRECHARGE: |
if (addr & 0x40) { |
if (addr & 0x400) { |
// Precharge all |
for(int i=0; i<NBANKS; i++) |
m_bank[i].tick(DDR_PRECHARGE,0); |
260,6 → 309,7
break; |
case DDR_ACTIVATE: |
assert(m_clocks_since_refresh >= (int)ckRFC); |
printf(PREFIX "::Activating bank %d, address %08x\n", ba, addr); |
m_bank[ba].tick(DDR_ACTIVATE,addr); |
for(int i=0; i<NBANKS; i++) |
if (i!=ba) m_bank[i].tick(DDR_NOOP,0); |
358,7 → 408,7
break; |
} |
|
if (true) { |
if (false) { |
bool flag = false; |
for(int i=0; i<5; i++) { |
int bl = (m_busloc+1+i)&(NTIMESLOTS-1); |
/wbddr3/trunk/rtl/wbddrsdram.v
81,7 → 81,7
o_ddr_dqs, o_ddr_dm, o_ddr_odt, o_ddr_bus_oe, |
o_ddr_addr, o_ddr_ba, o_ddr_data, i_ddr_data); |
parameter CKRBITS = 13, // Bits in CKREFI4 |
CKREFI4 = 13'd6240, // 4 * 7.8us at 200 MHz clock |
CKREFI = 13'd1560, // 4 * 7.8us at 200 MHz clock |
CKRFC = 320, |
CKWR = 3, |
CKXPR = CKRFC+5+2; // Clocks per tXPR timeout |
162,7 → 162,7
w_this_rw_move; |
reg last_closing_bank, last_opening_bank; |
wire w_need_close_this_bank, w_need_open_bank, |
w_r_valid, w_s_valid; |
w_r_valid, w_s_valid, w_s_match; |
// |
// tWTR = 7.5 |
// tRRD = 7.5 |
239,7 → 239,7
end |
|
wire [16:0] w_ckXPR = CKXPR, w_ckRST = 4, w_ckRP = 3, |
w_ckRFC = CKRFC; |
w_ckRFC_first = CKRFC-2-9; |
always @(posedge i_clk) |
if (i_reset) |
reset_instruction <= { 4'h4, `DDR_NOOP, 17'd40_000 }; |
269,8 → 269,8
1'b0, // High order bit of Output Drvr Impedence Ctrl |
2'b0, // Additive latency = 0 |
1'b1, // Low order bit of Rtt_Nom |
1'b1, // DIC set to 2'b01 |
1'b1 }; // MRS1, DLL enable |
1'b0, // DIC set to 2'b00 |
1'b0 }; // MRS1, DLL enable |
// 7. Wait another 4 clocks |
5'h6: reset_instruction <= { 4'h7, `DDR_NOOP, 17'h02 }; |
// 8. Send MRS0 |
298,7 → 298,7
// 14. A single Auto Refresh commands |
5'hd: reset_instruction <= { 4'h3, `DDR_REFRESH, 17'h00 }; |
// 15. Wait for the auto refresh to complete |
5'he: reset_instruction <= { 4'h7, `DDR_NOOP, w_ckRFC }; |
5'he: reset_instruction <= { 4'h7, `DDR_NOOP, w_ckRFC_first }; |
// Two Auto Refresh commands |
default: |
reset_instruction <={4'hb, `DDR_NOOP, 17'd00_000 }; |
347,10 → 347,14
reg [13:0] bank_address [0:7]; |
reg [3:0] bank_wr_ck [0:7]; // tWTR |
reg bank_wr_ckzro [0:7]; // tWTR |
reg [7:0] bank_open; |
reg [7:0] bank_closed; |
|
wire [3:0] write_recycle_clocks; |
assign write_recycle_clocks = CKWR+4+4; |
|
initial bank_open = 8'h00; |
initial bank_closed = 8'hff; |
always @(posedge i_clk) |
begin |
bank_status[0] <= { bank_status[0][2:0], bank_status[0][0] }; |
388,11 → 392,29
bank_wr_ckzro[6] <= (bank_wr_ck[6][3:1]==3'b00); |
bank_wr_ckzro[7] <= (bank_wr_ck[7][3:1]==3'b00); |
|
bank_open[0] <= (bank_status[0][1:0] == 2'h3); |
bank_open[1] <= (bank_status[1][1:0] == 2'h3); |
bank_open[2] <= (bank_status[2][1:0] == 2'h3); |
bank_open[3] <= (bank_status[3][1:0] == 2'h3); |
bank_open[4] <= (bank_status[4][1:0] == 2'h3); |
bank_open[5] <= (bank_status[5][1:0] == 2'h3); |
bank_open[6] <= (bank_status[6][1:0] == 2'h3); |
bank_open[7] <= (bank_status[7][1:0] == 2'h3); |
|
bank_closed[0] <= (bank_status[0][0] == 1'b0); |
bank_closed[1] <= (bank_status[1][0] == 1'b0); |
bank_closed[2] <= (bank_status[2][0] == 1'b0); |
bank_closed[3] <= (bank_status[3][0] == 1'b0); |
bank_closed[4] <= (bank_status[4][0] == 1'b0); |
bank_closed[5] <= (bank_status[5][0] == 1'b0); |
bank_closed[6] <= (bank_status[6][0] == 1'b0); |
bank_closed[7] <= (bank_status[7][0] == 1'b0); |
|
if (w_this_rw_move) |
bank_wr_ck[rw_cmd[16:14]] <= (rw_cmd[`DDR_WEBIT])? 4'h0 |
: write_recycle_clocks; |
|
if (reset_override) |
if (maintenance_override) |
begin |
bank_status[0][0] <= 1'b0; |
bank_status[1][0] <= 1'b0; |
403,21 → 425,13
bank_status[6][0] <= 1'b0; |
bank_status[7][0] <= 1'b0; |
banks_are_closing <= 1'b1; |
end else if ((need_refresh)||(w_precharge_all)) |
begin |
bank_status[0][0] <= 1'b0; |
bank_status[1][0] <= 1'b0; |
bank_status[2][0] <= 1'b0; |
bank_status[3][0] <= 1'b0; |
bank_status[4][0] <= 1'b0; |
bank_status[5][0] <= 1'b0; |
bank_status[6][0] <= 1'b0; |
bank_status[7][0] <= 1'b0; |
banks_are_closing <= 1'b1; |
bank_closed <= 8'hff; |
bank_open <= 8'h00; |
end else if (need_close_bank) |
begin |
bank_status[close_bank_cmd[16:14]] |
<= { bank_status[close_bank_cmd[16:14]][2:0], 1'b0 }; |
bank_open[close_bank_cmd[16:14]] <= 1'b0; |
// bank_status[close_bank_cmd[16:14]][0] <= 1'b0; |
end else if (need_open_bank) |
begin |
426,12 → 440,14
// bank_status[activate_bank_cmd[16:14]][0] <= 1'b1; |
all_banks_closed <= 1'b0; |
banks_are_closing <= 1'b0; |
end else if ((valid_bank)&&(!r_move)) |
bank_closed[activate_bank_cmd[16:14]] <= 1'b0; |
end else if (valid_bank) |
; |
else if (maybe_close_next_bank) |
begin |
bank_status[maybe_close_cmd[16:14]] |
<= { bank_status[maybe_close_cmd[16:14]][2:0], 1'b0 }; |
bank_open[maybe_close_cmd[16:14]] <= 1'b0; |
end else if (maybe_open_next_bank) |
begin |
bank_status[maybe_open_cmd[16:14]] |
439,6 → 455,7
// bank_status[activate_bank_cmd[16:14]][0] <= 1'b1; |
all_banks_closed <= 1'b0; |
banks_are_closing <= 1'b0; |
bank_closed[maybe_open_cmd[16:14]] <= 1'b0; |
end |
end |
|
469,15 → 486,15
// |
reg refresh_ztimer; |
reg [16:0] refresh_counter; |
reg [3:0] refresh_addr; |
reg [2:0] refresh_addr; |
reg [23:0] refresh_instruction; |
always @(posedge i_clk) |
if (reset_override) |
refresh_addr <= 4'hf; |
refresh_addr <= 3'hf; |
else if (refresh_ztimer) |
refresh_addr <= refresh_addr + 1; |
refresh_addr <= refresh_addr + 3'h1; |
else if (refresh_instruction[`DDR_RFBEGIN]) |
refresh_addr <= 4'h0; |
refresh_addr <= 3'h0; |
|
always @(posedge i_clk) |
if (reset_override) |
494,6 → 511,8
refresh_counter <= refresh_instruction[16:0]; |
end |
|
`ifdef QUADRUPLE_REFRESH |
// REFI4 = 13'd6240 |
wire [16:0] w_ckREFIn, w_ckREFRst; |
assign w_ckREFIn[(CKRBITS-1): 0] = CKREFI4-5*CKRFC-2-10; |
assign w_ckREFIn[ 16:(CKRBITS)] = 0; |
500,17 → 519,6
assign w_ckREFRst = CKRFC-2-12; |
|
always @(posedge i_clk) |
if (reset_override) |
refresh_cmd <= { `DDR_NOOP, w_ckREFIn }; |
else if (refresh_ztimer) |
refresh_cmd <= refresh_instruction[20:0]; |
always @(posedge i_clk) |
if (reset_override) |
need_refresh <= 1'b0; |
else if (refresh_ztimer) |
need_refresh <= refresh_instruction[`DDR_NEEDREFRESH]; |
|
always @(posedge i_clk) |
if (refresh_ztimer) |
case(refresh_addr)//NEED-RFC, HAVE-TIMER, |
4'h0: refresh_instruction <= { 3'h2, `DDR_NOOP, w_ckREFIn }; |
533,8 → 541,39
default: |
refresh_instruction <= { 3'h1, `DDR_NOOP, 17'h00 }; |
endcase |
`else |
wire [16:0] w_ckREFI_left, w_ckRFC_nxt; |
assign w_ckREFI_left[12:0] = CKREFI-CKRFC-2-19; |
assign w_ckREFI_left[16:13] = 0; |
assign w_ckRFC_nxt[8:0] = CKRFC+9'h2; |
assign w_ckRFC_nxt[16:9] = 0; |
|
always @(posedge i_clk) |
if (refresh_ztimer) |
case(refresh_addr)//NEED-REFRESH, HAVE-TIMER, BEGIN(start-over) |
3'h0: refresh_instruction <= { 3'h2, `DDR_NOOP, w_ckREFI_left }; |
3'h1: refresh_instruction <= { 3'h6, `DDR_NOOP, 17'd10 }; |
3'h2: refresh_instruction <= { 3'h4, `DDR_PRECHARGE, 17'h0400 }; |
3'h3: refresh_instruction <= { 3'h6, `DDR_NOOP, 17'd2 }; |
3'h4: refresh_instruction <= { 3'h4, `DDR_REFRESH, 17'h00 }; |
3'h5: refresh_instruction <= { 3'h6, `DDR_NOOP, w_ckRFC_nxt }; |
default: |
refresh_instruction <= { 3'h1, `DDR_NOOP, 17'h00 }; |
endcase |
`endif |
|
always @(posedge i_clk) |
if (reset_override) |
refresh_cmd <= { `DDR_NOOP, w_ckREFI_left }; |
else if (refresh_ztimer) |
refresh_cmd <= refresh_instruction[20:0]; |
always @(posedge i_clk) |
if (reset_override) |
need_refresh <= 1'b0; |
else if (refresh_ztimer) |
need_refresh <= refresh_instruction[`DDR_NEEDREFRESH]; |
|
|
// |
// |
// Let's track: when will our bus be active? When will we be reading or |
544,6 → 583,7
reg [`BUSNOW:0] bus_active, bus_read, bus_new, bus_ack; |
reg [1:0] bus_subaddr [`BUSNOW:0]; |
initial bus_active = 0; |
initial bus_ack = 0; |
always @(posedge i_clk) |
begin |
bus_active[`BUSNOW:0] <= { bus_active[(`BUSNOW-1):0], 1'b0 }; |
573,6 → 613,7
bus_subaddr[2] <= 2'h1; |
bus_subaddr[1] <= 2'h2; |
bus_new[{ 2'b0, rw_sub }] <= 1'b1; |
bus_ack[3:0] <= 4'h0; |
bus_ack[{ 2'b0, rw_sub }] <= 1'b1; |
|
bus_read[3:0] <= (rw_we)? 4'h0:4'hf; |
584,6 → 625,8
bus_ack[3] <= 1'b1; |
if (bus_subaddr[1] == s_sub) |
bus_ack[2] <= 1'b1; |
if (bus_subaddr[0] == s_sub) |
bus_ack[1] <= 1'b1; |
end |
end |
|
597,11 → 640,32
// Now, let's see, can we issue a read command? |
// |
// |
wire w_s_match; |
reg pre_valid; |
always @(posedge i_clk) |
if ((refresh_ztimer)&&(refresh_instruction[`DDR_NEEDREFRESH])) |
pre_valid <= 1'b0; |
else if (need_refresh) |
pre_valid <= 1'b0; |
else if (w_this_rw_move) |
pre_valid <= 1'b0; |
else if (bus_active[0]) |
pre_valid <= 1'b0; |
else |
pre_valid <= 1'b1; |
|
assign w_r_valid = (pre_valid)&&(r_pending) |
&&(bank_status[r_bank][1]) |
&&(bank_address[r_bank]==r_row) |
&&((r_we)||(bank_wr_ckzro[r_bank])); |
assign w_s_valid = (pre_valid)&&(s_pending) |
&&(bank_status[s_bank][1]) |
&&(bank_address[s_bank]==s_row) |
&&((s_we)||(bank_wr_ckzro[s_bank])); |
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 |
654,23 → 718,14
end |
end |
|
assign w_need_close_this_bank = (r_pending)&&(bank_status[r_bank][0]) |
assign w_need_close_this_bank = (r_pending) |
&&(bank_open[r_bank]) |
&&(bank_wr_ckzro[r_bank]) |
&&(r_row != bank_address[r_bank]) |
||(pipe_stall)&&(s_pending)&&(bank_status[s_bank][0]) |
||(pipe_stall)&&(s_pending)&&(bank_open[s_bank]) |
&&(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) |
&&((r_we)||(bank_wr_ckzro[r_bank])) |
&&(!bus_active[0]); |
assign w_s_valid = (!need_refresh)&&(s_pending) |
&&(bank_status[s_bank][3]) |
&&(bank_address[s_bank]==s_row) |
&&((r_we)||(bank_wr_ckzro[s_bank])) |
&&(!bus_active[0]); |
assign w_need_open_bank = (r_pending)&&(bank_closed[r_bank]) |
||(pipe_stall)&&(s_pending)&&(bank_closed[s_bank]); |
|
always @(posedge i_clk) |
begin |
677,12 → 732,12
need_close_bank <= (w_need_close_this_bank) |
&&(!need_open_bank) |
&&(!need_close_bank) |
&&(!w_this_closing_bank)&&(!last_closing_bank); |
&&(!w_this_closing_bank); |
|
maybe_close_next_bank <= (r_pending) |
&&(bank_status[r_nxt_bank][0]) |
&&(bank_wr_ckzro[r_nxt_bank]) |
&&(r_nxt_row != bank_address[r_nxt_bank]) |
maybe_close_next_bank <= (s_pending) |
&&(bank_open[s_nxt_bank]) |
&&(bank_wr_ckzro[s_nxt_bank]) |
&&(s_nxt_row != bank_address[s_nxt_bank]) |
&&(!w_this_maybe_close)&&(!last_maybe_close); |
|
close_bank_cmd <= { `DDR_PRECHARGE, r_bank, r_row[13:11], 1'b0, r_row[9:0] }; |
690,13 → 745,14
|
|
need_open_bank <= (w_need_open_bank) |
&&(!w_this_opening_bank)&&(!last_opening_bank); |
&&(!w_this_opening_bank); |
last_open_bank <= (w_this_opening_bank); |
|
maybe_open_next_bank <= (r_pending) |
&&(bank_status[r_bank][0] == 1'b1) |
&&(bank_status[r_nxt_bank][1:0] == 2'b00) |
&&(!w_this_maybe_open)&&(!last_maybe_open); |
maybe_open_next_bank <= (s_pending) |
&&(!need_close_bank) |
&&(!need_open_bank) |
&&(bank_closed[s_nxt_bank]) |
&&(!w_this_maybe_open); // &&(!last_maybe_open); |
|
activate_bank_cmd<= { `DDR_ACTIVATE, r_bank, r_row[13:0] }; |
maybe_open_cmd <= { `DDR_ACTIVATE,r_nxt_bank, r_nxt_row[13:0] }; |
703,8 → 759,9
|
|
|
valid_bank <= ((w_r_valid)||(pipe_stall)&&(w_s_valid)) |
&&(!last_valid_bank)&&(!r_move); |
valid_bank <= ((w_r_valid)||((pipe_stall)&&(w_s_valid))) |
&&(!last_valid_bank)&&(!r_move) |
&&(!w_this_rw_move); |
last_valid_bank <= r_move; |
|
if ((s_pending)&&(pipe_stall)) |
762,14 → 819,14
&&(!need_close_bank)&&(need_open_bank); |
assign w_this_rw_move = (!maintenance_override) |
&&(!need_close_bank)&&(!need_open_bank) |
&&(valid_bank)&&(!r_move); |
&&(valid_bank); |
assign w_this_maybe_close = (!maintenance_override) |
&&(!need_close_bank)&&(!need_open_bank) |
&&((!valid_bank)||(r_move)) |
&&(!valid_bank) |
&&(maybe_close_next_bank); |
assign w_this_maybe_open = (!maintenance_override) |
&&(!need_close_bank)&&(!need_open_bank) |
&&((!valid_bank)||(r_move)) |
&&(!valid_bank) |
&&(!maybe_close_next_bank) |
&&(maybe_open_next_bank); |
always @(posedge i_clk) |
789,7 → 846,7
begin |
cmd <= activate_bank_cmd; |
last_opening_bank <= 1'b1; |
end else if ((valid_bank)&&(!r_move)) |
end else if (valid_bank) |
begin |
cmd <= rw_cmd; |
r_move <= 1'b1; |
805,8 → 862,8
cmd <= { `DDR_NOOP, rw_cmd[(`DDR_WEBIT-1):0] }; |
end |
|
`define LGFIFOLN 3 |
`define FIFOLEN 8 |
`define LGFIFOLN 4 |
`define FIFOLEN 16 |
reg [(`LGFIFOLN-1):0] bus_fifo_head, bus_fifo_tail; |
reg [31:0] bus_fifo_data [0:(`FIFOLEN-1)]; |
reg [1:0] bus_fifo_sub [0:(`FIFOLEN-1)]; |