This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Thank you for all your support.
During debugging unstable DDR3 memory access, I found out "unexpected write access timing" as attached. It seems that DQ and DQS timing is shifted by 45 degree, and I believe this should be right in the center. I was wondering if any of you could advise me how to fix this. The configuration is below. I appreciate this.
DSP: TMS320C6657CZH25
memory, Micron: MT41J128M16HA-125
8 banks open for interleaving
RZQ/2
RZQ/2
RZQ/7
CWL = 8
32-bit bus width
CAS = 11
14 row bits
8 bank SDRAM
Use DCE0# for all SDRAM accesses
1024-word page
Where were these signals measured? Do you see the same shift if the signal is measured at the vias next to the SOC?
Regards, Bill
Hi Bill
These signals are measured at the vias right next to the DDR memory pads.
Thank you
Matsuno
Hi Matsuno,
If they are measured at the via next to the DDR memory pads than the measurement includes the delay through the traces on the board. Are you trace lengths matched as defined in the DDR3 design requirements? What is the length of each trace and what layers are they routed on?
Regards, Bill
I have the same problem. The DQS strobes are NOT centered in the data bit window which is causing a marginal hold time condition. Our system is working with DDR3-1333 but with little timing margin. I was told that this is NOT programmable in the DSP and that I must have a layout problem. I do NOT have a layout problem and I have not been given an adequate explanation as to why the device operates this way.
Hi Bill
Thank you for your support.
The ones measured, DQS_P0, DQS_N0, and DQ5 have 37.154, 37.148, and 37.010 mm respectively in their length meeting the requirement( <0.25mm). They are all strip line (inner layer) . Any advice would be appreciated.
Thank you
matsuno
Hi Matsuno,
The response to your post may get delayed due to Christmas and New Year Holidays.
Kindly bear with us.
Thanks.
Hi Aditya
Thank you for your support.
Initialization routine is attached(ddr3.c). Basically this is from evaluation board sample code.
Thank you
matsuno
/*""FILE COMMENT""************************************************************** *** ModuleName : ddr3 *** Contents : Source File *** Note : for setting system PLL ******************************************************************************** *** COPYRIGHT(C) Myway Plus Corporation ******************************************************************************** ***""FILE COMMENT END""********************************************************/ /*""FILE INCLUDE""*************************************************************/ #include "ddr3_p.h" //#include "csl_emif4f.h" //#include "csl_bootcfgAux.h" /*""FILE INCLUDE END""*********************************************************/ /*""Function Define""**********************************************************/ INT32 DDR3_TestMemory_s32(void) { #if 0 UINT32 index_u32, value_u32; printf ( "DDR3 memory test... Started. \n" ); /* Write a pattern */ for (index_u32 = DDR3_TEST_START_ADDRESS; index_u32 < DDR3_TEST_END_ADDRESS; index_u32 += 4) { *(UINT32 *)index_u32 = index_u32; } /* Read and check the pattern */ for (index_u32 = DDR3_TEST_START_ADDRESS; index_u32 < DDR3_TEST_END_ADDRESS; index_u32 += 4) { value_u32 = *(UINT32 *)index_u32; if (value_u32 != index_u32) { printf ( "DDR3 memory test... Failed. \n" ); return -1; } } /* Write a pattern for complementary values */ for (index_u32 = DDR3_TEST_START_ADDRESS; index_u32 < DDR3_TEST_END_ADDRESS; index_u32 += 4) { *(UINT32 *)index_u32 = ~index_u32; } /* Read and check the pattern */ for (index_u32 = DDR3_TEST_START_ADDRESS; index_u32 < DDR3_TEST_END_ADDRESS; index_u32 += 4) { value_u32 = *(UINT32 *)index_u32; if (value_u32 != ~index_u32) { printf ( "DDR3 memory test... Failed. \n" ); return -1; } } #else volatile UINT32 *pWork = (UINT32 *)DDR3_TEST_START_ADDRESS; //point to start of DDR3 volatile UINT32 u32Tmp; BOOL bError = FALSE; printf ( "DDR3 memory test... Started. \n" ); while (pWork < (UINT32 *)DDR3_TEST_END_ADDRESS) { u32Tmp = ~(*pWork); *pWork = u32Tmp; if (u32Tmp != *pWork) { bError = TRUE; break; } pWork += 0x1; } if (bError == TRUE) { printf("DDR3 memory test... Failed. \n"); return -1; } #endif printf ( "DDR3 memory test... Passed. \n" ); return 0; } INT32 DDR3_Init_s32 (void) { INT32 i; printf("DDR3 Configuration... \n"); /*Unlock Boot Config*/ CSL_BootCfgUnlockKicker(); /* Wait for PLL to lock = min 500 ref clock cycles. With refclk = 100MHz, = 5000 ns = 5us */ for(i=0; i< 1000; i++) asm(" nop 5"); /***************** 3.2 DDR3 PLL Configuration ************/ /* Done before */ /**************** 3.0 Leveling Register Configuration ********************/ /* Using partial automatic leveling due to errata */ /**************** 3.3 Leveling register configuration ********************/ boot_cfg_regs->DDR3_CONFIG_REG[0] &= ~(0x007FE000U); // clear ctrl_slave_ratio field boot_cfg_regs->DDR3_CONFIG_REG[0] |= 0x00200000U; // set ctrl_slave_ratio to 0x100 boot_cfg_regs->DDR3_CONFIG_REG[12] |= 0x08000000U; // Set invert_clkout = 1 boot_cfg_regs->DDR3_CONFIG_REG[0] |= 0xFU; // set dll_lock_diff to 15 //From 4.2.1 Executing Partial Automatic Leveling -- Start boot_cfg_regs->DDR3_CONFIG_REG[23] |= 0x00000200U; //Set bit 9 = 1 to use forced ratio leveling for read DQS //From 4.2.1 Executing Partial Automatic Leveling -- End //Values with invertclkout = 1 /**************** 3.3 Partial Automatic Leveling ********************/ /*WRLVL_INIT_RATIO*/ boot_cfg_regs->DDR3_CONFIG_REG[2] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[3] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[4] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[5] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[6] = 0x5D; boot_cfg_regs->DDR3_CONFIG_REG[7] = 0x5C; boot_cfg_regs->DDR3_CONFIG_REG[8] = 0x51; boot_cfg_regs->DDR3_CONFIG_REG[9] = 0x48; boot_cfg_regs->DDR3_CONFIG_REG[10] = 0x00; /*GTLVL_INIT_RATIO*/ boot_cfg_regs->DDR3_CONFIG_REG[14] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[15] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[16] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[17] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[18] = 0xAD; boot_cfg_regs->DDR3_CONFIG_REG[19] = 0xAE; boot_cfg_regs->DDR3_CONFIG_REG[20] = 0x93; boot_cfg_regs->DDR3_CONFIG_REG[21] = 0x9D; boot_cfg_regs->DDR3_CONFIG_REG[22] = 0x00; //Do a PHY reset. Toggle DDR_PHY_CTRL_1 bit 15 0->1->0 DDR_Regs->DDR_PHY_CTRL_1 &= ~(0x00008000U); DDR_Regs->DDR_PHY_CTRL_1 |= (0x00008000U); DDR_Regs->DDR_PHY_CTRL_1 &= ~(0x00008000U); /***************** 3.4 Basic Controller and DRAM Configuration ************/ DDR_Regs->SDRAM_REF_CTRL = 0x0000515CU; // enable configuration DDR_Regs->SDRAM_TIM_1 = 0x1333780C; DDR_Regs->SDRAM_TIM_2 = 0x30717FE3U; DDR_Regs->SDRAM_TIM_3 = 0x559F86AFU; DDR_Regs->DDR_PHY_CTRL_1 = 0x0010010FU; DDR_Regs->ZQ_CONFIG = 0x70074c1fU; DDR_Regs->PWR_MGMT_CTRL = 0x0U; DDR_Regs->SDRAM_CONFIG = 0x62477AB2U; //Wait 600us for HW init to complete for(i=0; i< 600*200; i++) asm(" nop 5"); DDR_Regs->SDRAM_REF_CTRL = 0x0000144FU; //Refresh rate = (7.8*666MHz) /**************** 4.2.1 Executing Partial Automatic Leveling ********************/ DDR_Regs->RDWR_LVL_RMP_CTRL = 0x80000000; //enable full leveling DDR_Regs->RDWR_LVL_CTRL = 0x80000000; //Trigger full leveling - This ignores read DQS leveling result and uses ratio forced value //(0x34) instead //Wait for min 1048576 DDR clock cycles for leveling to complete = 1048576 * 1.5ns = 1572864ns = 1.57ms. //Actual time = ~10-15 ms for(i=0; i<15*200000; i++) asm(" nop 5"); i=0; while ((DDR_Regs->STATUS & 0x00000070U) && (i<0xf)) { i++; asm(" nop 5"); if (i>3000000){ break; } } // Lock the kicker mechanism CSL_BootCfgLockKicker(); if (i>3000000) { printf("write leveling is failed! \n"); return -1; } printf("DDR3 configuration is done! \n"); return 0; } INT32 DDR3_Init1_s32 (void) { INT32 i; UINT32 TEMP; printf("DDR3 Configuration... \n"); /*Unlock Boot Config*/ CSL_BootCfgUnlockKicker(); /* Wait for PLL to lock = min 500 ref clock cycles. With refclk = 100MHz, = 5000 ns = 5us */ for(i=0; i< 1000; i++) asm(" nop 5"); /***************** 3.2 DDR3 PLL Configuration ************/ /* Done before */ /**************** 3.0 Leveling Register Configuration ********************/ /* Using partial automatic leveling due to errata */ /**************** 3.3 Leveling register configuration ********************/ boot_cfg_regs->DDR3_CONFIG_REG[0] &= ~(0x007FE000U); // clear ctrl_slave_ratio field boot_cfg_regs->DDR3_CONFIG_REG[0] |= 0x00200000U; // set ctrl_slave_ratio to 0x100 boot_cfg_regs->DDR3_CONFIG_REG[12] |= 0x08000000U; // Set invert_clkout = 1 boot_cfg_regs->DDR3_CONFIG_REG[0] |= 0xFU; // set dll_lock_diff to 15 //From 4.2.1 Executing Partial Automatic Leveling -- Start boot_cfg_regs->DDR3_CONFIG_REG[23] |= 0x00000200U; //Set bit 9 = 1 to use forced ratio leveling for read DQS //From 4.2.1 Executing Partial Automatic Leveling -- End //Values with invertclkout = 1 /**************** 3.3 Partial Automatic Leveling ********************/ #if 0 /*WRLVL_INIT_RATIO*/ boot_cfg_regs->DDR3_CONFIG_REG[2] = 0x00U; boot_cfg_regs->DDR3_CONFIG_REG[3] = 0x00U; boot_cfg_regs->DDR3_CONFIG_REG[4] = 0x00U; boot_cfg_regs->DDR3_CONFIG_REG[5] = 0x00U; boot_cfg_regs->DDR3_CONFIG_REG[6] = 0x33U; boot_cfg_regs->DDR3_CONFIG_REG[7] = 0x3AU; boot_cfg_regs->DDR3_CONFIG_REG[8] = 0x2CU; boot_cfg_regs->DDR3_CONFIG_REG[9] = 0x2CU; boot_cfg_regs->DDR3_CONFIG_REG[10] = 0x21U; /*GTLVL_INIT_RATIO*/ boot_cfg_regs->DDR3_CONFIG_REG[14] = 0x00U; boot_cfg_regs->DDR3_CONFIG_REG[15] = 0x00U; boot_cfg_regs->DDR3_CONFIG_REG[16] = 0x00U; boot_cfg_regs->DDR3_CONFIG_REG[17] = 0x00U; boot_cfg_regs->DDR3_CONFIG_REG[18] = 0xB7U; boot_cfg_regs->DDR3_CONFIG_REG[19] = 0xB1U; boot_cfg_regs->DDR3_CONFIG_REG[20] = 0xA4U; boot_cfg_regs->DDR3_CONFIG_REG[21] = 0xA4U; boot_cfg_regs->DDR3_CONFIG_REG[22] = 0x98U; #else #if 0 /* for test haku */ /*WRLVL_INIT_RATIO*/ boot_cfg_regs->DDR3_CONFIG_REG[2] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[3] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[4] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[5] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[6] = 0x5C; boot_cfg_regs->DDR3_CONFIG_REG[7] = 0x5B; boot_cfg_regs->DDR3_CONFIG_REG[8] = 0x63; boot_cfg_regs->DDR3_CONFIG_REG[9] = 0x5A; boot_cfg_regs->DDR3_CONFIG_REG[10] = 0x00; /*GTLVL_INIT_RATIO*/ boot_cfg_regs->DDR3_CONFIG_REG[14] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[15] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[16] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[17] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[18] = 0xAC; boot_cfg_regs->DDR3_CONFIG_REG[19] = 0xAD; boot_cfg_regs->DDR3_CONFIG_REG[20] = 0xA5; boot_cfg_regs->DDR3_CONFIG_REG[21] = 0xAF; boot_cfg_regs->DDR3_CONFIG_REG[22] = 0x00; #endif /*WRLVL_INIT_RATIO*/ boot_cfg_regs->DDR3_CONFIG_REG[2] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[3] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[4] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[5] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[6] = 0x5D; boot_cfg_regs->DDR3_CONFIG_REG[7] = 0x5C; boot_cfg_regs->DDR3_CONFIG_REG[8] = 0x51; boot_cfg_regs->DDR3_CONFIG_REG[9] = 0x48; boot_cfg_regs->DDR3_CONFIG_REG[10] = 0x00; /*GTLVL_INIT_RATIO*/ boot_cfg_regs->DDR3_CONFIG_REG[14] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[15] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[16] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[17] = 0x00; boot_cfg_regs->DDR3_CONFIG_REG[18] = 0xAD; boot_cfg_regs->DDR3_CONFIG_REG[19] = 0xAE; boot_cfg_regs->DDR3_CONFIG_REG[20] = 0x93; boot_cfg_regs->DDR3_CONFIG_REG[21] = 0x9D; boot_cfg_regs->DDR3_CONFIG_REG[22] = 0x00; #endif //Do a PHY reset. Toggle DDR_PHY_CTRL_1 bit 15 0->1->0 DDR_Regs->DDR_PHY_CTRL_1 &= ~(0x00008000U); DDR_Regs->DDR_PHY_CTRL_1 |= (0x00008000U); DDR_Regs->DDR_PHY_CTRL_1 &= ~(0x00008000U); /***************** 3.4 Basic Controller and DRAM Configuration ************/ DDR_Regs->SDRAM_REF_CTRL = 0x0000515CU; // enable configuration /* SDRAM_TIM_1 */ TEMP = 0U; TEMP |= 0x09U << 25; // T_RP bit field 28:25 TEMP |= 0x09U << 21; // T_RCD bit field 24:21 TEMP |= 0x09U << 17; // T_WR bit field 20:17 TEMP |= 0x17U << 12; // T_RAS bit field 16:12 TEMP |= 0x20U << 6; // T_RC bit field 11:6 TEMP |= 0x1U << 3; // T_RRD bit field 5:3 TEMP |= 0x4U; // T_WTR bit field 2:0 DDR_Regs->SDRAM_TIM_1 = TEMP; /* SDRAM_TIM_2 */ TEMP = 0U; TEMP |= 0x3U << 28; // T_XP bit field 30:28 TEMP |= 0x71U << 16; // T_XSNR bit field 24:16 TEMP |= 0x1ffU << 6; // T_XSRD bit field 15:6 TEMP |= 0x4U << 3; // T_RTP bit field 5:3 TEMP |= 0x3U; // T_CKE bit field 2:0 DDR_Regs->SDRAM_TIM_2 = TEMP; /* SDRAM_TIM_3 */ TEMP = 0U; TEMP |= 0x5U << 28; // T_PDLL_UL bit field 31:28 (fixed value) TEMP |= 0x5U << 24; // T_CSTA bit field 27:24 (fixed value) TEMP |= 0x4U << 21; // T_CKESR bit field 23:21 TEMP |= 0x3fU << 15; // T_ZQCS bit field 20:15 TEMP |= 0x6AU << 4; // T_RFC bit field 12:4 TEMP |= 0xfU; // T_RAS_MAX bit field 3:0 (fixed value) DDR_Regs->SDRAM_TIM_3 = TEMP; DDR_Regs->DDR_PHY_CTRL_1 = 0x0010010FU; DDR_Regs->ZQ_CONFIG = 0x70074c1fU; DDR_Regs->PWR_MGMT_CTRL = 0x0U; /* DDR_SDCFG */ /* New value with DYN_ODT disabled and SDRAM_DRIVE = RZQ/7 //0x63222A32; // last config write DRAM init occurs */ TEMP = 0U; TEMP |= 0x3U << 29; // SDRAM_TYPE bit field 31:29 (fixed value) TEMP |= 0x0U << 27; // IBANK_POS bit field 28:27 TEMP |= 0x2U << 24; // DDR_TERM bit field 26:24 TEMP |= 0x2U << 21; // DYN_ODT bit field 22:21 TEMP |= 0x1U << 18; // SDRAM_DRIVE bit field 19:18 TEMP |= 0x3U << 16; // CWL bit field 17:16 TEMP |= 0x1U << 14; // NM bit field 15:14 TEMP |= 0xEU << 10; // CL bit field 13:10 TEMP |= 0x5U << 7; // ROWSIZE bit field 9:7 TEMP |= 0x3U << 4; // IBANK bit field 6:4 TEMP |= 0x0U << 3; // EBANK bit field 3:3 TEMP |= 0x2U; // PAGESIZE bit field 2:0 DDR_Regs->SDRAM_CONFIG = TEMP; //Wait 600us for HW init to complete for(i=0; i< 600*200; i++) asm(" nop 5"); DDR_Regs->SDRAM_REF_CTRL = 0x0000144FU; //Refresh rate = (7.8*666MHz) /**************** 4.2.1 Executing Partial Automatic Leveling ********************/ DDR_Regs->RDWR_LVL_RMP_CTRL = 0x80000000U; //enable full leveling DDR_Regs->RDWR_LVL_CTRL = 0x80000000U; //Trigger full leveling - This ignores read DQS leveling result and uses ratio forced value //(0x34) instead //Wait for min 1048576 DDR clock cycles for leveling to complete = 1048576 * 1.5ns = 1572864ns = 1.57ms. //Actual time = ~10-15 ms for(i=0; i<15*200000; i++) asm(" nop 5"); i=0; while ((DDR_Regs->STATUS & 0x00000070U) && (i<0xf)) { i++; asm(" nop 5"); if (i>3000000){ break; } } // Lock the kicker mechanism CSL_BootCfgLockKicker(); if (i>3000000) { printf("write leveling is failed! \n"); return -1; } printf("DDR3 configuration is done! \n"); return 0; } #if 0 #define uint32_t unsigned int #define uint8_t unsigned char /* Set the desired DDR3 configuration -- assumes 66.67 MHz DDR3 clock input */ int DDR3Init_s32(void) { CSL_Status status = CSL_SOK; volatile unsigned int loopCount; uint32_t ddr3config, ddrPhyCtrl; uint8_t ddrPHYReadLatency; EMIF4F_TIMING1_CONFIG sdram_tim1; EMIF4F_TIMING2_CONFIG sdram_tim2; EMIF4F_TIMING3_CONFIG sdram_tim3; EMIF4F_OUTPUT_IMP_CONFIG zqcfg; EMIF4F_PWR_MGMT_CONFIG pwrmgmtcfg; EMIF4F_SDRAM_CONFIG sdramcfg; CSL_BootCfgUnlockKicker(); /* Wait for PLL to lock = min 500 ref clock cycles. With refclk = 100MHz, = 5000 ns = 5us */ platform_delaycycles(50000); /**************** 3.3 Leveling Register Configuration ********************/ CSL_BootCfgGetDDRConfig(0, &ddr3config); ddr3config &= ~(0x007FE000); // clear ctrl_slave_ratio field CSL_BootCfgSetDDRConfig(0, ddr3config); CSL_BootCfgGetDDRConfig(0, &ddr3config); ddr3config |= 0x00200000; // set ctrl_slave_ratio to 0x100 CSL_BootCfgSetDDRConfig(0, ddr3config); CSL_BootCfgGetDDRConfig(12, &ddr3config); ddr3config |= 0x08000000; // Set invert_clkout = 1 CSL_BootCfgSetDDRConfig(12, ddr3config); CSL_BootCfgGetDDRConfig(0, &ddr3config); ddr3config |= 0xF; // set dll_lock_diff to 15 CSL_BootCfgSetDDRConfig(0, ddr3config); CSL_BootCfgGetDDRConfig(23, &ddr3config); ddr3config |= 0x00000200; // See section 4.2.1, set for partial automatic levelling CSL_BootCfgSetDDRConfig(23, ddr3config); /**************** 3.3 Partial Automatic Leveling ********************/ ddr3config = 0x00; CSL_BootCfgSetDDRConfig(2, ddr3config); ddr3config = 0x00; CSL_BootCfgSetDDRConfig(3, ddr3config); ddr3config = 0x00; CSL_BootCfgSetDDRConfig(4, ddr3config); ddr3config = 0x00; CSL_BootCfgSetDDRConfig(5, ddr3config); ddr3config = 0x00000033; CSL_BootCfgSetDDRConfig(6, ddr3config); ddr3config = 0x0000003A; CSL_BootCfgSetDDRConfig(7, ddr3config); ddr3config = 0x0000002C; CSL_BootCfgSetDDRConfig(8, ddr3config); ddr3config = 0x0000002C; CSL_BootCfgSetDDRConfig(9, ddr3config); ddr3config = 0x0000001C; CSL_BootCfgSetDDRConfig(10, ddr3config); ddr3config = 0x00; CSL_BootCfgSetDDRConfig(14, ddr3config); ddr3config = 0x00; CSL_BootCfgSetDDRConfig(15, ddr3config); ddr3config = 0x00; CSL_BootCfgSetDDRConfig(16, ddr3config); ddr3config = 0x00; CSL_BootCfgSetDDRConfig(17, ddr3config); ddr3config = 0x000000B7; CSL_BootCfgSetDDRConfig(18, ddr3config); ddr3config = 0x000000B1; CSL_BootCfgSetDDRConfig(19, ddr3config); ddr3config = 0x000000A4; CSL_BootCfgSetDDRConfig(20, ddr3config); ddr3config = 0x000000A4; CSL_BootCfgSetDDRConfig(21, ddr3config); ddr3config = 0x00000098; CSL_BootCfgSetDDRConfig(22, ddr3config); /*Do a PHY reset. Toggle DDR_PHY_CTRL_1 bit 15 0->1->0 */ CSL_EMIF4F_GetPhyControl(&ddrPhyCtrl, &ddrPHYReadLatency); ddrPhyCtrl &= ~(0x00008000); CSL_EMIF4F_SetPhyControl(ddrPhyCtrl, ddrPHYReadLatency); CSL_EMIF4F_GetPhyControl(&ddrPhyCtrl, &ddrPHYReadLatency); ddrPhyCtrl |= (0x00008000); CSL_EMIF4F_SetPhyControl(ddrPhyCtrl, ddrPHYReadLatency); CSL_EMIF4F_GetPhyControl(&ddrPhyCtrl, &ddrPHYReadLatency); ddrPhyCtrl &= ~(0x00008000); CSL_EMIF4F_SetPhyControl(ddrPhyCtrl, ddrPHYReadLatency); /***************** 3.4 Basic Controller and DRAM configuration ************/ /* enable configuration */ /* hEmif->SDRAM_REF_CTRL = 0x00006180; */ CSL_EMIF4F_EnableInitRefresh(); CSL_EMIF4F_SetRefreshRate(0x515C); sdram_tim1.t_wtr = 4; sdram_tim1.t_rrd = 1; sdram_tim1.t_rc = 0x20; sdram_tim1.t_ras = 0x17; sdram_tim1.t_wr = 0x09; sdram_tim1.t_rcd = 0x09; sdram_tim1.t_rp = 0x09; CSL_EMIF4F_SetTiming1Config(&sdram_tim1); /* hEmif->SDRAM_TIM_2 = 0x40877FEC; */ sdram_tim2.t_cke = 3; sdram_tim2.t_rtp = 4; sdram_tim2.t_xsrd = 0x1FF; sdram_tim2.t_xsnr = 0x071; sdram_tim2.t_xp = 3; sdram_tim2.t_odt = 0; CSL_EMIF4F_SetTiming2Config (&sdram_tim2); /* hEmif->SDRAM_TIM_3 = 0x55BF87FF; */ sdram_tim3.t_rasMax = 0xF; sdram_tim3.t_rfc = 0x06A; sdram_tim3.t_tdqsckmax = 0; sdram_tim3.zq_zqcs = 0x3F; sdram_tim3.t_ckesr = 4; sdram_tim3.t_csta = 0x5; sdram_tim3.t_pdll_ul = 0x5; CSL_EMIF4F_SetTiming3Config (&sdram_tim3); /* hEmif->DDR_PHY_CTRL_1 = 0x0010010F; */ ddrPHYReadLatency = 0x0F; ddrPhyCtrl = (0x0010010F); CSL_EMIF4F_SetPhyControl(ddrPhyCtrl, ddrPHYReadLatency); /* hEmif->ZQ_CONFIG = 0x70074C1F; */ zqcfg.zqRefInterval = 0x4C1F; zqcfg.zqZQCLMult = 3; zqcfg.zqZQCLInterval = 1; zqcfg.zqSFEXITEn = 1; zqcfg.zqDualCSEn = 1; zqcfg.zqCS0En = 1; zqcfg.zqCS1En = 0; CSL_EMIF4F_SetOutputImpedanceConfig(&zqcfg); /* hEmif->PWR_MGMT_CTRL = 0x0; */ pwrmgmtcfg.csTime = 0; pwrmgmtcfg.srTime = 0; pwrmgmtcfg.lpMode = 0; pwrmgmtcfg.dpdEnable = 0; pwrmgmtcfg.pdTime = 0; CSL_EMIF4F_SetPowerMgmtConfig (&pwrmgmtcfg); /* New value with DYN_ODT disabled and SDRAM_DRIVE = RZQ/7 */ /* hEmif->SDRAM_CONFIG = 0x63077AB3; */ CSL_EMIF4F_GetSDRAMConfig (&sdramcfg); sdramcfg.pageSize = 2; sdramcfg.eBank = 0; sdramcfg.iBank = 3; sdramcfg.rowSize = 5; sdramcfg.CASLatency = 14; sdramcfg.narrowMode = 1; sdramcfg.CASWriteLat = 3; sdramcfg.SDRAMDrive = 1; sdramcfg.disableDLL = 0; sdramcfg.dynODT = 2; sdramcfg.ddrDDQS = 0; sdramcfg.ddrTerm = 2; sdramcfg.iBankPos = 0; sdramcfg.type = 3; CSL_EMIF4F_SetSDRAMConfig (&sdramcfg); pll_delay(840336); /*Wait 600us for HW init to complete*/ /* Refresh rate = (7.8*666MHz] */ /* hEmif->SDRAM_REF_CTRL = 0x00001450; */ CSL_EMIF4F_SetRefreshRate(0x0000144F); /***************** 4.2.1 Partial automatic leveling ************/ /* hEmif->RDWR_LVL_RMP_CTRL = 0x80000000; */ CSL_EMIF4F_SetLevelingRampControlInfo(1, 0, 0, 0, 0); /* Trigger full leveling - This ignores read DQS leveling result and uses ratio forced value */ /* hEmif->RDWR_LVL_CTRL = 0x80000000; */ CSL_EMIF4F_SetLevelingControlInfo(1, 0, 0, 0, 0); /************************************************************ Wait for min 1048576 DDR clock cycles for leveling to complete = 1048576 * 1.5ns = 1572864ns = 1.57ms. Actual time = ~10-15 ms **************************************************************/ pll_delay(4201680); //Wait 3ms for leveling to complete return (status); } #endif /*""Function Define END""******************************************************/ /******************************************************************************* END OF FILE *******************************************************************************/
Hi Matsuno,
We recently discovered a bug in our C665x DDR3 initialization sequence. Please see the attached GEL file which contains the updated sequence. The updates to our documentation will be rolled into the DDR3 Users guide and Keystone DDR3 initialization app note in the near future.
Please update your sequence and let us know your observations. Apologize for any inconvenience.
We reviewed this gel file and implemented all of the changes we found. It made no difference in the write timing. The data strobe sample point is not centered in the data bit window and as a result the hold time is still marginal.
One question we ask everyone facing DDR3 issues that have no apparent software bugs in their init sequence is: are you following all the requirements listed in the DDR3 design requirements guide? Do you have a spreadsheet with these trace lengths (address, command, control, data group, clock signals) showing you meet the requirements?
All layout guidelines were followed. In particular the data bits and strobes were matched exactly within each byte lane. You can contact 'Meixner, David' (dmeixner@ti.com) for our history on this problem as he has already asked these questions.
I will check with David.
We have not had our initialization sequence formally reviewed; I will forward this to you. All boards have the same layout and behave the same way. We have not done testing at lower speeds. This issue is not creating a functional problem for us; the product is working reliably at a 667Mhz clock using DDR-1333 speed grade memory. The concern is that the write data hold time is barely meeting memory specs because the sampling point is shifted 45 degrees (as Matsuno also pointed out) and that variations in process may induce a functional problem in the future.
Hi Aditya
Thank you for your support.
I have not had a chance to check the waveform with the new GEL sequence yet, since high-speed scope has not been available until end of this month. I'll let you know as soon as it's ready and I observe it.
However, it makes "difference" in the behavior with the new GEL in our system. "No memory check error" is observed in my test routine with the new GEL.
Thank you
matsuno
Both individuals posting to this thread are concerned about DDR3 write timing. This is surprising. DDR3 write timing is the most robust and has the most timing margin. DDR3 interface integrity problems are almost always read related since the margins are smaller. I see the waveforms posted but I want to understand why there is an expectation that the write timing is a problem. Additionally, the related timing between the data strobe DQS/DQS# and data bits DQn is controlled entirely in the silicon IP design and PCB layout. This is not controllable by leveling adjustment.
There are numerous forum threads on this topic. Please refer to http://e2e.ti.com/support/dsp/c6000_multi-core_dsps/f/639/t/245304.aspx as an example. It lists the steps required to validate a DDR3 layout. The sequence of steps from that thread is copied below:
First, you need to lay out the board by following the routing rules stated in the DDR3 Design Requirements for KeyStone Devices at: http://www.ti.com/litv/pdf/sprabi1a. Most importantly, the length matching rules for the net classes need to be met. I recommend creation of a spreadsheet to validate that these rules are met. An example spreadsheet generated from the layout tool is attached here.
8473.Shn_EVM_DDR3_Rules_1201.xls
From this table, you can extract the routed lengths for each of the data groups and for the address/command/control/clock fly-by routes from the controller to each of the DRAMs. This information must be placed into the PHY_CALC spreadsheet. It and its associated Ap Note are available at: http://www.ti.com/litv/pdf/sprabl2a and http://www.ti.com/litv/zip/sprabl2a. The PHY_CALC spreadsheet will provide the initialization values needed for your board design. These links will also provide the REG_CALC spreadsheet which can be used to calculate the remainder of the necessary configuration values.
If you have done all of this and your design is not functional, please provide the routed length spreadsheet, PHY_CALC and REG_CALC spreadsheets for review.
Also, please describe your mode of failure and your method for testing the robustness of the memory interface. If there are failures observed, are they read or write failures? Repeated reads of the failed location can indicate the mode of failure.
Tom
We are not experiencing any failures. The problem is our expectation that the DQS/DQS# crossover point (sample point) would be centered in the DQn window to maximize timing margin for setup and hold time. Instead, the sample point is biased to favor setup time and barely meets hold time. If this was deliberate in the design of the silicon I would like to understand the reasoning. - thank you
James,
I was forwarded additional information on the issue that you have been reporting. We need to review and get back to you. The sample point is ideally set to the most robust sampling point while accounting for all variations of voltage, silicon, temperature and aging. This is not necessarily in the middle at a random PVT point for a given chip. Do you see this on multiple boards? Do all boards tested contain chips from the same order batch?
Tom
We have made the same measurement on 3 different boards. The first board used the slower speed grade silicon (TMS320C6657CZH8). The 2 more recent boards used faster silicon (TMS320C6657CZH) but the DDR3 timing was similar in all cases.
James,
Can you provide Time Of Flight measurements for these data group nets? We want the delays caused by the via barrels to also be included. Can you also provide the stackup and layout images of the DDR3 routing?
Tom
Hi Tom,
The printed circuit board stack-up, impedances, routing, and lengths are in the attached Word file. The measurements for each byte lane are "ball to ball" and include vias and fan-outs.
thanks
Jim
Jim,
When you say the data group nets match length exactly, what does this mean? Are they all within 1 mil?
Can you also provide the dielectric thicknesses in the stackup? Specifically, what are the thicknesses between layers 8, 9, 10 and 11?
Tom
Each data group is matched to the limits of our tool which is 0.00001 inches. The detailed stack-up and impedance report is attached.
James,
You indicate that you have this interface functional. Do you have a functional GEL with the configuration parameters? What speed DDR reference clock and DDR clock are you using? Are you using Partial Automatic or Full automatic leveling?
Tom
Hi Tom,
Our init code was posted on Jan 16. We are fully functional with a DDR3 clock of 667Mhz on sixty-five boards. The reference clock is 66.67Mhz generated by the TI CDCM6208 clock chip. The purpose of this inquiry is to simply understand why the DQS edge is not positioned closer to the center of the data bit window to give more hold time margin for write data. This is the expected norm based on another DDR3 design we have working on the same board for our host cpu.
Jim
Jim,
OK, looking back in to the code I see that you are using the proper register initialization for Partial Automatic leveling that was released a few weeks back. I wanted to be sure that this condition was not connected to programming the registers on this device incorrectly.
Tom
Hi Tom,
I posted two scope shots that were saved using the TEK/DSA70804C scope and TEK/P7380A differential probes.
thanks
Jim
Jim,
I want to let you know that we have not forgotten about this issue. We have busy with other activities. We are coordinating the right resources to address this in the coming weeks.
Tom
Hi Tom,
Could you please let me know whether this issue has been solved or not?
Because I have the same problem now.
Regards,
j-breeze
Hi,
I need to get any workarounds for this issue until next Monday morning Japan time.
So, doesn't someone know that?
Thanks in advance for your cooperation.
Regards,
j-breeze
We still have this issue but it has NOT caused any functional problems after building a few hundred boards.
Hi james,
Thank you for your information. I'm not sure, but I think there are any reliability problems.
I'll check out the detailed write leveling spec.
Regards,
j-breeze
A solution is available for this problem. The team conducting tests on this issue were able to observe a similar DQS-DQ shift as observed. We reviewed this observed behavior with the Silicon Design Team. With their help we identified a previously undocumented register that controls this offset. It appears that the default value in this register in C665x devices does not result in an optimum offset between DQS to DQ for writes. Once the proper value 0x40 is loaded into the data_reg_phy_dq_offset in bits 24:18 of the DDR3_CONFIG_REG_1 at offset 0x408 as part of the DDR3 initialization process, the proper DQS-DQ offset is obtained. Please see the GEL excerpt below which shows the additions needed to the C665x DDR3 configuration process to correct for this issue. Please confirm that this resolves the DQ-DQS issue observed.
We will be updating the online documentation in the coming weeks to contain this corrected procedure.
See below code snippet of C665x GEL – changes highlighted in bold text:
...
#define DDR3_CONFIG_REG_1 (*(unsigned int*)(CHIP_LEVEL_REG + 0x0408))
ddr3_setup_auto_lvl_1333()
{
int i,TEMP,startlo, stoplo,starthi, stophi;
KICK0 = KICK0_UNLOCK;
KICK1 = KICK1_UNLOCK;
/* Wait for PLL to lock = min 500 ref clock cycles.
With refclk = 100MHz, = 5000 ns = 5us */
Delay_milli_seconds(1);
/***************** 3.2 DDR3 PLL Configuration ************/
/* Done before */
/**************** 3.0 Leveling Register Configuration ********************/
/* Using partial automatic leveling due to errata */
/**************** 3.3 Leveling register configuration ********************/
DDR3_CONFIG_REG_0 &= ~(0x007FE000); // clear ctrl_slave_ratio field
DDR3_CONFIG_REG_0 |= 0x00200000; // set ctrl_slave_ratio to 0x100
DDR3_CONFIG_REG_12 |= 0x08000000; // Set invert_clkout = 1
DDR3_CONFIG_REG_0 |= 0xF; // set dll_lock_diff to 15
//From 4.2.1 Executing Partial Automatic Leveling -- Start
DDR3_CONFIG_REG_52 |= 0x00000200;
DDR3_CONFIG_REG_53 |= 0x00000200;
DDR3_CONFIG_REG_54 |= 0x00000200;
DDR3_CONFIG_REG_55 |= 0x00000200;
DDR3_CONFIG_REG_60 |= 0x00000200;
//From 4.2.1 Executing Partial Automatic Leveling -- End
//Values with invertclkout = 1 and v10 of PHY_CALC
/**************** 3.3 Partial Automatic Leveling ********************/
//Correct DQS-DQ timing offset
DDR3_CONFIG_REG_1 = 0x01000000;
DATA0_WRLVL_INIT_RATIO = 0x6C;
DATA1_WRLVL_INIT_RATIO = 0x6C;
DATA2_WRLVL_INIT_RATIO = 0x7A;
DATA3_WRLVL_INIT_RATIO = 0x73;
DATA8_WRLVL_INIT_RATIO = 0x5C;
DATA0_GTLVL_INIT_RATIO = 0xB0;
DATA1_GTLVL_INIT_RATIO = 0xB0;
DATA2_GTLVL_INIT_RATIO = 0xBD;
DATA3_GTLVL_INIT_RATIO = 0xC3;
DATA8_GTLVL_INIT_RATIO = 0xA4;
//Do a PHY reset. Toggle DDR_PHY_CTRL_1 bit 15 0->1->0
DDR_DDRPHYC &= ~(0x00008000);
DDR_DDRPHYC |= (0x00008000);
DDR_DDRPHYC &= ~(0x00008000);
…
Tom
We implemented this change and DO see improved margins in the write timing. Thank you for your attention to this matter!