dfii: new design

This commit is contained in:
Sebastien Bourdeauducq 2012-02-23 21:21:07 +01:00
parent b3ca952a39
commit 92ac69bae3
5 changed files with 176 additions and 117 deletions

View file

@ -3,26 +3,53 @@ from migen.bus import dfi
from migen.bank.description import * from migen.bank.description import *
from migen.bank import csrgen from migen.bank import csrgen
def _data_en(trigger, output, delay, duration): class PhaseInjector:
dcounter = Signal(BV(4)) def __init__(self, phase):
dce = Signal() self.phase = phase
return [
If(trigger, self._cs = Field("cs", 1, WRITE_ONLY, READ_ONLY)
dcounter.eq(delay), self._we = Field("we", 1, WRITE_ONLY, READ_ONLY)
dce.eq(1) self._cas = Field("cas", 1, WRITE_ONLY, READ_ONLY)
).Elif(dce, self._ras = Field("ras", 1, WRITE_ONLY, READ_ONLY)
dcounter.eq(dcounter - 1), self._wren = Field("wren", 1, WRITE_ONLY, READ_ONLY)
If(dcounter == 0, self._rden = Field("rden", 1, WRITE_ONLY, READ_ONLY)
If(~output, self._command = RegisterFields("command",
output.eq(1), [self._cs, self._we, self._cas, self._ras, self._wren, self._rden])
dcounter.eq(duration)
).Else( self._address = RegisterField("address", self.phase.address.bv.width)
output.eq(0), self._baddress = RegisterField("baddress", self.phase.bank.bv.width)
dce.eq(0)
) self._wrdata = RegisterField("wrdata", self.phase.wrdata.bv.width)
) self._rddata = RegisterField("rddata", self.phase.rddata.bv.width, READ_ONLY, WRITE_ONLY)
)
] def get_registers(self):
return [self._command,
self._address, self._baddress,
self._wrdata, self._rddata]
def get_fragment(self):
comb = [
If(self._command.re,
self.phase.cs_n.eq(~self._cs.r),
self.phase.we_n.eq(~self._we.r),
self.phase.cas_n.eq(~self._cas.r),
self.phase.ras_n.eq(~self._ras.r)
).Else(
self.phase.cs_n.eq(1),
self.phase.we_n.eq(1),
self.phase.cas_n.eq(1),
self.phase.ras_n.eq(1)
),
self.phase.address.eq(self._address.field.r),
self.phase.bank.eq(self._baddress.field.r),
self.phase.wrdata.eq(self._wrdata.field.r)
]
sync = [
self.phase.wrdata_en.eq(self._command.re & self._wren.r),
self.phase.rddata_en.eq(self._command.re & self._rden.r),
If(self.phase.rddata_valid, self._rddata.field.w.eq(self.phase.rddata))
]
return Fragment(comb, sync)
class DFIInjector: class DFIInjector:
def __init__(self, csr_address, a, ba, d, nphases=1): def __init__(self, csr_address, a, ba, d, nphases=1):
@ -34,84 +61,19 @@ class DFIInjector:
self._cke = Field("cke") self._cke = Field("cke")
self._control = RegisterFields("control", [self._sel, self._cke]) self._control = RegisterFields("control", [self._sel, self._cke])
self._cs = Field("cs", 1, WRITE_ONLY, READ_ONLY) self._phase_injectors = [PhaseInjector(phase) for phase in self._int.phases]
self._we = Field("we", 1, WRITE_ONLY, READ_ONLY)
self._cas = Field("cas", 1, WRITE_ONLY, READ_ONLY)
self._ras = Field("ras", 1, WRITE_ONLY, READ_ONLY)
self._rddata = Field("rddata", 1, WRITE_ONLY, READ_ONLY)
self._wrdata = Field("wrdata", 1, WRITE_ONLY, READ_ONLY)
self._command = RegisterFields("command",
[self._cs, self._we, self._cas, self._ras, self._rddata, self._wrdata])
self._address = RegisterField("address", a) registers = sum([pi.get_registers() for pi in self._phase_injectors], [self._control])
self._baddress = RegisterField("baddress", ba) self.bank = csrgen.Bank(registers, address=csr_address)
self._rddelay = RegisterField("rddelay", 4, reset=5)
self._rdduration = RegisterField("rdduration", 3, reset=0)
self._wrdelay = RegisterField("wrdelay", 4, reset=3)
self._wrduration = RegisterField("wrduration", 3, reset=0)
self.bank = csrgen.Bank([
self._control, self._command,
self._address, self._baddress,
self._rddelay, self._rdduration,
self._wrdelay, self._wrduration
], address=csr_address)
def get_fragment(self): def get_fragment(self):
comb = []
sync = []
# mux
connect_int = dfi.interconnect_stmts(self._int, self.master) connect_int = dfi.interconnect_stmts(self._int, self.master)
connect_slave = dfi.interconnect_stmts(self.slave, self.master) connect_slave = dfi.interconnect_stmts(self.slave, self.master)
comb.append(If(self._sel.r, *connect_slave).Else(*connect_int)) comb = [
If(self._sel.r, *connect_slave).Else(*connect_int)
# phases
rddata_en = Signal()
wrdata_en = Signal()
for phase in self._int.phases:
comb += [
phase.cke.eq(self._cke.r),
phase.rddata_en.eq(rddata_en),
phase.wrdata_en.eq(wrdata_en)
]
cmdphase = self._int.phases[0]
for phase in self._int.phases[1:]:
comb += [
phase.cs_n.eq(1),
phase.we_n.eq(1),
phase.cas_n.eq(1),
phase.ras_n.eq(1)
]
# commands
comb += [
If(self._command.re,
cmdphase.cs_n.eq(~self._cs.r),
cmdphase.we_n.eq(~self._we.r),
cmdphase.cas_n.eq(~self._cas.r),
cmdphase.ras_n.eq(~self._ras.r)
).Else(
cmdphase.cs_n.eq(1),
cmdphase.we_n.eq(1),
cmdphase.cas_n.eq(1),
cmdphase.ras_n.eq(1)
)
] ]
comb += [phase.cke.eq(self._cke.r) for phase in self._int.phases]
# addresses return Fragment(comb) \
comb += [ + sum([pi.get_fragment() for pi in self._phase_injectors], Fragment()) \
cmdphase.address.eq(self._address.field.r), + self.bank.get_fragment()
cmdphase.bank.eq(self._baddress.field.r)
]
# data enables
sync += _data_en(self._command.re & self._rddata.r,
rddata_en,
self._rddelay.field.r, self._rdduration.field.r)
sync += _data_en(self._command.re & self._wrdata.r,
wrdata_en,
self._wrdelay.field.r, self._wrduration.field.r)
return Fragment(comb, sync) + self.bank.get_fragment()

