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 12 to Rev 13
    Reverse comparison

Rev 12 → Rev 13

/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;
/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
/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;
}
 
/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
 
/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;
/doc/spec.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/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
/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

powered by: WebSVN 2.1.0

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