dfii: new design
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 23 Feb 2012 20:21:07 +0000 (21:21 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 23 Feb 2012 20:21:07 +0000 (21:21 +0100)
milkymist/dfii/__init__.py
software/bios/ddrinit.c
software/bios/ddrinit.h
software/bios/main.c
software/include/hw/dfii.h

index c8dfbbe81d5c7e84677eff4ed346d818f3feed3c..d50bc9344afd6353255b8ede11d5ddbbd002e319 100644 (file)
@@ -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()
index 6e18e16bae6108cc75db991702d6d673b32b98d1..39cd448c712ad17d66e8123d934679a63bea29fa 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 
 #include <hw/dfii.h>
 
@@ -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 <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)
 {
        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;
 }
index 7ef4a215f8c4eba6153f0a8ba3866ac4c8533264..2c2a6771a5dc0db233657e6009a47ec2641524fb 100644 (file)
@@ -19,5 +19,7 @@
 #define __DDRINIT_H
 
 int ddrinit(void);
+void ddrrd(char *startaddr);
+void ddrwr(char *startaddr);
 
 #endif /* __DDRINIT_H */
index f465126f26ee912a3943185efea6a85230d552c7..bc3c8cd6fc70caf06508e05377c3bfbce8c5041c 100644 (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, "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");
index 045e25aede4f70d6d2d260968000fc709e9085a8..fc13090cf2e7f9fec429ad80b6b2d02b5e3cbad6 100644 (file)
 #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 */