View file

@ -16,6 +16,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <hw/dfii.h> #include <hw/dfii.h>
@ -31,8 +32,10 @@ static void cdelay(int i)
static void setaddr(int a) static void setaddr(int a)
{ {
CSR_DFII_AH = (a & 0x1fe0) >> 5; CSR_DFII_AH_P0 = (a & 0x1fe0) >> 5;
CSR_DFII_AL = a & 0x001f; CSR_DFII_AL_P0 = a & 0x001f;
CSR_DFII_AH_P1 = (a & 0x1fe0) >> 5;
CSR_DFII_AL_P1 = a & 0x001f;
} }
static void init_sequence(void) static void init_sequence(void)
@ -43,46 +46,105 @@ static void init_sequence(void)
/* Bring CKE high */ /* Bring CKE high */
setaddr(0x0000); setaddr(0x0000);
CSR_DFII_BA = 0; CSR_DFII_BA_P0 = 0;
CSR_DFII_CONTROL = DFII_CONTROL_CKE; CSR_DFII_CONTROL = DFII_CONTROL_CKE;
/* Precharge All */ /* Precharge All */
setaddr(0x0400); setaddr(0x0400);
CSR_DFII_COMMAND = DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS; CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
/* Load Extended Mode Register */ /* Load Extended Mode Register */
CSR_DFII_BA = 1; CSR_DFII_BA_P0 = 1;
setaddr(0x0000); setaddr(0x0000);
CSR_DFII_COMMAND = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS; CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
CSR_DFII_BA = 0; CSR_DFII_BA_P0 = 0;
/* Load Mode Register */ /* Load Mode Register */
setaddr(0x0132); /* Reset DLL, CL=3, BL=4 */ setaddr(0x0132); /* Reset DLL, CL=3, BL=4 */
CSR_DFII_COMMAND = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS; CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
cdelay(200); cdelay(200);
/* Precharge All */ /* Precharge All */
setaddr(0x0400); setaddr(0x0400);
CSR_DFII_COMMAND = DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS; CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
/* 2x Auto Refresh */ /* 2x Auto Refresh */
for(i=0;i<2;i++) { for(i=0;i<2;i++) {
setaddr(0); setaddr(0);
CSR_DFII_COMMAND = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS; CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS;
cdelay(4); cdelay(4);
} }
/* Load Mode Register */ /* Load Mode Register */
setaddr(0x0032); /* CL=3, BL=4 */ setaddr(0x0032); /* CL=3, BL=4 */
CSR_DFII_COMMAND = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS; CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS;
cdelay(200); cdelay(200);
} }
void ddrrd(char *startaddr)
{
char *c;
unsigned int addr;
int i;
if(*startaddr == 0) {
printf("ddrrd <address>\n");
return;
}
addr = strtoul(startaddr, &c, 0);
if(*c != 0) {
printf("incorrect address\n");
return;
}
setaddr(addr);
CSR_DFII_BA_P0 = 0;
CSR_DFII_COMMAND_P0 = DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA;
cdelay(15);
for(i=0;i<8;i++)
printf("%08x ", MMPTR(0xe0000834+4*i));
for(i=0;i<8;i++)
printf("%08x ", MMPTR(0xe0000884+4*i));
printf("\n");
}
void ddrwr(char *startaddr)
{
char *c;
unsigned int addr;
int i;
if(*startaddr == 0) {
printf("ddrrd <address>\n");
return;
}
addr = strtoul(startaddr, &c, 0);
if(*c != 0) {
printf("incorrect address\n");
return;
}
for(i=0;i<8;i++) {
MMPTR(0xe0000814+4*i) = i;
MMPTR(0xe0000864+4*i) = i;
}
setaddr(addr);
CSR_DFII_BA_P1 = 0;
CSR_DFII_COMMAND_P1 = DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA;
}
int ddrinit(void) int ddrinit(void)
{ {
printf("Initializing DDR SDRAM...\n"); printf("Initializing DDR SDRAM...\n");
init_sequence(); init_sequence();
setaddr(0x0000);
CSR_DFII_BA_P0 = 0;
CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CS;
cdelay(15);
return 1; return 1;
} }

