URL
https://opencores.org/ocsvn/wbddr3/wbddr3/trunk
Subversion Repositories wbddr3
Compare Revisions
- This comparison shows the changes necessary to convert path
/wbddr3
- from Rev 12 to Rev 13
- ↔ Reverse comparison
Rev 12 → Rev 13
/trunk/bench/cpp/ddrsdramsim.h
48,7 → 48,7
#define DDR_NOOP 7 |
|
#define NBANKS 8 |
#define NTIMESLOTS 16 |
#define NTIMESLOTS 32 |
|
class BANKINFO { |
public: |
59,13 → 59,14
|
class BUSTIMESLOT { |
public: |
int m_used, m_read, m_data; |
int m_used, m_read, m_data, m_rtt; |
unsigned m_addr; |
}; |
|
class DDRSDRAMSIM { |
int m_reset_state, m_reset_counts, m_memlen, m_busloc, |
m_clocks_since_refresh, m_nrefresh_issued; |
m_clocks_since_refresh, m_nrefresh_issued, |
m_last_dqs, m_last_rtt; |
unsigned *m_mem; |
BANKINFO m_bank[8]; |
BUSTIMESLOT *m_bus; |
/trunk/bench/cpp/ddrsdram_tb.cpp
129,10 → 129,11
m_core->v__DOT__bus_fifo_sub[m_core->v__DOT__bus_fifo_tail], |
m_core->v__DOT__bus_fifo_data[m_core->v__DOT__bus_fifo_tail]); |
|
printf(" BUS[%03x/%03x/%03x/%d]", |
printf(" BUS[A%03x/R%03x/N%03x/K%03x/%d]", |
(m_core->v__DOT__bus_active), |
(m_core->v__DOT__bus_read), |
(m_core->v__DOT__bus_new), |
(m_core->v__DOT__bus_ack), |
(m_core->v__DOT__bus_subaddr[8])); |
|
/* |
503,6 → 504,19
} |
} |
} |
|
// Same thing, but writing all first before reading |
{ |
unsigned v, a; |
for(int i=0; i<8; i++) { |
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); |
goto test_failure; |
} |
} |
} |
#endif |
|
#ifdef SINGULAR_WRITE |
/trunk/bench/cpp/ddrsdramsim.cpp
95,6 → 95,8
m_bus = new BUSTIMESLOT[NTIMESLOTS]; |
for(int i=0; i<NTIMESLOTS; i++) |
m_bus[i].m_used = 0; |
for(int i=0; i<NTIMESLOTS; i++) |
m_bus[i].m_rtt = 0; |
m_busloc = 0; |
} |
|
102,9 → 104,10
int csn, int rasn, int casn, int wen, |
int dqs, int dm, int odt, int busoe, |
int addr, int ba, int data) { |
|
BUSTIMESLOT *ts, *nxtts; |
int cmd = (reset_n?0:32)|(cke?0:16)|(csn?8:0) |
|(rasn?4:0)|(casn?2:0)|(wen?1:0); |
|
if ((m_reset_state!=0)&&(reset_n==0)) { |
m_reset_state = 0; |
m_reset_counts = 0; |
354,23 → 357,71
m_bank[i].tick(DDR_NOOP,addr); |
break; |
} |
|
if (true) { |
bool flag = false; |
for(int i=0; i<5; i++) { |
int bl = (m_busloc+1+i)&(NTIMESLOTS-1); |
nxtts = &m_bus[bl]; |
if (nxtts->m_used) { |
flag = true; |
break; |
} |
} if (flag) { |
printf("DQS = %d BUSLOC = %d\n", dqs, (m_busloc+1)&(NTIMESLOTS-1)); |
for(int i=0; i<5; i++) { |
int bl = (m_busloc+1+i)&(NTIMESLOTS-1); |
nxtts = &m_bus[bl]; |
printf("BUS[%2d] ", bl); |
if (nxtts->m_used) |
printf(" USED"); |
if (nxtts->m_read) |
printf(" READ"); |
if (nxtts->m_rtt) |
printf(" RTT"); |
printf("\n"); |
}} |
} |
|
ts = &m_bus[(m_busloc+1)&(NTIMESLOTS-1)]; |
if (dqs) |
assert((ts->m_rtt)&&(m_last_rtt)); |
else if (!m_last_dqs) |
assert(!m_last_rtt); |
} |
|
m_busloc = (m_busloc+1)&(NTIMESLOTS-1); |
|
BUSTIMESLOT *ts = &m_bus[m_busloc]; |
ts = &m_bus[m_busloc]; |
nxtts = &m_bus[(m_busloc+1)&(NTIMESLOTS-1)]; |
unsigned vl = ts->m_data; |
assert( ((!ts->m_used)||(busoe)) |
|| ((ts->m_used)&&(ts->m_read))); |
|| ((ts->m_used)&&(ts->m_read)&&(!busoe)) |
|| ((ts->m_used)&&(!ts->m_read)&&(busoe)) |
); |
|
m_last_dqs = dqs; |
m_last_rtt = ts->m_rtt; |
|
if (ts->m_used) { |
if (ts->m_read) |
assert((!dqs)&&(!m_last_dqs)); |
else |
assert((dqs) && (m_last_dqs)); |
} else if (!nxtts->m_used) |
assert(!dqs); |
|
assert((!ts->m_used)||(ts->m_addr < (unsigned)m_memlen)); |
if ((ts->m_used)&&(!ts->m_read)&&(!dm)) { |
printf(PREFIX "::Setting MEM[%08x] = %08x\n", ts->m_addr, data); |
m_mem[ts->m_addr] = data; |
} |
|
m_bus[(m_busloc+3)&(NTIMESLOTS-1)].m_rtt = (odt)&&(reset_n); |
ts->m_used = 0; |
ts->m_read = 0; |
ts->m_addr = -1; |
ts->m_rtt = 0; |
return (!busoe)?vl:data; |
} |
|
/trunk/bench/cpp/Makefile
36,10 → 36,8
################################################################################ |
## |
## |
all: $(OBJDIR)/ ddrsdram_tb |
|
OBJDIR := obj-pc |
CXX := g++ |
OBJDIR := obj-pc |
YYMMDD := `date +%Y%m%d` |
RTLD := ../../rtl |
VOBJDR := $(RTLD)/obj_dir |
50,6 → 48,9
VOBJDR := $(RTLD)/obj_dir |
VLIB := $(VROOT)/include/verilated.cpp |
|
all: $(OBJDIR)/ ddrsdram_tb |
|
|
$(OBJDIR)/: |
@bash -c "if [ ! -e $(OBJDIR) ]; then mkdir -p $(OBJDIR); fi" |
|
69,3 → 70,7
clean: |
rm -rf $(OBJDIR)/ ddrsdram_tb |
|
.PHONY: test |
test: ddrsdram_tb |
./ddrsdram_tb |
|
/trunk/rtl/wbddrsdram.v
80,7 → 80,8
o_ddr_cs_n, o_ddr_ras_n, o_ddr_cas_n, o_ddr_we_n, |
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 CKREFI4 = 13'd6240, // 4 * 7.8us at 200 MHz clock |
parameter CKRBITS = 13, // Bits in CKREFI4 |
CKREFI4 = 13'd6240, // 4 * 7.8us at 200 MHz clock |
CKRFC = 320, |
CKWR = 3, |
CKXPR = CKRFC+5+2; // Clocks per tXPR timeout |
100,7 → 101,8
// DQS outputs:set to 3'b010 when data is active, 3'b100 (i.e. 2'bzz) ow |
output wire o_ddr_dqs; |
output reg o_ddr_dm; |
output wire o_ddr_odt, o_ddr_bus_oe; |
output reg o_ddr_odt; |
output wire o_ddr_bus_oe; |
// Address outputs |
output wire [13:0] o_ddr_addr; |
output wire [2:0] o_ddr_ba; |
493,10 → 495,9
end |
|
wire [16:0] w_ckREFIn, w_ckREFRst; |
assign w_ckREFIn[ 12: 0] = CKREFI4-5*CKRFC-2-10; |
assign w_ckREFIn[ 16:13] = 4'h0; |
assign w_ckREFRst[12: 0] = CKRFC-2-12; |
assign w_ckREFRst[16:13] = 4'h0; |
assign w_ckREFIn[(CKRBITS-1): 0] = CKREFI4-5*CKRFC-2-10; |
assign w_ckREFIn[ 16:(CKRBITS)] = 0; |
assign w_ckREFRst = CKRFC-2-12; |
|
always @(posedge i_clk) |
if (reset_override) |
540,7 → 541,7
// writing? |
// |
// |
reg [`BUSNOW:0] bus_active, bus_read, bus_new; |
reg [`BUSNOW:0] bus_active, bus_read, bus_new, bus_ack; |
reg [1:0] bus_subaddr [`BUSNOW:0]; |
initial bus_active = 0; |
always @(posedge i_clk) |
549,6 → 550,8
bus_read[`BUSNOW:0] <= { bus_read[(`BUSNOW-1):0], 1'b0 }; // Drive the d-bus? |
// Is this a new command? i.e., the start of a transaction? |
bus_new[`BUSNOW:0] <= { bus_new[(`BUSNOW-1):0], 1'b0 }; |
// Will this position on the bus get a wishbone acknowledgement? |
bus_ack[`BUSNOW:0] <= { bus_ack[(`BUSNOW-1):0], 1'b0 }; |
//bus_mask[8:0] <= { bus_mask[7:0], 1'b1 }; // Write this value? |
bus_subaddr[8] <= bus_subaddr[7]; |
bus_subaddr[7] <= bus_subaddr[6]; |
559,21 → 562,35
bus_subaddr[2] <= bus_subaddr[1]; |
bus_subaddr[1] <= bus_subaddr[0]; |
bus_subaddr[0] <= 2'h3; |
|
bus_ack[5] <= (bus_ack[4])&& |
((bus_subaddr[5] != bus_subaddr[4]) |
||(bus_new[4])); |
if (w_this_rw_move) |
begin |
bus_active[3:0]<= 4'hf; // Once per clock |
bus_read[3:0] <= 4'hf; // These will be reads |
bus_subaddr[3] <= 2'h0; |
bus_subaddr[2] <= 2'h1; |
bus_subaddr[1] <= 2'h2; |
bus_new[{ 2'b0, rw_sub }] <= 1'b1; |
bus_ack[{ 2'b0, rw_sub }] <= 1'b1; |
|
bus_read[3:0] <= (rw_we)? 4'h0:4'hf; |
end else if ((s_pending)&&(!pipe_stall)) |
begin |
if (bus_subaddr[3] == s_sub) |
bus_ack[4] <= 1'b1; |
if (bus_subaddr[2] == s_sub) |
bus_ack[3] <= 1'b1; |
if (bus_subaddr[1] == s_sub) |
bus_ack[2] <= 1'b1; |
end |
end |
|
// Need to set o_wb_dqs high one clock prior to any read. |
always @(posedge i_clk) |
drive_dqs <= (~bus_read[`BUSREG])&&(|bus_active[`BUSREG]); |
drive_dqs <= (|bus_active[`BUSREG:(`BUSREG-1)]) |
&&(~(|bus_read[`BUSREG:(`BUSREG-1)])); |
|
// |
// |
788,8 → 805,8
cmd <= { `DDR_NOOP, rw_cmd[(`DDR_WEBIT-1):0] }; |
end |
|
`define LGFIFOLN 4 |
`define FIFOLEN 16 |
`define LGFIFOLN 3 |
`define FIFOLEN 8 |
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)]; |
798,30 → 815,24
|
// The bus R/W FIFO |
wire w_bus_fifo_read_next_transaction; |
assign w_bus_fifo_read_next_transaction = |
(bus_fifo_sub[bus_fifo_tail]==bus_subaddr[`BUSREG]) |
&&(bus_fifo_tail != bus_fifo_head) |
&&(bus_active[`BUSREG]) |
&&(bus_new[`BUSREG] == bus_fifo_new[bus_fifo_tail]); |
assign w_bus_fifo_read_next_transaction = (bus_ack[`BUSREG]); |
always @(posedge i_clk) |
begin |
pre_ack <= 1'b0; |
o_ddr_dm <= 1'b0; |
if ((i_reset)||(reset_override)) |
if (reset_override) |
begin |
bus_fifo_head <= 4'h0; |
bus_fifo_tail <= 4'h0; |
bus_fifo_head <= {(`LGFIFOLN){1'b0}}; |
bus_fifo_tail <= {(`LGFIFOLN){1'b0}}; |
o_ddr_dm <= 1'b0; |
end else begin |
if |
//((w_this_rw_move)||((s_pending)&&(s_match)&&(!pipe_stall))) |
((s_pending)&&(!pipe_stall)) |
bus_fifo_head <= bus_fifo_head + 4'h1; |
if ((s_pending)&&(!pipe_stall)) |
bus_fifo_head <= bus_fifo_head + 1'b1; |
|
o_ddr_dm <= (bus_active[`BUSREG])&&(!bus_read[`BUSREG]); |
if (w_bus_fifo_read_next_transaction) |
begin |
bus_fifo_tail <= bus_fifo_tail + 4'h1; |
bus_fifo_tail <= bus_fifo_tail + 1'b1; |
pre_ack <= 1'b1; |
o_ddr_dm <= 1'b0; |
end |
829,6 → 840,23
bus_fifo_data[bus_fifo_head] <= s_data; |
bus_fifo_sub[bus_fifo_head] <= s_sub; |
bus_fifo_new[bus_fifo_head] <= w_this_rw_move; |
|
// |
// if ((s_pending)&&(!pipe_stall)&&(!nxt_valid)) |
// nxt_fifo_data <= s_data; |
// nxt_fifo_sub <= s_sub; |
// nxt_fifo_new <= w_this_rw_move; |
// nxt_valid <= 1'b1; |
// bus_fifo_head <= bus_fifo_head+1; |
// bus_fifo_tail <= bus_fifo_tail+1; |
// else if (w_bus_fifo_read_next_transaction) |
// nxt_fifo_data <= bus_fifo_data[bus_fifo_tail] |
// nxt_fifo_sub <= bus_fifo_data[bus_fifo_tail] |
// nxt_fifo_new <= bus_fifo_data[bus_fifo_tail] |
// nxt_valid <= (bus_fifo_tail+1 == bus_fifo_head); |
// |
// if ((!valid)||(w_bus_fifo_next_read_transaction)) |
// nxt_ <= bus_fifo_x |
end |
|
|
844,13 → 872,14
assign w_precharge_all = (cmd[`DDR_CSBIT:`DDR_WEBIT]==`DDR_PRECHARGE) |
&&(o_ddr_addr[10]); // 5 bits |
|
// Need to set o_wb_dqs high one clock prior to any read. |
// As per spec, ODT = 0 during reads |
assign o_ddr_bus_oe = ~bus_read[`BUSNOW]; |
assign o_ddr_bus_oe = drive_dqs; // ~bus_read[`BUSNOW]; |
|
// ODT must be in high impedence while reset_n=0, then it can be set |
// to low or high. |
assign o_ddr_odt = o_ddr_bus_oe; |
// to low or high. As per spec, ODT = 0 during reads |
always @(posedge i_clk) |
o_ddr_odt <= (bus_active[`BUSREG-3])&&(!bus_read[`BUSREG-3]) |
||(bus_active[`BUSREG-4])&&(!bus_read[`BUSREG-4]) |
||((w_this_rw_move)&&(rw_we)); |
|
always @(posedge i_clk) |
o_wb_ack <= pre_ack; |
/trunk/doc/spec.pdf
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/doc/src/spec.tex
74,7 → 74,7
with this program. If not, see \texttt{http://www.gnu.org/licenses/} for a copy. |
\end{license} |
\begin{revisionhistory} |
0.0 & 6/20/2016 & D. Gisselquist & Initial Version\\\hline |
0.0 & 8/02/2016 & D. Gisselquist & (Pre-release) Initial Version\\\hline |
\end{revisionhistory} |
% Revision History |
% Table of Contents, named Contents |
142,6 → 142,11
|
% This section describes the architecture of the block. A block level diagram |
% should be included describing the top level of the design. |
\section{Data Structures} |
There are two basic data structures within the core: the bank data structures, |
and the bus data structure(s). The first keeps track of the persistent state |
of each bank, while the second keeps track of I/O transactions that have been |
initiated but not completed. |
|
\section{Strategies} |
\subsection{Bank} |
227,13 → 232,14
\end{wishboneds} |
\caption{Wishbone Datasheet}\label{tbl:wishbone} |
\end{center}\end{table} |
is required by the wishbone specification, and so |
it is included here. The big thing to notice is that all accesses to the |
DDR3 SDRAM memory are via 32--bit reads and writes to this interface. You may |
also wish to note that the scope supports pipeline reading and writing, to |
speed up reading the results out. As a result, the memory interface speed |
should approach one transfer per clock once the pipeline is loaded, although |
there will be delays loading the pipeline. |
is required by the wishbone specification, and so it is included here. The big |
thing to notice is that all accesses to the DDR3 SDRAM memory are via 32--bit |
reads and writes to this interface. You may also wish to note that the memory |
interface supports pipeline reading and writing, to speed up any transfers. As |
a result, the memory interface speed should approach one transfer per clock |
once the pipeline is loaded, although there will be delays loading the pipeline. |
Other than refresh cycles, once the pipeline is loaded it will continue its |
transfer rate at one cycle per clock for as long as it is fed at that speed. |
|
Further, the Wishbone specification this core communicates with has been |
simplified in this manner: The {\tt STB\_I} signal has been constrained so that |
/trunk/Makefile
37,7 → 37,7
################################################################################ |
## |
## |
all: rtl bench test |
all: rtl bench |
|
.PHONY: doc |
doc: |
48,9 → 48,14
cd rtl; $(MAKE) --no-print-directory |
|
.PHONY: bench |
bench: |
cd bench/cpp; $(MAKE) --no-print-directory wbddr3_tb |
bench: rtl |
cd bench/cpp; $(MAKE) --no-print-directory ddrsdram_tb |
|
.PHONY: test |
test: |
test: rtl bench |
cd bench/cpp; $(MAKE) --no-print-directory test |
|
.PHONY: clean |
clean: |
cd rtl; $(MAKE) --no-print-directory clean |
cd bench/cpp; $(MAKE) --no-print-directory clean |