From: Sebastien Bourdeauducq Date: Thu, 23 Feb 2012 20:21:07 +0000 (+0100) Subject: dfii: new design X-Git-Tag: 24jan2021_ls180~3221 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=92ac69bae34d543fc842309b414a58a1594174b1;p=litex.git dfii: new design --- diff --git a/milkymist/dfii/__init__.py b/milkymist/dfii/__init__.py index c8dfbbe8..d50bc934 100644 --- a/milkymist/dfii/__init__.py +++ b/milkymist/dfii/__init__.py @@ -3,26 +3,53 @@ from migen.bus import dfi from migen.bank.description import * from migen.bank import csrgen -def _data_en(trigger, output, delay, duration): - dcounter = Signal(BV(4)) - dce = Signal() - return [ - If(trigger, - dcounter.eq(delay), - dce.eq(1) - ).Elif(dce, - dcounter.eq(dcounter - 1), - If(dcounter == 0, - If(~output, - output.eq(1), - dcounter.eq(duration) - ).Else( - output.eq(0), - dce.eq(0) - ) - ) - ) - ] +class PhaseInjector: + def __init__(self, phase): + self.phase = phase + + self._cs = Field("cs", 1, WRITE_ONLY, READ_ONLY) + 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._wren = Field("wren", 1, WRITE_ONLY, READ_ONLY) + self._rden = Field("rden", 1, WRITE_ONLY, READ_ONLY) + self._command = RegisterFields("command", + [self._cs, self._we, self._cas, self._ras, self._wren, self._rden]) + + self._address = RegisterField("address", self.phase.address.bv.width) + self._baddress = RegisterField("baddress", self.phase.bank.bv.width) + + 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: def __init__(self, csr_address, a, ba, d, nphases=1): @@ -34,84 +61,19 @@ class DFIInjector: self._cke = Field("cke") self._control = RegisterFields("control", [self._sel, self._cke]) - self._cs = Field("cs", 1, WRITE_ONLY, READ_ONLY) - 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) - self._baddress = RegisterField("baddress", ba) + self._phase_injectors = [PhaseInjector(phase) for phase in self._int.phases] - 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) + registers = sum([pi.get_registers() for pi in self._phase_injectors], [self._control]) + self.bank = csrgen.Bank(registers, address=csr_address) def get_fragment(self): - comb = [] - sync = [] - - # mux connect_int = dfi.interconnect_stmts(self._int, self.master) connect_slave = dfi.interconnect_stmts(self.slave, self.master) - comb.append(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 = [ + If(self._sel.r, *connect_slave).Else(*connect_int) ] + comb += [phase.cke.eq(self._cke.r) for phase in self._int.phases] - # addresses - comb += [ - cmdphase.address.eq(self._address.field.r), - 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() + return Fragment(comb) \ + + sum([pi.get_fragment() for pi in self._phase_injectors], Fragment()) \ + + self.bank.get_fragment() diff --git a/software/bios/ddrinit.c b/software/bios/ddrinit.c index 6e18e16b..39cd448c 100644 --- a/software/bios/ddrinit.c +++ b/software/bios/ddrinit.c @@ -16,6 +16,7 @@ */ #include +#include #include @@ -31,8 +32,10 @@ static void cdelay(int i) static void setaddr(int a) { - CSR_DFII_AH = (a & 0x1fe0) >> 5; - CSR_DFII_AL = a & 0x001f; + CSR_DFII_AH_P0 = (a & 0x1fe0) >> 5; + CSR_DFII_AL_P0 = a & 0x001f; + CSR_DFII_AH_P1 = (a & 0x1fe0) >> 5; + CSR_DFII_AL_P1 = a & 0x001f; } static void init_sequence(void) @@ -43,46 +46,105 @@ static void init_sequence(void) /* Bring CKE high */ setaddr(0x0000); - CSR_DFII_BA = 0; + CSR_DFII_BA_P0 = 0; CSR_DFII_CONTROL = DFII_CONTROL_CKE; /* Precharge All */ 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 */ - CSR_DFII_BA = 1; + CSR_DFII_BA_P0 = 1; setaddr(0x0000); - CSR_DFII_COMMAND = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS; - CSR_DFII_BA = 0; + CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS; + CSR_DFII_BA_P0 = 0; /* Load Mode Register */ 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); /* Precharge All */ 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 */ for(i=0;i<2;i++) { 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); } /* Load Mode Register */ 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); } +void ddrrd(char *startaddr) +{ + char *c; + unsigned int addr; + int i; + + if(*startaddr == 0) { + printf("ddrrd
\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
\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) { printf("Initializing DDR SDRAM...\n"); init_sequence(); + setaddr(0x0000); + CSR_DFII_BA_P0 = 0; + CSR_DFII_COMMAND_P0 = DFII_COMMAND_RAS|DFII_COMMAND_CS; + cdelay(15); + return 1; } diff --git a/software/bios/ddrinit.h b/software/bios/ddrinit.h index 7ef4a215..2c2a6771 100644 --- a/software/bios/ddrinit.h +++ b/software/bios/ddrinit.h @@ -19,5 +19,7 @@ #define __DDRINIT_H int ddrinit(void); +void ddrrd(char *startaddr); +void ddrwr(char *startaddr); #endif /* __DDRINIT_H */ diff --git a/software/bios/main.c b/software/bios/main.c index f465126f..bc3c8cd6 100644 --- a/software/bios/main.c +++ b/software/bios/main.c @@ -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, "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) printf("Command not found\n"); diff --git a/software/include/hw/dfii.h b/software/include/hw/dfii.h index 045e25ae..fc13090c 100644 --- a/software/include/hw/dfii.h +++ b/software/include/hw/dfii.h @@ -25,22 +25,53 @@ #define DFII_CONTROL_SEL (0x01) #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_WE (0x02) #define DFII_COMMAND_CAS (0x04) #define DFII_COMMAND_RAS (0x08) -#define DFII_COMMAND_RDDATA (0x10) -#define DFII_COMMAND_WRDATA (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) +#define DFII_COMMAND_WRDATA (0x10) +#define DFII_COMMAND_RDDATA (0x20) #endif /* __HW_DFII_H */