View file

@ -19,5 +19,7 @@
#define __DDRINIT_H #define __DDRINIT_H
int ddrinit(void); int ddrinit(void);
void ddrrd(char *startaddr);
void ddrwr(char *startaddr);
#endif /* __DDRINIT_H */ #endif /* __DDRINIT_H */

View file

@ -353,6 +353,8 @@ static void do_command(char *c)
else if(strcmp(token, "wcsr") == 0) wcsr(get_token(&c), get_token(&c)); else if(strcmp(token, "wcsr") == 0) wcsr(get_token(&c), get_token(&c));
else if(strcmp(token, "ddrinit") == 0) ddrinit(); else if(strcmp(token, "ddrinit") == 0) ddrinit();
else if(strcmp(token, "ddrrd") == 0) ddrrd(get_token(&c));
else if(strcmp(token, "ddrwr") == 0) ddrwr(get_token(&c));
else if(strcmp(token, "") != 0) else if(strcmp(token, "") != 0)
printf("Command not found\n"); printf("Command not found\n");

View file

@ -25,22 +25,53 @@
#define DFII_CONTROL_SEL (0x01) #define DFII_CONTROL_SEL (0x01)
#define DFII_CONTROL_CKE (0x02) #define DFII_CONTROL_CKE (0x02)
#define CSR_DFII_COMMAND MMPTR(0xe0001004) #define CSR_DFII_COMMAND_P0 MMPTR(0xe0000804)
#define CSR_DFII_AH_P0 MMPTR(0xe0000808)
#define CSR_DFII_AL_P0 MMPTR(0xe000080C)
#define CSR_DFII_BA_P0 MMPTR(0xe0000810)
#define CSR_DFII_WD0_P0 MMPTR(0xe0000814)
#define CSR_DFII_WD1_P0 MMPTR(0xe0000818)
#define CSR_DFII_WD2_P0 MMPTR(0xe000081C)
#define CSR_DFII_WD3_P0 MMPTR(0xe0000820)
#define CSR_DFII_WD4_P0 MMPTR(0xe0000824)
#define CSR_DFII_WD5_P0 MMPTR(0xe0000828)
#define CSR_DFII_WD6_P0 MMPTR(0xe000082C)
#define CSR_DFII_WD7_P0 MMPTR(0xe0000830)
#define CSR_DFII_RD0_P0 MMPTR(0xe0000834)
#define CSR_DFII_RD1_P0 MMPTR(0xe0000838)
#define CSR_DFII_RD2_P0 MMPTR(0xe000083C)
#define CSR_DFII_RD3_P0 MMPTR(0xe0000840)
#define CSR_DFII_RD4_P0 MMPTR(0xe0000844)
#define CSR_DFII_RD5_P0 MMPTR(0xe0000848)
#define CSR_DFII_RD6_P0 MMPTR(0xe000084C)
#define CSR_DFII_RD7_P0 MMPTR(0xe0000850)
#define CSR_DFII_COMMAND_P1 MMPTR(0xe0000854)
#define CSR_DFII_AH_P1 MMPTR(0xe0000858)
#define CSR_DFII_AL_P1 MMPTR(0xe000085C)
#define CSR_DFII_BA_P1 MMPTR(0xe0000860)
#define CSR_DFII_WD0_P1 MMPTR(0xe0000864)
#define CSR_DFII_WD1_P1 MMPTR(0xe0000868)
#define CSR_DFII_WD2_P1 MMPTR(0xe000086C)
#define CSR_DFII_WD3_P1 MMPTR(0xe0000870)
#define CSR_DFII_WD4_P1 MMPTR(0xe0000874)
#define CSR_DFII_WD5_P1 MMPTR(0xe0000878)
#define CSR_DFII_WD6_P1 MMPTR(0xe000087C)
#define CSR_DFII_WD7_P1 MMPTR(0xe0000880)
#define CSR_DFII_RD0_P1 MMPTR(0xe0000884)
#define CSR_DFII_RD1_P1 MMPTR(0xe0000888)
#define CSR_DFII_RD2_P1 MMPTR(0xe000088C)
#define CSR_DFII_RD3_P1 MMPTR(0xe0000890)
#define CSR_DFII_RD4_P1 MMPTR(0xe0000894)
#define CSR_DFII_RD5_P1 MMPTR(0xe0000898)
#define CSR_DFII_RD6_P1 MMPTR(0xe000089C)
#define CSR_DFII_RD7_P1 MMPTR(0xe00008a0)
#define DFII_COMMAND_CS (0x01) #define DFII_COMMAND_CS (0x01)
#define DFII_COMMAND_WE (0x02) #define DFII_COMMAND_WE (0x02)
#define DFII_COMMAND_CAS (0x04) #define DFII_COMMAND_CAS (0x04)
#define DFII_COMMAND_RAS (0x08) #define DFII_COMMAND_RAS (0x08)
#define DFII_COMMAND_RDDATA (0x10) #define DFII_COMMAND_WRDATA (0x10)
#define DFII_COMMAND_WRDATA (0x20) #define DFII_COMMAND_RDDATA (0x20)
#define CSR_DFII_AH MMPTR(0xe0000808)
#define CSR_DFII_AL MMPTR(0xe000080C)
#define CSR_DFII_BA MMPTR(0xe0000810)
#define CSR_DFII_RDDELAY MMPTR(0xe0000814)
#define CSR_DFII_RDDURATION MMPTR(0xe0000818)
#define CSR_DFII_WRDELAY MMPTR(0xe000081C)
#define CSR_DFII_WRDURATION MMPTR(0xe0000820)
#endif /* __HW_DFII_H */ #endif /* __HW_DFII_H */