URL
https://opencores.org/ocsvn/wbddr3/wbddr3/trunk
Subversion Repositories wbddr3
Compare Revisions
- This comparison shows the changes necessary to convert path
/wbddr3/trunk
- from Rev 5 to Rev 6
- ↔ Reverse comparison
Rev 5 → Rev 6
/bench/cpp/ddrsdramsim.h
64,7 → 64,8
}; |
|
class DDRSDRAMSIM { |
int m_reset_state, m_reset_counts, m_memlen, m_busloc; |
int m_reset_state, m_reset_counts, m_memlen, m_busloc, |
m_clocks_since_refresh, m_nrefresh_issued; |
unsigned *m_mem; |
BANKINFO m_bank[8]; |
BUSTIMESLOT *m_bus; |
/bench/cpp/ddrsdram_tb.cpp
82,51 → 82,117
m_core->o_ddr_ba, |
m_core->o_ddr_data); |
|
printf("%08lx-WB: %s/%s %s%s%s %s@0x%08x[%08x/%08x] -- ", |
m_tickcount, |
(m_core->i_wb_cyc)?"CYC":" ", |
(m_core->i_wb_stb)?"STB":" ", |
(m_core->o_wb_stall)?"STALL":" ", |
(m_core->o_wb_ack)?"ACK":" ", |
(m_core->o_cmd_accepted)?"BUS":" ", |
(m_core->i_wb_we)?"W":"R", |
(m_core->i_wb_addr), |
(m_core->i_wb_data), |
(m_core->o_wb_data)); |
bool writeout = (!m_core->v__DOT__reset_override); |
|
printf("%s%s %d%d%d%d %s%s%s%s B[%d]@%04x %08x %08x", |
(m_core->o_ddr_reset_n)?" ":"R", |
(m_core->o_ddr_cke)?"CK":" ", |
(m_core->o_ddr_cs_n), |
(m_core->o_ddr_ras_n), |
(m_core->o_ddr_cas_n), |
(m_core->o_ddr_we_n), |
// |
(m_core->o_ddr_dqs)?"D":" ", |
(m_core->o_ddr_dm)?"M":" ", |
(m_core->o_ddr_odt)?"O":" ", |
(m_core->o_ddr_bus_oe)?"E":" ", |
// |
(m_core->o_ddr_ba), |
(m_core->o_ddr_addr), |
(m_core->i_ddr_data), |
(m_core->o_ddr_data)); |
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":" ", |
(m_core->i_wb_stb)?"STB":" ", |
(m_core->o_wb_stall)?"STALL":" ", |
(m_core->o_wb_ack)?"ACK":" ", |
(m_core->o_cmd_accepted)?"BUS":" ", |
(m_core->i_wb_we)?"W":"R", |
(m_core->i_wb_addr), |
(m_core->i_wb_data), |
(m_core->o_wb_data)); |
|
// Reset logic |
printf(" RST(%06x%s[%d] - %08x->%08x)", |
m_core->v__DOT__reset_timer, |
(m_core->v__DOT__reset_ztimer)?"Z":" ", |
(m_core->v__DOT__reset_address), |
(m_core->v__DOT__reset_instruction), |
(m_core->v__DOT__reset_cmd)); |
printf("%s%s %d%d%d%d %s%s%s%s B[%d]@%04x %08x %08x", |
(m_core->o_ddr_reset_n)?" ":"R", |
(m_core->o_ddr_cke)?"CK":" ", |
(m_core->o_ddr_cs_n), |
(m_core->o_ddr_ras_n), |
(m_core->o_ddr_cas_n), |
(m_core->o_ddr_we_n), |
// |
(m_core->o_ddr_dqs)?"D":" ", |
(m_core->o_ddr_dm)?"M":" ", |
(m_core->o_ddr_odt)?"O":" ", |
(m_core->o_ddr_bus_oe)?"E":" ", |
// |
(m_core->o_ddr_ba), |
(m_core->o_ddr_addr), |
(m_core->i_ddr_data), |
(m_core->o_ddr_data)); |
|
extern int gbl_state, gbl_counts; |
printf(" %d:%08x ", gbl_state, gbl_counts); |
/* |
// Reset logic |
printf(" RST(%06x%s[%d] - %08x->%08x)", |
m_core->v__DOT__reset_timer, |
(m_core->v__DOT__reset_ztimer)?"Z":" ", |
(m_core->v__DOT__reset_address), |
(m_core->v__DOT__reset_instruction), |
(m_core->v__DOT__reset_cmd)); |
*/ |
|
if (m_core->v__DOT__reset_override) |
printf(" OVERRIDE"); |
printf("\n"); |
printf(" %s%03x[%d]%04x:%d", |
(m_core->v__DOT__r_pending)?"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)); |
printf(" %s%s%s", |
(m_core->v__DOT__all_banks_closed)?"b":"B", |
(m_core->v__DOT__need_close_bank)?"C":"N", |
//:(m_core->v__DOT__maybe_close_next_bank)?"c":"N", |
(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@%05x%s", |
(m_core->v__DOT__r_bank==i)?"R":"[", |
m_core->v__DOT__bank_status[i], |
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:%08x:%08x", |
(m_core->v__DOT__reset_override)?"R":" ", |
(m_core->v__DOT__need_refresh)?"N":" ", |
(m_core->v__DOT__need_close_bank)?"C":" ", |
(m_core->v__DOT__need_open_bank)?"O":" ", |
(m_core->v__DOT__valid_bank)?"V":" ", |
m_core->v__DOT__activate_bank_cmd, |
m_core->v__DOT__cmd); |
|
printf(" F%05x:%d%d%d:%d:%08x", |
m_core->v__DOT__refresh_clk, |
m_core->v__DOT__need_refresh, |
m_core->v__DOT__midrefresh, |
m_core->v__DOT__endrefresh, |
m_core->v__DOT__midrefresh_hctr, |
m_core->v__DOT__midrefresh_lctr); |
|
if (m_core->v__DOT__reset_override) |
printf(" OVERRIDE"); |
//if(m_core->v__DOT__last_open_bank)printf(" LST-OPEN"); |
switch(cmd) { |
case DDR_MRSET: printf(" MRSET"); break; |
case DDR_REFRESH: printf(" REFRESH"); break; |
case DDR_PRECHARGE: printf(" PRECHARGE%s", (m_core->o_ddr_addr&0x400)?"-ALL":""); break; |
case DDR_ACTIVATE: printf(" ACTIVATE"); break; |
case DDR_WRITE: printf(" WRITE"); break; |
case DDR_READ: printf(" READ"); break; |
case DDR_ZQS: printf(" ZQS"); break; |
case DDR_NOOP: printf(" NOOP"); break; |
default: printf(" Unknown-CMD(%02x)", cmd); break; |
} |
|
// Decode the command |
|
printf("\n"); |
} |
|
m_core->eval(); |
m_core->i_clk = 0; |
m_core->eval(); |
/bench/cpp/ddrsdramsim.cpp
39,23 → 39,24
#include <assert.h> |
|
const unsigned ckCL = 5, |
ckRC = 3; |
ckRC = 3, |
ckRFC = 320, // Clocks from refresh to activate |
nREF = 4, |
ckREFI = 1560, // 7.8us @ 200MHz = 7.8e-6 * 200e6 = 1560 |
ckREFIn = nREF*ckREFI - (nREF-1) * ckRFC; |
|
#include "ddrsdramsim.h" |
void BANKINFO::tick(int cmd, unsigned addr) { |
switch(cmd) { |
case DDR_PRECHARGE: |
m_state <<= 1; |
// m_state |= 1; |
m_state &= 6; |
m_state = 6; |
break; |
case DDR_ACTIVATE: |
m_state <<= 1; |
m_state |= 1; |
m_state &= 7; |
m_state = 1; |
m_row = addr & 0x7fff; |
break; |
case DDR_READ: case DDR_WRITE: |
printf("BANK::R/W Request, m_state = %d\n", m_state); |
assert((m_state&7) == 7); |
break; |
case DDR_ZQS: |
111,6 → 112,7
} break; |
case 2: |
m_reset_counts++; |
assert(cke); |
if (cmd != DDR_NOOP) { |
assert(m_reset_counts > 147); |
m_reset_counts = 0; |
121,6 → 123,7
} break; |
case 3: |
m_reset_counts++; |
assert(cke); |
if (cmd != DDR_NOOP) { |
// assert(m_reset_counts > 3); |
m_reset_counts = 0; |
131,6 → 134,7
} break; |
case 4: |
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); |
assert(m_reset_counts > 3); |
142,6 → 146,7
} break; |
case 5: |
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); |
assert(m_reset_counts > 11); |
152,6 → 157,7
} break; |
case 6: |
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); |
assert(m_reset_counts > 512); |
162,6 → 168,7
} break; |
case 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); |
assert(m_reset_counts > 3); |
168,9 → 175,11
m_reset_counts = 0; |
m_reset_state = 8; |
assert(cmd == DDR_REFRESH); |
m_clocks_since_refresh = 0; |
} break; |
case 8: |
m_reset_counts++; |
assert(cke); |
assert(cmd == DDR_NOOP); |
if (m_reset_counts > 140) { |
m_reset_state = 16; |
183,9 → 192,28
|
gbl_state = m_reset_state; |
gbl_counts= m_reset_counts; |
} else if (cke == 0) { |
m_nrefresh_issued = nREF; |
} else if (!cke) { |
assert(0&&"Clock not enabled!"); |
} else switch(cmd) { |
} else if ((cmd == DDR_REFRESH)||(m_nrefresh_issued < (int)nREF)) { |
if (DDR_REFRESH == cmd) { |
m_clocks_since_refresh = 0; |
if (m_nrefresh_issued >= (int)nREF) |
m_nrefresh_issued = 0; |
else |
m_nrefresh_issued++; |
} else { |
m_clocks_since_refresh++; |
assert(DDR_NOOP == cmd); |
} |
for(int i=0; i<NBANKS; i++) |
m_bank[i].tick(DDR_REFRESH,0); |
} else { |
// In operational mode!! |
|
m_clocks_since_refresh++; |
assert(m_clocks_since_refresh < (int)ckREFIn); |
switch(cmd) { |
case DDR_MRSET: |
assert(0&&"Modes should only be set in reset startup"); |
for(int i=0; i<NBANKS; i++) |
194,6 → 222,8
case DDR_REFRESH: |
for(int i=0; i<NBANKS; i++) |
m_bank[i].tick(DDR_REFRESH,0); |
m_clocks_since_refresh = 0; |
assert(0 && "Internal err: Refresh should be handled above"); |
break; |
case DDR_PRECHARGE: |
if (addr & 0x40) { |
214,8 → 244,11
break; |
case DDR_WRITE: |
{ |
// This SIM doesn't handle out of order writes |
assert((addr&7)==0); |
m_bank[ba].tick(DDR_WRITE, addr); |
for(int i=0; i<NBANKS; i++) |
m_bank[i].tick(DDR_WRITE,addr); |
if (i!=ba)m_bank[i].tick(DDR_NOOP,addr); |
unsigned addr = m_bank[ba].m_row; |
addr <<= 13; |
addr |= ba; |
247,8 → 280,11
} break; |
case DDR_READ: |
{ |
// This SIM doesn't handle out of order reads |
assert((addr&7)==0); |
m_bank[ba].tick(DDR_READ, addr); |
for(int i=0; i<NBANKS; i++) |
m_bank[i].tick(DDR_READ,addr); |
if (i!=ba)m_bank[i].tick(DDR_NOOP,addr); |
unsigned addr = m_bank[ba].m_row; |
addr <<= 13; |
addr |= ba; |
293,6 → 329,7
for(int i=0; i<NBANKS; i++) |
m_bank[i].tick(DDR_NOOP,addr); |
break; |
} |
} |
|
m_busloc = (m_busloc+1)&(NTIMESLOTS-1); |
/rtl/wbddrsdram.v
127,7 → 127,15
// Can we preload the next bank? |
reg [13:0] r_nxt_row; |
reg [2:0] r_nxt_bank; |
|
|
reg need_close_bank, need_close_this_bank, |
last_close_bank, maybe_close_next_bank, |
last_maybe_close, |
need_open_bank, last_open_bank, maybe_open_next_bank, |
last_maybe_open, |
valid_bank, last_valid_bank; |
reg [(`DDR_CMDLEN-1):0] close_bank_cmd, activate_bank_cmd, |
maybe_close_cmd, maybe_open_cmd, rw_cmd; |
// |
// tWTR = 7.5 |
// tRRD = 7.5 |
167,12 → 175,12
// 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 [3:0] reset_address; |
reg [4:0] reset_address; |
reg [(`DDR_CMDLEN-1):0] reset_cmd, cmd, refresh_cmd; |
reg [24:0] reset_instruction; |
reg [16:0] reset_timer; |
initial reset_override = 1'b1; |
initial reset_address = 4'h0; |
initial reset_address = 5'h0; |
always @(posedge i_clk) |
if (i_reset) |
begin |
214,18 → 222,18
reset_instruction <= { 4'h4, `DDR_NOOP, 17'd40_000 }; |
else if (reset_ztimer) case(reset_address) // RSTDONE, TIMER, CKE, ?? |
// 1. Reset asserted (active low) for 200 us. (@200MHz) |
4'h0: reset_instruction <= { 4'h4, `DDR_NOOP, 17'd40_000 }; |
5'h0: reset_instruction <= { 4'h4, `DDR_NOOP, 17'd40_000 }; |
// 2. Reset de-asserted, wait 500 us before asserting CKE |
4'h1: reset_instruction <= { 4'h6, `DDR_NOOP, 17'd100_000 }; |
5'h1: reset_instruction <= { 4'h6, `DDR_NOOP, 17'd100_000 }; |
// 3. Assert CKE, wait minimum of Reset CKE Exit time |
4'h2: reset_instruction <= { 4'h7, `DDR_NOOP, w_ckXPR }; |
5'h2: reset_instruction <= { 4'h7, `DDR_NOOP, w_ckXPR }; |
// 4. Look MR2. (1CK, no TIMER) |
4'h3: reset_instruction <= { 4'h3, `DDR_MRSET, 3'h2, |
5'h3: reset_instruction <= { 4'h3, `DDR_MRSET, 3'h2, |
3'h0, 2'b00, 1'b0, 1'b0, 1'b1, 3'b0, 3'b0 }; // MRS2 |
// 3. Wait 4 clocks (tMRD) |
4'h4: reset_instruction <= { 4'h7, `DDR_NOOP, 17'h02 }; |
5'h4: reset_instruction <= { 4'h7, `DDR_NOOP, 17'h02 }; |
// 5. Set MR1 |
4'h5: reset_instruction <= { 4'h3, `DDR_MRSET, 3'h1, |
5'h5: reset_instruction <= { 4'h3, `DDR_MRSET, 3'h1, |
1'h0, // Reserved for Future Use (RFU) |
1'b0, // Qoff - output buffer enabled |
1'b1, // TDQS ... enabled |
241,9 → 249,9
1'b1, // DIC set to 2'b01 |
1'b1 }; // MRS1, DLL enable |
// 7. Wait another 4 clocks |
4'h6: reset_instruction <= { 4'h7, `DDR_NOOP, 17'h02 }; |
5'h6: reset_instruction <= { 4'h7, `DDR_NOOP, 17'h02 }; |
// 8. Send MRS0 |
4'h7: reset_instruction <= { 4'h3, `DDR_MRSET, 3'h0, |
5'h7: reset_instruction <= { 4'h3, `DDR_MRSET, 3'h0, |
1'b0, // Reserved for future use |
1'b0, // PPD control, (slow exit(DLL off)) |
3'b1, // Write recovery for auto precharge |
255,19 → 263,19
1'b0, // Low bit of cas latency |
2'b0 }; // Burst length = 8 (Fixed) |
// 9. Wait tMOD, is max(12 clocks, 15ns) |
4'h8: reset_instruction <= { 4'h7, `DDR_NOOP, 17'h0a }; |
5'h8: reset_instruction <= { 4'h7, `DDR_NOOP, 17'h0a }; |
// 10. Issue a ZQCL command to start ZQ calibration, A10 is high |
4'h9: reset_instruction <= { 4'h3, `DDR_ZQS, 6'h0, 1'b1, 10'h0}; |
5'h9: reset_instruction <= { 4'h3, `DDR_ZQS, 6'h0, 1'b1, 10'h0}; |
//11.Wait for both tDLLK and tZQinit completed, both are 512 cks |
4'ha: reset_instruction <= { 4'h7, `DDR_NOOP, 17'd512 }; |
5'ha: reset_instruction <= { 4'h7, `DDR_NOOP, 17'd512 }; |
// 12. Precharge all command |
4'hb: reset_instruction <= { 4'h3, `DDR_PRECHARGE, 6'h0, 1'b1, 10'h0 }; |
5'hb: reset_instruction <= { 4'h3, `DDR_PRECHARGE, 6'h0, 1'b1, 10'h0 }; |
// 13. Wait for the precharge to complete |
4'hc: reset_instruction <= { 4'h7, `DDR_NOOP, w_ckRP }; |
5'hc: reset_instruction <= { 4'h7, `DDR_NOOP, w_ckRP }; |
// 14. A single Auto Refresh commands |
4'hd: reset_instruction <= { 4'h3, `DDR_REFRESH, 17'h00 }; |
5'hd: reset_instruction <= { 4'h3, `DDR_REFRESH, 17'h00 }; |
// 15. Wait for the auto refresh to complete |
4'he: reset_instruction <= { 4'h7, `DDR_NOOP, w_ckRFC }; |
5'he: reset_instruction <= { 4'h7, `DDR_NOOP, w_ckRFC }; |
// Two Auto Refresh commands |
default: |
reset_instruction <={4'hb, `DDR_NOOP, 17'd00_000 }; |
274,12 → 282,12
endcase |
// reset_instruction <= reset_mem[reset_address]; |
|
initial reset_address = 4'h0; |
initial reset_address = 5'h0; |
always @(posedge i_clk) |
if (i_reset) |
reset_address <= 4'h1; |
else if (reset_ztimer) |
reset_address <= reset_address + 4'h1; |
reset_address <= 5'h1; |
else if ((reset_ztimer)&&(reset_override)) |
reset_address <= reset_address + 5'h1; |
// |
// initial reset_mem = |
// 0. !DONE, TIMER,RESET_N=0, CKE=0, CMD = NOOP, TIMER = 200us ( 40,000) |
312,44 → 320,63
|
wire w_precharge_all; |
reg banks_are_closing, all_banks_closed; |
reg [2:0] bank_status[7:0]; |
reg [3:0] bank_status [0:7]; |
reg [13:0] bank_address [0:7]; |
|
always @(posedge i_clk) |
begin |
bank_status[0] = { bank_status[0][1:0], bank_status[0][0] }; |
bank_status[1] = { bank_status[1][1:0], bank_status[1][0] }; |
bank_status[2] = { bank_status[2][1:0], bank_status[2][0] }; |
bank_status[3] = { bank_status[3][1:0], bank_status[3][0] }; |
bank_status[4] = { bank_status[4][1:0], bank_status[4][0] }; |
bank_status[5] = { bank_status[5][1:0], bank_status[5][0] }; |
bank_status[6] = { bank_status[6][1:0], bank_status[6][0] }; |
bank_status[7] = { bank_status[7][1:0], bank_status[7][0] }; |
all_banks_closed <= (bank_status[0][1:0] == 2'b00) |
&&(bank_status[1][1:0] == 2'b00) |
&&(bank_status[2][1:0] == 2'b00) |
&&(bank_status[3][1:0] == 2'b00) |
&&(bank_status[4][1:0] == 2'b00) |
&&(bank_status[5][1:0] == 2'b00) |
&&(bank_status[6][1:0] == 2'b00) |
&&(bank_status[7][1:0] == 2'b00); |
bank_status[0] <= { bank_status[0][2:0], bank_status[0][0] }; |
bank_status[1] <= { bank_status[1][2:0], bank_status[1][0] }; |
bank_status[2] <= { bank_status[2][2:0], bank_status[2][0] }; |
bank_status[3] <= { bank_status[3][2:0], bank_status[3][0] }; |
bank_status[4] <= { bank_status[4][2:0], bank_status[4][0] }; |
bank_status[5] <= { bank_status[5][2:0], bank_status[5][0] }; |
bank_status[6] <= { bank_status[6][2:0], bank_status[6][0] }; |
bank_status[7] <= { bank_status[7][2:0], bank_status[7][0] }; |
all_banks_closed <= (bank_status[0][2:0] == 3'b00) |
&&(bank_status[1][2:0] == 3'b00) |
&&(bank_status[2][2:0] == 3'b00) |
&&(bank_status[3][2:0] == 3'b00) |
&&(bank_status[4][2:0] == 3'b00) |
&&(bank_status[5][2:0] == 3'b00) |
&&(bank_status[6][2:0] == 3'b00) |
&&(bank_status[7][2:0] == 3'b00); |
if ((!reset_override)&&(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; |
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; |
end else if (need_close_bank) |
begin |
bank_status[r_bank][0] = 1'b0; |
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]][0] <= 1'b0; |
end else if (need_open_bank) |
begin |
bank_status[r_bank][0] = 1'b1; |
bank_status[activate_bank_cmd[16:14]] |
<= { bank_status[activate_bank_cmd[16:14]][2:0], 1'b1 }; |
// 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)) |
; |
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 }; |
end else if (maybe_open_next_bank) |
begin |
bank_status[maybe_open_cmd[16:14]] |
<= { bank_status[maybe_open_cmd[16:14]][2:0], 1'b1 }; |
// bank_status[activate_bank_cmd[16:14]][0] <= 1'b1; |
all_banks_closed <= 1'b0; |
banks_are_closing <= 1'b0; |
end |
end |
|
385,7 → 412,11
else if (|refresh_clk) |
refresh_clk <= refresh_clk-1; |
always @(posedge i_clk) |
need_refresh <= (refresh_clk == 0)||(midrefresh); |
if (refresh_clk == 0) |
need_refresh <= 1'b1; |
else if (endrefresh) |
need_refresh <= 1'b0; |
|
always @(posedge i_clk) |
if (!need_refresh) |
refresh_cmd <= { `DDR_NOOP, 17'h00 }; |
399,10 → 430,10
midrefresh <= (need_refresh)&&(all_banks_closed)&&(~refresh_clear); |
|
always @(posedge i_clk) |
if (!midrefresh) |
midrefresh_hctr <= 3'h4; |
else if ((midrefresh_lctr == 0)&&(|midrefresh_hctr)) |
midrefresh_hctr <= midrefresh_hctr - 1; |
if (!need_refresh) |
midrefresh_hctr <= 3'h0; |
else if ((midrefresh_lctr == 0)&&(!midrefresh_hctr[2])) |
midrefresh_hctr <= midrefresh_hctr + 3'h1; |
always @(posedge i_clk) |
if ((!need_refresh)||(!midrefresh)) |
endrefresh <= 1'b0; |
409,12 → 440,12
else if (midrefresh_hctr == 3'h0) |
endrefresh <= 1'b1; |
always @(posedge i_clk) |
if (!midrefresh) |
if (!need_refresh) |
midrefresh_lctr <= CKRFC; |
else if (midrefresh_lctr == 0) |
midrefresh_lctr <= 0; |
midrefresh_lctr <= CKRFC; |
else |
midrefresh_lctr <= CKRFC; |
midrefresh_lctr <= midrefresh_lctr-1; |
|
always @(posedge i_clk) |
refresh_clear <= (need_refresh)&&(endrefresh)&&(midrefresh_lctr == 0); |
487,55 → 518,53
r_sub <= i_wb_addr[1:0]; |
|
// pre-emptive work |
r_nxt_row <= i_wb_addr[25:12]+14'h1; |
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 |
end |
|
reg [2:0] bank_active[7:0]; |
reg [13:0] bank_address[7:0]; |
wire w_need_close_this_bank, w_need_open_bank; |
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); |
|
reg [(`DDR_CMDLEN-1):0] close_bank_cmd, activate_bank_cmd, rw_cmd; |
reg need_close_bank, need_close_this_bank, |
last_close_bank, maybe_close_next_bank, |
need_open_bank, last_open_bank, maybe_open_next_bank, |
valid_bank, last_valid_bank; |
wire w_this_closing_bank, w_this_opening_bank, |
w_this_maybe_close, w_this_maybe_open; |
reg last_closing_bank, last_opening_bank; |
always @(posedge i_clk) |
begin |
need_close_bank <= (r_pending)&&(bank_active[r_bank][0]) |
&&(r_row != bank_address[r_bank])&&(!last_close_bank); |
need_close_this_bank <= (r_pending)&&(bank_active[r_bank][0]) |
&&(r_row != bank_address[r_bank]); |
last_close_bank <= need_close_bank; |
need_close_bank <= (w_need_close_this_bank) |
&&(!w_this_closing_bank)&&(!last_closing_bank); |
|
maybe_close_next_bank <= (r_pending) |
&&(bank_active[r_nxt_bank][0]) |
&&(bank_status[r_nxt_bank][0]) |
&&(r_nxt_row != bank_address[r_nxt_bank]) |
&&(!need_close_this_bank); |
&&(!w_this_maybe_close)&&(!last_maybe_close); |
|
close_bank_cmd <= (maybe_close_next_bank) |
? { `DDR_PRECHARGE, r_nxt_bank, r_nxt_row[13:11], 1'b0, r_nxt_row[9:0] } |
: { `DDR_PRECHARGE, r_bank, r_row[13:11], 1'b0, r_row[9:0] }; |
close_bank_cmd <= { `DDR_PRECHARGE, r_bank, r_row[13:11], 1'b0, r_row[9:0] }; |
maybe_close_cmd <= { `DDR_PRECHARGE, r_nxt_bank, r_nxt_row[13:11], 1'b0, r_nxt_row[9:0] }; |
|
|
need_open_bank <= (r_pending)&&(bank_active[r_bank][1:0]==2'b00) |
&&(!last_open_bank); |
last_open_bank <= need_open_bank; |
need_open_bank <= (w_need_open_bank) |
&&(!w_this_opening_bank)&&(!last_opening_bank); |
last_open_bank <= (w_this_opening_bank); |
|
maybe_open_next_bank <= (r_pending) |
&&(bank_active[r_nxt_bank][1:0] == 2'b00) |
&&(!need_open_bank)&&(!need_close_bank); |
&&(bank_status[r_bank][0] == 1'b1) |
&&(bank_status[r_nxt_bank][1:0] == 2'b00) |
&&(!w_this_maybe_open)&&(!last_maybe_open); |
last_maybe_open <= (w_this_maybe_open); |
|
activate_bank_cmd <= (maybe_open_next_bank) |
? { `DDR_ACTIVATE,r_nxt_bank, r_nxt_row[13:0] } |
: { `DDR_ACTIVATE, r_bank, r_row[13:0] }; |
activate_bank_cmd<= { `DDR_ACTIVATE, r_bank, r_row[13:0] }; |
maybe_open_cmd <= { `DDR_ACTIVATE,r_nxt_bank, r_nxt_row[13:0] }; |
|
|
|
valid_bank <= (r_pending)&&(bank_active[r_bank][1:0]==2'b11) |
valid_bank <= (r_pending)&&(bank_status[r_bank][3]) |
&&(bank_address[r_bank]==r_row) |
&&(!last_valid_bank); |
last_valid_bank <= valid_bank; |
&&(!last_valid_bank)&&(!r_move) |
&&(!bus_active[0]); |
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 }; |
583,8 → 612,26
o_ddr_cke <= 1'b0; |
else if (reset_ztimer) |
o_ddr_cke <= reset_instruction[`DDR_CKEBIT]; |
|
assign w_this_closing_bank = (!reset_override)&&(!need_refresh) |
&&(need_close_bank); |
assign w_this_opening_bank = (!reset_override)&&(!need_refresh) |
&&(!need_close_bank)&&(need_open_bank); |
assign w_this_maybe_close = (!reset_override)&&(!need_refresh) |
&&(!need_close_bank)&&(!need_open_bank) |
&&((!valid_bank)||(r_move)) |
&&(maybe_close_next_bank); |
assign w_this_maybe_open = (!reset_override)&&(!need_refresh) |
&&(!need_close_bank)&&(!need_open_bank) |
&&((!valid_bank)||(r_move)) |
&&(!maybe_close_next_bank) |
&&(maybe_open_next_bank); |
always @(posedge i_clk) |
begin |
last_opening_bank <= 1'b0; |
last_closing_bank <= 1'b0; |
last_maybe_open <= 1'b0; |
last_maybe_close <= 1'b0; |
r_move <= 1'b0; |
if (reset_override) |
cmd <= reset_cmd[`DDR_CSBIT:0]; |
592,13 → 639,25
begin |
cmd <= refresh_cmd; // The command from the refresh logc |
end else if (need_close_bank) |
begin |
cmd <= close_bank_cmd; |
else if (need_open_bank) |
last_closing_bank <= 1'b1; |
end else if (need_open_bank) |
begin |
cmd <= activate_bank_cmd; |
else if ((valid_bank)&&(bus_active[2:0]==3'h0)) |
last_opening_bank <= 1'b1; |
end else if ((valid_bank)&&(!r_move)) |
begin |
cmd <= rw_cmd; |
r_move <= 1'b1; |
end else if (maybe_close_next_bank) |
begin |
cmd <= maybe_close_cmd; |
last_maybe_close <= 1'b1; |
end else if (maybe_open_next_bank) |
begin |
cmd <= maybe_open_cmd; |
last_maybe_open <= 1'b1; |
end else |
cmd <= { `DDR_NOOP, rw_cmd[(`DDR_WEBIT-1):0] }; |
end |