diff --git a/litex/boards/targets/genesys2.py b/litex/boards/targets/genesys2.py index c10d6fb2d..69cfc2a41 100755 --- a/litex/boards/targets/genesys2.py +++ b/litex/boards/targets/genesys2.py @@ -63,8 +63,7 @@ class BaseSoC(SoCCore): self.submodules.ddrphy = s7ddrphy.K7DDRPHY(platform.request("ddram"), memtype = "DDR3", nphases = 4, - sys_clk_freq = sys_clk_freq, - cmd_latency = 1) + sys_clk_freq = sys_clk_freq) self.add_csr("ddrphy") self.add_sdram("sdram", phy = self.ddrphy, diff --git a/litex/boards/targets/kc705.py b/litex/boards/targets/kc705.py index 15f312eb8..320d0ca78 100755 --- a/litex/boards/targets/kc705.py +++ b/litex/boards/targets/kc705.py @@ -65,8 +65,7 @@ class BaseSoC(SoCCore): self.submodules.ddrphy = s7ddrphy.K7DDRPHY(platform.request("ddram"), memtype = "DDR3", nphases = 4, - sys_clk_freq = sys_clk_freq, - cmd_latency = 1) + sys_clk_freq = sys_clk_freq) self.add_csr("ddrphy") self.add_sdram("sdram", phy = self.ddrphy, diff --git a/litex/boards/targets/kcu105.py b/litex/boards/targets/kcu105.py index 7a9111d9c..83a4e684f 100755 --- a/litex/boards/targets/kcu105.py +++ b/litex/boards/targets/kcu105.py @@ -74,8 +74,7 @@ class BaseSoC(SoCCore): self.submodules.ddrphy = usddrphy.USDDRPHY(platform.request("ddram"), memtype = "DDR4", sys_clk_freq = sys_clk_freq, - iodelay_clk_freq = 200e6, - cmd_latency = 1) + iodelay_clk_freq = 200e6) self.add_csr("ddrphy") self.add_sdram("sdram", phy = self.ddrphy, diff --git a/litex/soc/software/bios/cmds/cmd_litedram.c b/litex/soc/software/bios/cmds/cmd_litedram.c index 1d9d51997..234814e4d 100644 --- a/litex/soc/software/bios/cmds/cmd_litedram.c +++ b/litex/soc/software/bios/cmds/cmd_litedram.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,20 @@ static void sdram_cal_handler(int nb_params, char **params) define_command(sdram_cal, sdram_cal_handler, "Calibrate SDRAM", LITEDRAM_CMDS); #endif +/** + * Command "sdram_test" + * + * Test SDRAM + * + */ +#if defined(CSR_SDRAM_BASE) +static void sdram_test_handler(int nb_params, char **params) +{ + memtest((unsigned int *)MAIN_RAM_BASE, MAIN_RAM_SIZE/32); +} +define_command(sdram_test, sdram_test_handler, "Test SDRAM", LITEDRAM_CMDS); +#endif + #ifdef CSR_DDRPHY_RDPHASE_ADDR /** * Command "sdram_force_rdphase" @@ -165,7 +180,7 @@ static void sdram_rst_dat_delay_handler(int nb_params, char **params) sdram_write_leveling_rst_dat_delay(module, 1); sdram_software_control_off(); } -define_command(sdram_rst_dat_delay, sdram_rst_dat_delay_handler, "Force write leveling Dat delay", LITEDRAM_CMDS); +define_command(sdram_rst_dat_delay, sdram_rst_dat_delay_handler, "Reset write leveling Dat delay", LITEDRAM_CMDS); #endif /** @@ -198,7 +213,67 @@ static void sdram_force_dat_delay_handler(int nb_params, char **params) sdram_write_leveling_force_dat_delay(module, taps, 1); sdram_software_control_off(); } -define_command(sdram_force_dat_delay, sdram_force_dat_delay_handler, "Reset write leveling Dat delay", LITEDRAM_CMDS); +define_command(sdram_force_dat_delay, sdram_force_dat_delay_handler, "Force write leveling Dat delay", LITEDRAM_CMDS); +#endif + +/** + * Command "sdram_rst_bitslip" + * + * Reset write leveling Bitslip + * + */ +#if defined(CSR_SDRAM_BASE) && defined(CSR_DDRPHY_BASE) +static void sdram_rst_bitslip_handler(int nb_params, char **params) +{ + char *c; + int module; + if (nb_params < 1) { + printf("sdram_rst_bitslip "); + return; + } + module = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect module"); + return; + } + sdram_software_control_on(); + sdram_write_leveling_rst_bitslip(module, 1); + sdram_software_control_off(); +} +define_command(sdram_rst_bitslip, sdram_rst_bitslip_handler, "Reset write leveling Bitslip", LITEDRAM_CMDS); +#endif + +/** + * Command "sdram_force_bitslip" + * + * Force write leveling Bitslip + * + */ +#if defined(CSR_SDRAM_BASE) && defined(CSR_DDRPHY_BASE) +static void sdram_force_bitslip_handler(int nb_params, char **params) +{ + char *c; + int module; + int bitslip; + if (nb_params < 2) { + printf("sdram_force_bitslip "); + return; + } + module = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect module"); + return; + } + bitslip = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect bitslip"); + return; + } + sdram_software_control_on(); + sdram_write_leveling_force_bitslip(module, bitslip, 1); + sdram_software_control_off(); +} +define_command(sdram_force_bitslip, sdram_force_bitslip_handler, "Force write leveling Bitslip", LITEDRAM_CMDS); #endif #endif diff --git a/litex/soc/software/liblitedram/sdram.c b/litex/soc/software/liblitedram/sdram.c index 852c37104..c8cfbb869 100644 --- a/litex/soc/software/liblitedram/sdram.c +++ b/litex/soc/software/liblitedram/sdram.c @@ -1,5 +1,5 @@ -// This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq // This file is Copyright (c) 2013-2020 Florent Kermarrec +// This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq // This file is Copyright (c) 2018 Chris Ballance // This file is Copyright (c) 2018 Dolu1990 // This file is Copyright (c) 2019 Gabriel L. Somlo @@ -238,6 +238,8 @@ void sdram_mode_register_write(char reg, int value) { /* Write Leveling */ /*-----------------------------------------------------------------------*/ +int _sdram_write_leveling_bitslips[16]; + #ifdef SDRAM_PHY_WRITE_LEVELING_CAPABLE int _sdram_write_leveling_cmd_scan = 1; @@ -305,6 +307,18 @@ void sdram_write_leveling_force_dat_delay(int module, int taps, int show) { printf("Forcing Dat delay of module %d to %d taps\n", module, taps); } +void sdram_write_leveling_rst_bitslip(int module, int show) { + _sdram_write_leveling_bitslips[module] = -1; + if (show) + printf("Reseting Bitslip of module %d\n", module); +} + +void sdram_write_leveling_force_bitslip(int module, int bitslip, int show) { + _sdram_write_leveling_bitslips[module] = bitslip; + if (show) + printf("Forcing Bitslip of module %d to %d\n", module, bitslip); +} + static void sdram_write_leveling_rst_delay(int module) { #ifdef SDRAM_PHY_WRITE_LEVELING_REINIT int i; @@ -507,7 +521,6 @@ int sdram_write_leveling(void) int cdly_range_end; int cdly_range_step; - if (_sdram_write_leveling_cmd_scan) { printf(" Cmd/Clk scan:\n"); @@ -580,7 +593,7 @@ static void sdram_read_leveling_rst_delay(int module) { #ifdef SDRAM_PHY_ECP5DDRPHY /* Sync all DQSBUFM's, By toggling all dly_sel (DQSBUFM.PAUSE) lines. */ - ddrphy_dly_sel_write(0xFF); + ddrphy_dly_sel_write(0xff); ddrphy_dly_sel_write(0); #endif } @@ -597,7 +610,7 @@ static void sdram_read_leveling_inc_delay(int module) { #ifdef SDRAM_PHY_ECP5DDRPHY /* Sync all DQSBUFM's, By toggling all dly_sel (DQSBUFM.PAUSE) lines. */ - ddrphy_dly_sel_write(0xFF); + ddrphy_dly_sel_write(0xff); ddrphy_dly_sel_write(0); #endif } @@ -607,7 +620,7 @@ static void sdram_read_leveling_rst_bitslip(char m) /* sel module */ ddrphy_dly_sel_write(1 << m); - /* inc delay */ + /* rst delay */ ddrphy_rdly_dq_bitslip_rst_write(1); /* unsel module */ @@ -627,139 +640,119 @@ static void sdram_read_leveling_inc_bitslip(char m) ddrphy_dly_sel_write(0); } -static int sdram_read_leveling_scan_module(int module, int bitslip) -{ - unsigned int prv; - unsigned char prs[SDRAM_PHY_PHASES][DFII_PIX_DATA_BYTES]; - unsigned char tst[DFII_PIX_DATA_BYTES]; - int p, i; - int score; - - /* Generate pseudo-random sequence */ - prv = 42; - for(p=0;p> module) & 0x1) != 1) + return 0; +#endif + + return 1; +} + +static int sdram_read_leveling_scan_module(int module, int bitslip, int show) +{ + int i; + int score; + + /* Check test pattern for each delay value */ + score = 0; + if (show) + printf(" m%d, b%d: |", module, bitslip); sdram_read_leveling_rst_delay(module); for(i=0;i 32 - show = (i%16 == 0); + _show = (i%16 == 0) & show; #endif -#ifdef SDRAM_PHY_ECP5DDRPHY - ddrphy_burstdet_clr_write(1); -#endif - command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA); - cdelay(15); - for(p=0;p> module) & 0x1) != 1) - working = 0; -#endif - if (show) + working = sdram_write_read_check_test_pattern(module, 42); + working &= sdram_write_read_check_test_pattern(module, 84); + if (_show) printf("%d", working); score += working; sdram_read_leveling_inc_delay(module); } - printf("| "); - - /* Precharge */ - sdram_dfii_pi0_address_write(0); - sdram_dfii_pi0_baddress_write(0); - command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS); - cdelay(15); + if (show) + printf("| "); return score; } static void sdram_read_leveling_module(int module) { - unsigned int prv; - unsigned char prs[SDRAM_PHY_PHASES][DFII_PIX_DATA_BYTES]; - unsigned char tst[DFII_PIX_DATA_BYTES]; - int p, i; + int i; int working; int delay, delay_min, delay_max; printf("delays: "); - /* Generate pseudo-random sequence */ - prv = 42; - for(p=0;p> module) & 0x1) != 1) - working = 0; -#endif + working = sdram_write_read_check_test_pattern(module, 42); + working &= sdram_write_read_check_test_pattern(module, 84); if(working) break; delay++; @@ -782,24 +775,8 @@ static void sdram_read_leveling_module(int module) /* Find largest working delay */ while(1) { -#ifdef SDRAM_PHY_ECP5DDRPHY - ddrphy_burstdet_clr_write(1); -#endif - command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA); - cdelay(15); - working = 1; - for(p=0;p> module) & 0x1) != 1) - working = 0; -#endif + working = sdram_write_read_check_test_pattern(module, 42); + working &= sdram_write_read_check_test_pattern(module, 84); if(!working) break; delay++; @@ -818,12 +795,6 @@ static void sdram_read_leveling_module(int module) sdram_read_leveling_rst_delay(module); for(i=0;i<(delay_min+delay_max)/2;i++) sdram_read_leveling_inc_delay(module); - - /* Precharge */ - sdram_dfii_pi0_address_write(0); - sdram_dfii_pi0_baddress_write(0); - command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS); - cdelay(15); } #endif /* CSR_DDRPHY_BASE */ @@ -842,37 +813,101 @@ void sdram_read_leveling(void) int best_bitslip; for(module=0; module best_score) { best_bitslip = bitslip; best_score = score; } - /* exit */ + /* Exit */ if (bitslip == SDRAM_PHY_BITSLIPS-1) break; - /* increment bitslip */ + /* Increment bitslip */ sdram_read_leveling_inc_bitslip(module); } - /* select best read window */ + /* Select best read window */ printf(" best: m%d, b%02d ", module, best_bitslip); sdram_read_leveling_rst_bitslip(module); for (bitslip=0; bitslip best_score) { + best_bitslip = bitslip; + best_score = score; + } + } + + if (_sdram_write_leveling_bitslips[module] < 0) + bitslip = best_bitslip; + else + bitslip = _sdram_write_leveling_bitslips[module]; + printf("m%d:%d ", module, bitslip); + + /* Select best write window */ + ddrphy_dly_sel_write(1 << module); + /* rst bitslip */ + ddrphy_wdly_dq_bitslip_rst_write(1); + for (i=0; i