software/bios/sdram: allow setting CLK/CMD delay from user design and configure it...
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 27 Feb 2020 11:25:37 +0000 (12:25 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 27 Feb 2020 11:26:27 +0000 (12:26 +0100)
Setting a manual delay on CLK/CMD vs DQ/DQS is required on some configuration to center the write leveling window:

Before (delay = 0 taps):
Write leveling:
m0: |11000000000000011111111111| delay: 15
m1: |00000000000000111111111111| delay: 14
m2: |11110000000000000111111111| delay: 17
m3: |11110000000000000011111111| delay: 18
m4: |11111111110000000000000111| delay: 00
m5: |11111111110000000000000111| delay: 00
m6: |11111111111000000000000001| delay: 00
m7: |11111111111000000000000011| delay: 00

After (delay = 12 taps):
Write leveling:
m0: |11111111111111000000000000| delay: 00
m1: |11111111111100000000000001| delay: 00
m2: |00011111111111110000000000| delay: 03
m3: |00011111111111110000000000| delay: 03
m4: |00000000111111111111110000| delay: 08
m5: |00000000111111111111110000| delay: 08
m6: |00000000001111111111111000| delay: 10
m7: |00000000001111111111111000| delay: 10

litex/soc/software/bios/sdram.c

index 866e8a025e9a0140e21d6c793cfc32373219644b..58e7b16ddd3eb182fe2157972b4a1b03ca66058a 100644 (file)
@@ -257,6 +257,23 @@ void sdrwr(char *startaddr)
 #define NBMODULES DFII_PIX_DATA_BYTES/2
 #endif
 
+#ifdef DDRPHY_CMD_DELAY
+static void ddrphy_cdly(unsigned int delay) {
+#if CSR_DDRPHY_EN_VTC_ADDR
+       ddrphy_en_vtc_write(0);
+#endif
+       ddrphy_cdly_rst_write(1);
+       while (delay > 0) {
+               ddrphy_cdly_inc_write(1);
+               cdelay(1000);
+               delay--;
+       }
+#if CSR_DDRPHY_EN_VTC_ADDR
+       ddrphy_en_vtc_write(1);
+#endif
+}
+#endif
+
 #ifdef CSR_DDRPHY_WLEVEL_EN_ADDR
 
 void sdrwlon(void)
@@ -975,6 +992,10 @@ int sdrinit(void)
 #ifdef CSR_DDRPHY_BASE
 #if CSR_DDRPHY_EN_VTC_ADDR
        ddrphy_en_vtc_write(0);
+#endif
+#ifdef DDRPHY_CMD_DELAY
+       printf("Setting clk/cmd delay to %d taps\n", DDRPHY_CMD_DELAY);
+       ddrphy_cdly(DDRPHY_CMD_DELAY);
 #endif
        sdrlevel();
 #if CSR_DDRPHY_EN_VTC_ADDR