OpenCores
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

powered by: WebSVN 2.1.0

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