OpenCores
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)];

powered by: WebSVN 2.1.0

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