def get_ddr2_phy_init_sequence(phy_settings, timing_settings): cl = phy_settings.cl bl = 4 wr = 2 mr = log2_int(bl) + (cl << 4) + (wr << 9) emr = 0 emr2 = 0 emr3 = 0 reset_dll = 1 << 8 ocd = 7 << 7 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200), ("Load Extended Mode Register / OCD Default", emr+ocd, 1, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0), ] return init_sequence, None
def load(cls): settings = get_litedram_settings() if settings.phy.memtype == "SDR": burst_length = settings.phy.nphases else: from litedram.common import burst_lengths burst_length = burst_lengths[settings.phy.memtype] address_align = log2_int(burst_length) return cls( colbits=settings.geom.colbits, rowbits=settings.geom.rowbits, bankbits=settings.geom.bankbits, address_align=address_align, address_mapping=settings.address_mapping, dram_port_width=settings.phy.nphases * settings.phy.dfi_databits, )
def get_sdr_phy_init_sequence(phy_settings, timing_settings): cl = phy_settings.cl bl = 1 mr = log2_int(bl) + (cl << 4) reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] return init_sequence, None
def __init__(self, platform, sys_clk_freq): self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_por = ClockDomain() # Clock from HFOSC self.submodules.sys_clk = sys_osc = NXOSCA() sys_osc.create_hf_clk(self.cd_sys, sys_clk_freq) # We make the period constraint 10% tighter than our actual system # clock frequency, because the CrossLink-NX internal oscillator runs # at ±10% of nominal frequency. platform.add_period_constraint(self.cd_sys.clk, 1e9 / (sys_clk_freq * 1.1)) # Power On Reset por_cycles = 4096 por_counter = Signal(log2_int(por_cycles), reset=por_cycles - 1) self.comb += self.cd_por.clk.eq(self.cd_sys.clk) self.sync.por += If(por_counter != 0, por_counter.eq(por_counter - 1)) self.specials += AsyncResetSynchronizer(self.cd_sys, (por_counter != 0))
def get_sdram_phy_init_sequence(phy_settings, timing_settings): # init sequence cmds = { "PRECHARGE_ALL": "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS", "MODE_REGISTER": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS", "AUTO_REFRESH": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS", "UNRESET": "DFII_CONTROL_ODT|DFII_CONTROL_RESET_N", "CKE": "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N" } cl = phy_settings.cl mr1 = None if phy_settings.memtype == "SDR": bl = 1 mr = log2_int(bl) + (cl << 4) reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format( cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif phy_settings.memtype == "DDR": bl = 4 mr = log2_int(bl) + (cl << 4) emr = 0 reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format( cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif phy_settings.memtype == "LPDDR": bl = 4 mr = log2_int(bl) + (cl << 4) emr = 0 reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format( cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif phy_settings.memtype == "DDR2": bl = 4 wr = 2 mr = log2_int(bl) + (cl << 4) + (wr << 9) emr = 0 emr2 = 0 emr3 = 0 reset_dll = 1 << 8 ocd = 7 << 7 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format( cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200), ("Load Extended Mode Register / OCD Default", emr + ocd, 1, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0), ] elif phy_settings.memtype == "DDR3": bl = 8 cwl = phy_settings.cwl def format_mr0(bl, cl, wr, dll_reset): bl_to_mr0 = {4: 0b10, 8: 0b00} cl_to_mr0 = { 5: 0b0010, 6: 0b0100, 7: 0b0110, 8: 0b1000, 9: 0b1010, 10: 0b1100, 11: 0b1110, 12: 0b0001, 13: 0b0011, 14: 0b0101 } wr_to_mr0 = { 16: 0b000, 5: 0b001, 6: 0b010, 7: 0b011, 8: 0b100, 10: 0b101, 12: 0b110, 14: 0b111 } mr0 = bl_to_mr0[bl] mr0 |= (cl_to_mr0[cl] & 1) << 2 mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4 mr0 |= dll_reset << 8 mr0 |= wr_to_mr0[wr] << 9 return mr0 def format_mr1(ron, rtt_nom): mr1 = ((ron >> 0) & 1) << 1 mr1 |= ((ron >> 1) & 1) << 5 mr1 |= ((rtt_nom >> 0) & 1) << 2 mr1 |= ((rtt_nom >> 1) & 1) << 6 mr1 |= ((rtt_nom >> 2) & 1) << 9 return mr1 def format_mr2(cwl, rtt_wr): mr2 = (cwl - 5) << 3 mr2 |= rtt_wr << 9 return mr2 z_to_rtt_nom = { "disabled": 0, "60ohm": 1, "120ohm": 2, "40ohm": 3, "20ohm": 4, "30ohm": 5 } z_to_rtt_wr = { "disabled": 0, "60ohm": 1, "120ohm": 2, } z_to_ron = { "40ohm": 0, "34ohm": 1, } # default electrical settings (point to point) rtt_nom = "60ohm" rtt_wr = "60ohm" ron = "34ohm" # override electrical settings if specified if hasattr(phy_settings, "rtt_nom"): rtt_nom = phy_settings.rtt_nom if hasattr(phy_settings, "rtt_wr"): rtt_wr = phy_settings.rtt_wr if hasattr(phy_settings, "ron"): ron = phy_settings.ron wr = max(timing_settings.tWTR * phy_settings.nphases, 5) # >= ceiling(tWR/tCK) mr0 = format_mr0(bl, cl, wr, 1) mr1 = format_mr1(z_to_ron[ron], z_to_rtt_nom[rtt_nom]) mr2 = format_mr2(cwl, z_to_rtt_wr[rtt_wr]) mr3 = 0 init_sequence = [ ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000), ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000), ("Load Mode Register 2, CWL={0:d}".format(cwl), mr2, 2, cmds["MODE_REGISTER"], 0), ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0), ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200), ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200), ] elif phy_settings.memtype == "DDR4": bl = 8 cwl = phy_settings.cwl def format_mr0(bl, cl, wr, dll_reset): bl_to_mr0 = {4: 0b10, 8: 0b00} cl_to_mr0 = { 9: 0b00000, 10: 0b00001, 11: 0b00010, 12: 0b00011, 13: 0b00100, 14: 0b00101, 15: 0b00110, 16: 0b00111, 18: 0b01000, 20: 0b01001, 22: 0b01010, 24: 0b01011, 23: 0b01100, 17: 0b01101, 19: 0b01110, 21: 0b01111, 25: 0b10000, 26: 0b10001, 27: 0b10010, 28: 0b10011, 29: 0b10100, 30: 0b10101, 31: 0b10110, 32: 0b10111, } wr_to_mr0 = { 10: 0b0000, 12: 0b0001, 14: 0b0010, 16: 0b0011, 18: 0b0100, 20: 0b0101, 24: 0b0110, 22: 0b0111, 26: 0b1000, 28: 0b1001, } mr0 = bl_to_mr0[bl] mr0 |= (cl_to_mr0[cl] & 0b1) << 2 mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4 mr0 |= ((cl_to_mr0[cl] >> 4) & 0b1) << 12 mr0 |= dll_reset << 8 mr0 |= (wr_to_mr0[wr] & 0b111) << 9 mr0 |= (wr_to_mr0[wr] >> 3) << 13 return mr0 def format_mr1(dll_enable, ron, rtt_nom): mr1 = dll_enable mr1 |= ((ron >> 0) & 0b1) << 1 mr1 |= ((ron >> 1) & 0b1) << 2 mr1 |= ((rtt_nom >> 0) & 0b1) << 8 mr1 |= ((rtt_nom >> 1) & 0b1) << 9 mr1 |= ((rtt_nom >> 2) & 0b1) << 10 return mr1 def format_mr2(cwl, rtt_wr): cwl_to_mr2 = { 9: 0b000, 10: 0b001, 11: 0b010, 12: 0b011, 14: 0b100, 16: 0b101, 18: 0b110, 20: 0b111 } mr2 = cwl_to_mr2[cwl] << 3 mr2 |= rtt_wr << 9 return mr2 def format_mr6(tccd): tccd_to_mr6 = {4: 0b000, 5: 0b001, 6: 0b010, 7: 0b011, 8: 0b100} mr6 = tccd_to_mr6[tccd] << 10 return mr6 z_to_rtt_nom = { "disabled": 0b000, "60ohm": 0b001, "120ohm": 0b010, "40ohm": 0b011, "240ohm": 0b100, "48ohm": 0b101, "80ohm": 0b110, "34ohm": 0b111 } z_to_rtt_wr = { "disabled": 0b000, "120ohm": 0b001, "240ohm": 0b010, "high-z": 0b011, "80ohm": 0b100, } z_to_ron = { "34ohm": 0b00, "48ohm": 0b01, } # default electrical settings (point to point) rtt_nom = "40ohm" rtt_wr = "120ohm" ron = "34ohm" # override electrical settings if specified if hasattr(phy_settings, "rtt_nom"): rtt_nom = phy_settings.rtt_nom if hasattr(phy_settings, "rtt_wr"): rtt_wr = phy_settings.rtt_wr if hasattr(phy_settings, "ron"): ron = phy_settings.ron wr = max(timing_settings.tWTR * phy_settings.nphases, 10) # >= ceiling(tWR/tCK) mr0 = format_mr0(bl, cl, wr, 1) mr1 = format_mr1(1, z_to_ron[ron], z_to_rtt_nom[rtt_nom]) mr2 = format_mr2(cwl, z_to_rtt_wr[rtt_wr]) mr3 = 0 mr4 = 0 mr5 = 0 mr6 = format_mr6(4) # FIXME: tCCD init_sequence = [ ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000), ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000), ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0), ("Load Mode Register 6", mr6, 6, cmds["MODE_REGISTER"], 0), ("Load Mode Register 5", mr5, 5, cmds["MODE_REGISTER"], 0), ("Load Mode Register 4", mr4, 4, cmds["MODE_REGISTER"], 0), ("Load Mode Register 2, CWL={0:d}".format(cwl), mr2, 2, cmds["MODE_REGISTER"], 0), ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200), ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200), ] else: raise NotImplementedError("Unsupported memory type: " + phy_settings.memtype) return init_sequence, mr1
def _get_bus_shift(self, bus_width): addr_shift = log2_int(self.dram_port_width // bus_width) bus_shift = log2_int(bus_width // 8) shift = addr_shift + bus_shift - self.address_align return shift
def _get_sdram_phy_sequence(sdram_phy_settings): nphases = sdram_phy_settings.nphases cl = sdram_phy_settings.cl consts = {} cmds = { "PRECHARGE_ALL": "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS", "MODE_REGISTER": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS", "AUTO_REFRESH": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS", "UNRESET": "DFII_CONTROL_ODT|DFII_CONTROL_RESET_N", "CKE": "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N" } if sdram_phy_settings.memtype == "SDR": bl = sdram_phy_settings.nphases mr = log2_int(bl) + (cl << 4) reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format( cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif sdram_phy_settings.memtype == "DDR": bl = 2 * sdram_phy_settings.nphases mr = log2_int(bl) + (cl << 4) emr = 0 reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format( cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif sdram_phy_settings.memtype == "LPDDR": bl = 2 * sdram_phy_settings.nphases mr = log2_int(bl) + (cl << 4) emr = 0 reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format( cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif sdram_phy_settings.memtype == "DDR2": bl = 2 * sdram_phy_settings.nphases wr = 2 mr = log2_int(bl) + (cl << 4) + (wr << 9) emr = 0 emr2 = 0 emr3 = 0 reset_dll = 1 << 8 ocd = 7 << 7 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format( cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200), ("Load Extended Mode Register / OCD Default", emr + ocd, 1, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0), ] elif sdram_phy_settings.memtype == "DDR3": bl = 2 * sdram_phy_settings.nphases def format_mr0(bl, cl, wr, dll_reset): bl_to_mr0 = {4: 0b10, 8: 0b00} cl_to_mr0 = { 5: 0b0010, 6: 0b0100, 7: 0b0110, 8: 0b1000, 9: 0b1010, 10: 0b1100, 11: 0b1110, 12: 0b0001, 13: 0b0011, 14: 0b0101 } wr_to_mr0 = { 16: 0b000, 5: 0b001, 6: 0b010, 7: 0b011, 8: 0b100, 10: 0b101, 12: 0b110, 14: 0b111 } mr0 = bl_to_mr0[bl] mr0 |= (cl_to_mr0[cl] & 1) << 2 mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4 mr0 |= dll_reset << 8 mr0 |= wr_to_mr0[wr] << 9 return mr0 def format_mr1(output_drive_strength, rtt_nom): mr1 = ((output_drive_strength >> 0) & 1) << 1 mr1 |= ((output_drive_strength >> 1) & 1) << 5 mr1 |= ((rtt_nom >> 0) & 1) << 2 mr1 |= ((rtt_nom >> 1) & 1) << 6 mr1 |= ((rtt_nom >> 2) & 1) << 9 return mr1 def format_mr2(cwl, rtt_wr): mr2 = (cwl - 5) << 3 mr2 |= rtt_wr << 9 return mr2 mr0 = format_mr0(bl, cl, 8, 1) # wr=8 FIXME: this should be ceiling(tWR/tCK) mr1 = format_mr1( 1, 1) # Output Drive Strength RZQ/7 (34 ohm) / Rtt RZQ/4 (60 ohm) mr2 = format_mr2(sdram_phy_settings.cwl, 2) # Rtt(WR) RZQ/4 mr3 = 0 init_sequence = [ ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000), ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000), ("Load Mode Register 2", mr2, 2, cmds["MODE_REGISTER"], 0), ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0), ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200), ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200), ] # the value of MR1 needs to be modified during write leveling consts["DDR3_MR1"] = mr1 else: raise NotImplementedError("Unsupported memory type: " + sdram_phy_settings.memtype) return { "nphases": sdram_phy_settings.nphases, "rdphase": sdram_phy_settings.rdphase, "wrphase": sdram_phy_settings.wrphase, "consts": consts, "init_sequence": init_sequence }
def get_sdram_phy_header(sdram_phy_settings): r = "#ifndef __GENERATED_SDRAM_PHY_H\n#define __GENERATED_SDRAM_PHY_H\n" r += "#include <hw/common.h>\n#include <generated/csr.h>\n#include <hw/flags.h>\n\n" nphases = sdram_phy_settings.nphases r += "#define DFII_NPHASES "+str(nphases)+"\n\n" r += "static void cdelay(int i);\n" # commands_px functions for n in range(nphases): r += """ static void command_p{n}(int cmd) {{ sdram_dfii_pi{n}_command_write(cmd); sdram_dfii_pi{n}_command_issue_write(1); }}""".format(n=str(n)) r += "\n\n" # rd/wr access macros r += """ #define sdram_dfii_pird_address_write(X) sdram_dfii_pi{rdphase}_address_write(X) #define sdram_dfii_piwr_address_write(X) sdram_dfii_pi{wrphase}_address_write(X) #define sdram_dfii_pird_baddress_write(X) sdram_dfii_pi{rdphase}_baddress_write(X) #define sdram_dfii_piwr_baddress_write(X) sdram_dfii_pi{wrphase}_baddress_write(X) #define command_prd(X) command_p{rdphase}(X) #define command_pwr(X) command_p{wrphase}(X) """.format(rdphase=str(sdram_phy_settings.rdphase), wrphase=str(sdram_phy_settings.wrphase)) r += "\n" # # sdrrd/sdrwr functions utilities # r += "#define DFII_PIX_DATA_SIZE CSR_SDRAM_DFII_PI0_WRDATA_SIZE\n" sdram_dfii_pix_wrdata_addr = [] for n in range(nphases): sdram_dfii_pix_wrdata_addr.append("CSR_SDRAM_DFII_PI{n}_WRDATA_ADDR".format(n=n)) r += """ const unsigned int sdram_dfii_pix_wrdata_addr[{n}] = {{ {sdram_dfii_pix_wrdata_addr} }}; """.format(n=nphases, sdram_dfii_pix_wrdata_addr=",\n\t".join(sdram_dfii_pix_wrdata_addr)) sdram_dfii_pix_rddata_addr = [] for n in range(nphases): sdram_dfii_pix_rddata_addr.append("CSR_SDRAM_DFII_PI{n}_RDDATA_ADDR".format(n=n)) r += """ const unsigned int sdram_dfii_pix_rddata_addr[{n}] = {{ {sdram_dfii_pix_rddata_addr} }}; """.format(n=nphases, sdram_dfii_pix_rddata_addr=",\n\t".join(sdram_dfii_pix_rddata_addr)) r += "\n" # init sequence cmds = { "PRECHARGE_ALL": "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS", "MODE_REGISTER": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS", "AUTO_REFRESH": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS", "UNRESET": "DFII_CONTROL_ODT|DFII_CONTROL_RESET_N", "CKE": "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N" } cl = sdram_phy_settings.cl if sdram_phy_settings.memtype == "SDR": bl = sdram_phy_settings.nphases mr = log2_int(bl) + (cl << 4) reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif sdram_phy_settings.memtype == "DDR": bl = 2*sdram_phy_settings.nphases mr = log2_int(bl) + (cl << 4) emr = 0 reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif sdram_phy_settings.memtype == "LPDDR": bl = 2*sdram_phy_settings.nphases mr = log2_int(bl) + (cl << 4) emr = 0 reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif sdram_phy_settings.memtype == "DDR2": bl = 2*sdram_phy_settings.nphases wr = 2 mr = log2_int(bl) + (cl << 4) + (wr << 9) emr = 0 emr2 = 0 emr3 = 0 reset_dll = 1 << 8 ocd = 7 << 7 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200), ("Load Extended Mode Register / OCD Default", emr+ocd, 1, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0), ] elif sdram_phy_settings.memtype == "DDR3": bl = 2*sdram_phy_settings.nphases def format_mr0(bl, cl, wr, dll_reset): bl_to_mr0 = { 4: 0b10, 8: 0b00 } cl_to_mr0 = { 5: 0b0010, 6: 0b0100, 7: 0b0110, 8: 0b1000, 9: 0b1010, 10: 0b1100, 11: 0b1110, 12: 0b0001, 13: 0b0011, 14: 0b0101 } wr_to_mr0 = { 16: 0b000, 5: 0b001, 6: 0b010, 7: 0b011, 8: 0b100, 10: 0b101, 12: 0b110, 14: 0b111 } mr0 = bl_to_mr0[bl] mr0 |= (cl_to_mr0[cl] & 1) << 2 mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4 mr0 |= dll_reset << 8 mr0 |= wr_to_mr0[wr] << 9 return mr0 def format_mr1(output_drive_strength, rtt_nom): mr1 = ((output_drive_strength >> 0) & 1) << 1 mr1 |= ((output_drive_strength >> 1) & 1) << 5 mr1 |= ((rtt_nom >> 0) & 1) << 2 mr1 |= ((rtt_nom >> 1) & 1) << 6 mr1 |= ((rtt_nom >> 2) & 1) << 9 return mr1 def format_mr2(cwl, rtt_wr): mr2 = (cwl-5) << 3 mr2 |= rtt_wr << 9 return mr2 mr0 = format_mr0(bl, cl, 8, 1) # wr=8 FIXME: this should be ceiling(tWR/tCK) mr1 = format_mr1(1, 1) # Output Drive Strength RZQ/7 (34 ohm) / Rtt RZQ/4 (60 ohm) mr2 = format_mr2(sdram_phy_settings.cwl, 2) # Rtt(WR) RZQ/4 mr3 = 0 init_sequence = [ ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000), ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000), ("Load Mode Register 2", mr2, 2, cmds["MODE_REGISTER"], 0), ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0), ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200), ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200), ] # the value of MR1 needs to be modified during write leveling r += "#define DDR3_MR1 {}\n\n".format(mr1) else: raise NotImplementedError("Unsupported memory type: "+sdram_phy_settings.memtype) r += "static void init_sequence(void)\n{\n" for comment, a, ba, cmd, delay in init_sequence: r += "\t/* {0} */\n".format(comment) r += "\tsdram_dfii_pi0_address_write({0:#x});\n".format(a) r += "\tsdram_dfii_pi0_baddress_write({0:d});\n".format(ba) if cmd[:12] == "DFII_CONTROL": r += "\tsdram_dfii_control_write({0});\n".format(cmd) else: r += "\tcommand_p0({0});\n".format(cmd) if delay: r += "\tcdelay({0:d});\n".format(delay) r += "\n" r += "}\n" r += "#endif\n" return r
def __init__(self, ddr_wr_port, ddr_rd_port, udp_port): SIZE = 1024 * 1024 SIZE = 1024 self.fifo_full = CSRStatus(reset=0) self.fifo_error = CSRStatus(reset=0) self.fifo_load = CSRStorage( reset=0) # Load the coefficients in memory to the ROI Summer self.fifo_read = CSRStorage(reset=0) self.fifo_size = CSRStorage(32, reset=SIZE) self.dst_ip = CSRStorage(32, reset=convert_ip("192.168.1.114")) self.dst_port = CSRStorage(16, reset=7778) dw = 64 print( f"Write port: A ({ddr_wr_port.address_width})/ D ({ddr_wr_port.data_width})" ) print( f"Read port: A ({ddr_rd_port.address_width})/ D ({ddr_rd_port.data_width})" ) self.submodules.dram_fifo = dram_fifo = LiteDRAMFIFO( data_width=dw, base=0, depth=SIZE, write_port=ddr_wr_port, read_port=ddr_rd_port, with_bypass=True, ) # self.mf = mf = Signal(reset=0) # mf == More Fragments # self.fragment_offset = fragment_offset = Signal(13, reset=0) # self.identification = identification = Signal(16, reset=0) self.submodules.adcs = adcs = ADCStream(1, dw) self.fifo_counter = fifo_counter = Signal(24) self.load_fifo = load_fifo = Signal() # adc --> buffer_fifo self.submodules.buffer_fifo = buffer_fifo = stream.SyncFIFO( stream.EndpointDescription([("data", dw)]), 256, buffered=True) # buffer_fifo --> dram_fifo fifo_size = Signal(32) self.sync += [ fifo_size.eq(self.fifo_size.storage), If(self.fifo_load.re & self.fifo_load.storage, fifo_counter.eq(0), load_fifo.eq(1)), If(load_fifo & adcs.source.valid, self.fifo_full.status.eq(0), self.fifo_error.status.eq(~dram_fifo.dram_fifo.ctrl.writable), fifo_counter.eq(fifo_counter + 1)), If((fifo_counter == fifo_size - 1) & adcs.source.valid, load_fifo.eq(0), self.fifo_full.status.eq(1)), ] self.comb += [ buffer_fifo.sink.data.eq(adcs.source.data), buffer_fifo.sink.valid.eq(adcs.source.valid & load_fifo), buffer_fifo.source.connect(dram_fifo.sink), ] # fifo --> stride converter self.submodules.stride_converter = sc = stream.Converter( dw, udp_port.dw) self.read_from_dram_fifo = read_from_dram_fifo = Signal() self.comb += [dram_fifo.source.connect(sc.sink)] self.receive_count = receive_count = Signal(24) self.sync += [ If(dram_fifo.source.valid & dram_fifo.source.ready, receive_count.eq(receive_count + 1)).Elif( read_from_dram_fifo == 0, receive_count.eq(0)) ] # --> udp fragmenter --> self.submodules.udp_fragmenter = udp_fragmenter = UDPFragmenter( udp_port.dw) self.sync += read_from_dram_fifo.eq(self.fifo_read.storage) self.comb += If( read_from_dram_fifo, # TODO: There is a bug somewhere in the converter, # its source.last somehow gets set, no idea why. That signal is of no real use # for the fragmenter anyways, so we live without it sc.source.connect(udp_fragmenter.sink, omit={'total_size', 'last'})) # TODO: 8 should be adcstream data width // 8 self.comb += udp_fragmenter.sink.length.eq(fifo_size << log2_int(dw // 8)) self.comb += udp_fragmenter.source.connect(udp_port.sink) self.comb += [ # param udp_port.sink.src_port.eq(4321), udp_port.sink.dst_port.eq(self.dst_port.storage), udp_port.sink.ip_address.eq(self.dst_ip.storage), # udp_port.sink.ip_address.eq(convert_ip("192.168.88.101")), # payload udp_port.sink.error.eq(0) ] # debug self.first_sample, self.last_sample = Signal(16), Signal(16) self.sync += [ If(fifo_counter == 1, self.first_sample.eq(adcs.source.data[:16])), If(fifo_counter == SIZE - 2, self.last_sample.eq(adcs.source.data[:16])), ]
def __init__(self, ddr_wr_port, ddr_rd_port, udp_port, adc_source, adc_dw): SIZE = 1024 * 1024 self.fifo_full = CSRStatus(reset=0) self.fifo_error = CSRStatus(reset=0) self.fifo_load = CSRStorage(reset=0) self.fifo_read = CSRStorage(reset=0) self.fifo_size = CSRStorage(32, reset=SIZE) self.dst_ip = CSRStorage(32, reset=convert_ip("192.168.1.114")) self.dst_port = CSRStorage(16, reset=7778) self.fifo_counter = fifo_counter = Signal(24) self.load_fifo = load_fifo = Signal() dw = ddr_wr_port.data_width print( f"Write port: A ({ddr_wr_port.address_width})/ D ({ddr_wr_port.data_width})" ) print( f"Read port: A ({ddr_rd_port.address_width})/ D ({ddr_rd_port.data_width})" ) print(f"dw: {dw}; adc_dw: {adc_dw}") self.submodules.dram_fifo = dram_fifo = LiteDRAMFIFO( data_width=dw, base=0, depth=SIZE * (dw // 8), # liteDRAM expects this in bytes write_port=ddr_wr_port, read_port=ddr_rd_port, ) self.adc_data = adc_data = Signal(dw) DW_RATIO = dw // adc_dw log_dw_ratio = log2_int(DW_RATIO) word_count = Signal(log_dw_ratio) word_count_d = Signal(log_dw_ratio) self.sync += [ If(adc_source.valid, adc_data.eq(Cat(adc_data[adc_dw:], adc_source.data)), word_count.eq(word_count + 1)), word_count_d.eq(word_count), ] self.comb += [ dram_fifo.sink.valid.eq((word_count == 0) & (word_count_d != 0) & load_fifo), dram_fifo.sink.data.eq(adc_data) ] fifo_size = Signal(32) self.sync += [ fifo_size.eq(self.fifo_size.storage), If(self.fifo_load.re & self.fifo_load.storage, fifo_counter.eq(0), load_fifo.eq(1)), If(load_fifo & adc_source.valid, self.fifo_full.status.eq(0), self.fifo_error.status.eq(~dram_fifo.dram_fifo.ctrl.writable), fifo_counter.eq(fifo_counter + 1)), If((fifo_counter == fifo_size - 1) & adc_source.valid, load_fifo.eq(0), self.fifo_full.status.eq(1)), ] # fifo --> stride converter self.submodules.stride_converter = sc = stream.Converter( dw, udp_port.dw) self.read_from_dram_fifo = read_from_dram_fifo = Signal() self.comb += [dram_fifo.source.connect(sc.sink)] self.receive_count = receive_count = Signal(24) self.sync += [ If(dram_fifo.source.valid & dram_fifo.source.ready, receive_count.eq(receive_count + 1)).Elif( read_from_dram_fifo == 0, receive_count.eq(0)) ] # --> udp fragmenter --> self.submodules.udp_fragmenter = udp_fragmenter = UDPFragmenter( udp_port.dw) self.sync += read_from_dram_fifo.eq(self.fifo_read.storage) self.comb += If( read_from_dram_fifo, # TODO: There is a bug somewhere in the converter, # its source.last somehow gets set, no idea why. That signal is of no real use # for the fragmenter anyways, so we live without it sc.source.connect(udp_fragmenter.sink, omit={'total_size', 'last'})) # TODO: 8 should be adcstream data width // 8 self.comb += udp_fragmenter.sink.length.eq( fifo_size << log2_int(adc_dw // 8)) self.comb += udp_fragmenter.source.connect(udp_port.sink) self.comb += [ # param udp_port.sink.src_port.eq(4321), udp_port.sink.dst_port.eq(self.dst_port.storage), udp_port.sink.ip_address.eq(self.dst_ip.storage), # udp_port.sink.ip_address.eq(convert_ip("192.168.88.101")), # payload udp_port.sink.error.eq(0) ]
def _get_sdram_phy_sequence(sdram_phy_settings): nphases = sdram_phy_settings.nphases cl = sdram_phy_settings.cl consts = {} cmds = { "PRECHARGE_ALL": "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS", "MODE_REGISTER": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS", "AUTO_REFRESH": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS", "UNRESET": "DFII_CONTROL_ODT|DFII_CONTROL_RESET_N", "CKE": "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N" } if sdram_phy_settings.memtype == "SDR": bl = sdram_phy_settings.nphases mr = log2_int(bl) + (cl << 4) reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif sdram_phy_settings.memtype == "DDR": bl = 2*sdram_phy_settings.nphases mr = log2_int(bl) + (cl << 4) emr = 0 reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif sdram_phy_settings.memtype == "LPDDR": bl = 2*sdram_phy_settings.nphases mr = log2_int(bl) + (cl << 4) emr = 0 reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif sdram_phy_settings.memtype == "DDR2": bl = 2*sdram_phy_settings.nphases wr = 2 mr = log2_int(bl) + (cl << 4) + (wr << 9) emr = 0 emr2 = 0 emr3 = 0 reset_dll = 1 << 8 ocd = 7 << 7 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200), ("Load Extended Mode Register / OCD Default", emr+ocd, 1, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0), ] elif sdram_phy_settings.memtype == "DDR3": bl = 2*sdram_phy_settings.nphases def format_mr0(bl, cl, wr, dll_reset): bl_to_mr0 = { 4: 0b10, 8: 0b00 } cl_to_mr0 = { 5: 0b0010, 6: 0b0100, 7: 0b0110, 8: 0b1000, 9: 0b1010, 10: 0b1100, 11: 0b1110, 12: 0b0001, 13: 0b0011, 14: 0b0101 } wr_to_mr0 = { 16: 0b000, 5: 0b001, 6: 0b010, 7: 0b011, 8: 0b100, 10: 0b101, 12: 0b110, 14: 0b111 } mr0 = bl_to_mr0[bl] mr0 |= (cl_to_mr0[cl] & 1) << 2 mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4 mr0 |= dll_reset << 8 mr0 |= wr_to_mr0[wr] << 9 return mr0 def format_mr1(output_drive_strength, rtt_nom): mr1 = ((output_drive_strength >> 0) & 1) << 1 mr1 |= ((output_drive_strength >> 1) & 1) << 5 mr1 |= ((rtt_nom >> 0) & 1) << 2 mr1 |= ((rtt_nom >> 1) & 1) << 6 mr1 |= ((rtt_nom >> 2) & 1) << 9 return mr1 def format_mr2(cwl, rtt_wr): mr2 = (cwl-5) << 3 mr2 |= rtt_wr << 9 return mr2 mr0 = format_mr0(bl, cl, 8, 1) # wr=8 FIXME: this should be ceiling(tWR/tCK) mr1 = format_mr1(1, 1) # Output Drive Strength RZQ/7 (34 ohm) / Rtt RZQ/4 (60 ohm) mr2 = format_mr2(sdram_phy_settings.cwl, 2) # Rtt(WR) RZQ/4 mr3 = 0 init_sequence = [ ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000), ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000), ("Load Mode Register 2", mr2, 2, cmds["MODE_REGISTER"], 0), ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0), ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200), ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200), ] # the value of MR1 needs to be modified during write leveling consts["DDR3_MR1"] = mr1 else: raise NotImplementedError("Unsupported memory type: "+sdram_phy_settings.memtype) return { "nphases": sdram_phy_settings.nphases, "rdphase": sdram_phy_settings.rdphase, "wrphase": sdram_phy_settings.wrphase, "consts": consts, "init_sequence": init_sequence }
def get_sdram_phy_header(sdram_phy_settings): r = "#ifndef __GENERATED_SDRAM_PHY_H\n#define __GENERATED_SDRAM_PHY_H\n" r += "#include <hw/common.h>\n#include <generated/csr.h>\n#include <hw/flags.h>\n\n" nphases = sdram_phy_settings.nphases r += "#define DFII_NPHASES "+str(nphases)+"\n\n" r += "static void cdelay(int i);\n" # commands_px functions for n in range(nphases): r += """ static void command_p{n}(int cmd) {{ dfii_pi{n}_command_write(cmd); dfii_pi{n}_command_issue_write(1); }}""".format(n=str(n)) r += "\n\n" # rd/wr access macros r += """ #define dfii_pird_address_write(X) dfii_pi{rdphase}_address_write(X) #define dfii_piwr_address_write(X) dfii_pi{wrphase}_address_write(X) #define dfii_pird_baddress_write(X) dfii_pi{rdphase}_baddress_write(X) #define dfii_piwr_baddress_write(X) dfii_pi{wrphase}_baddress_write(X) #define command_prd(X) command_p{rdphase}(X) #define command_pwr(X) command_p{wrphase}(X) """.format(rdphase=str(sdram_phy_settings.rdphase), wrphase=str(sdram_phy_settings.wrphase)) r += "\n" # # sdrrd/sdrwr functions utilities # r += "#define DFII_PIX_DATA_SIZE CSR_DFII_PI0_WRDATA_SIZE\n" dfii_pix_wrdata_addr = [] for n in range(nphases): dfii_pix_wrdata_addr.append("CSR_DFII_PI{n}_WRDATA_ADDR".format(n=n)) r += """ const unsigned int dfii_pix_wrdata_addr[{n}] = {{ {dfii_pix_wrdata_addr} }}; """.format(n=nphases, dfii_pix_wrdata_addr=",\n\t".join(dfii_pix_wrdata_addr)) dfii_pix_rddata_addr = [] for n in range(nphases): dfii_pix_rddata_addr.append("CSR_DFII_PI{n}_RDDATA_ADDR".format(n=n)) r += """ const unsigned int dfii_pix_rddata_addr[{n}] = {{ {dfii_pix_rddata_addr} }}; """.format(n=nphases, dfii_pix_rddata_addr=",\n\t".join(dfii_pix_rddata_addr)) r += "\n" # init sequence cmds = { "PRECHARGE_ALL": "DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS", "MODE_REGISTER": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS", "AUTO_REFRESH": "DFII_COMMAND_RAS|DFII_COMMAND_CAS|DFII_COMMAND_CS", "UNRESET": "DFII_CONTROL_ODT|DFII_CONTROL_RESET_N", "CKE": "DFII_CONTROL_CKE|DFII_CONTROL_ODT|DFII_CONTROL_RESET_N" } cl = sdram_phy_settings.cl if sdram_phy_settings.memtype == "SDR": bl = sdram_phy_settings.nphases mr = log2_int(bl) + (cl << 4) reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif sdram_phy_settings.memtype == "DDR": bl = 2*sdram_phy_settings.nphases mr = log2_int(bl) + (cl << 4) emr = 0 reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif sdram_phy_settings.memtype == "LPDDR": bl = 2*sdram_phy_settings.nphases mr = log2_int(bl) + (cl << 4) emr = 0 reset_dll = 1 << 8 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register", emr, 2, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200) ] elif sdram_phy_settings.memtype == "DDR2": bl = 2*sdram_phy_settings.nphases wr = 2 mr = log2_int(bl) + (cl << 4) + (wr << 9) emr = 0 emr2 = 0 emr3 = 0 reset_dll = 1 << 8 ocd = 7 << 7 init_sequence = [ ("Bring CKE high", 0x0000, 0, cmds["CKE"], 20000), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Load Extended Mode Register 3", emr3, 3, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register 2", emr2, 2, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register", emr, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register / Reset DLL, CL={0:d}, BL={1:d}".format(cl, bl), mr + reset_dll, 0, cmds["MODE_REGISTER"], 200), ("Precharge All", 0x0400, 0, cmds["PRECHARGE_ALL"], 0), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Auto Refresh", 0x0, 0, cmds["AUTO_REFRESH"], 4), ("Load Mode Register / CL={0:d}, BL={1:d}".format(cl, bl), mr, 0, cmds["MODE_REGISTER"], 200), ("Load Extended Mode Register / OCD Default", emr+ocd, 1, cmds["MODE_REGISTER"], 0), ("Load Extended Mode Register / OCD Exit", emr, 1, cmds["MODE_REGISTER"], 0), ] elif sdram_phy_settings.memtype == "DDR3": bl = 2*sdram_phy_settings.nphases def format_mr0(bl, cl, wr, dll_reset): bl_to_mr0 = { 4: 0b10, 8: 0b00 } cl_to_mr0 = { 5: 0b0010, 6: 0b0100, 7: 0b0110, 8: 0b1000, 9: 0b1010, 10: 0b1100, 11: 0b1110, 12: 0b0001, 13: 0b0011, 14: 0b0101 } wr_to_mr0 = { 16: 0b000, 5: 0b001, 6: 0b010, 7: 0b011, 8: 0b100, 10: 0b101, 12: 0b110, 14: 0b111 } mr0 = bl_to_mr0[bl] mr0 |= (cl_to_mr0[cl] & 1) << 2 mr0 |= ((cl_to_mr0[cl] >> 1) & 0b111) << 4 mr0 |= dll_reset << 8 mr0 |= wr_to_mr0[wr] << 9 return mr0 def format_mr1(output_drive_strength, rtt_nom): mr1 = ((output_drive_strength >> 0) & 1) << 1 mr1 |= ((output_drive_strength >> 1) & 1) << 5 mr1 |= ((rtt_nom >> 0) & 1) << 2 mr1 |= ((rtt_nom >> 1) & 1) << 6 mr1 |= ((rtt_nom >> 2) & 1) << 9 return mr1 def format_mr2(cwl, rtt_wr): mr2 = (cwl-5) << 3 mr2 |= rtt_wr << 9 return mr2 mr0 = format_mr0(bl, cl, 8, 1) # wr=8 FIXME: this should be ceiling(tWR/tCK) mr1 = format_mr1(1, 1) # Output Drive Strength RZQ/7 (34 ohm) / Rtt RZQ/4 (60 ohm) mr2 = format_mr2(sdram_phy_settings.cwl, 2) # Rtt(WR) RZQ/4 mr3 = 0 init_sequence = [ ("Release reset", 0x0000, 0, cmds["UNRESET"], 50000), ("Bring CKE high", 0x0000, 0, cmds["CKE"], 10000), ("Load Mode Register 2", mr2, 2, cmds["MODE_REGISTER"], 0), ("Load Mode Register 3", mr3, 3, cmds["MODE_REGISTER"], 0), ("Load Mode Register 1", mr1, 1, cmds["MODE_REGISTER"], 0), ("Load Mode Register 0, CL={0:d}, BL={1:d}".format(cl, bl), mr0, 0, cmds["MODE_REGISTER"], 200), ("ZQ Calibration", 0x0400, 0, "DFII_COMMAND_WE|DFII_COMMAND_CS", 200), ] # the value of MR1 needs to be modified during write leveling r += "#define DDR3_MR1 {}\n\n".format(mr1) else: raise NotImplementedError("Unsupported memory type: "+sdram_phy_settings.memtype) r += "static void init_sequence(void)\n{\n" for comment, a, ba, cmd, delay in init_sequence: r += "\t/* {0} */\n".format(comment) r += "\tdfii_pi0_address_write({0:#x});\n".format(a) r += "\tdfii_pi0_baddress_write({0:d});\n".format(ba) if cmd[:12] == "DFII_CONTROL": r += "\tdfii_control_write({0});\n".format(cmd) else: r += "\tcommand_p0({0});\n".format(cmd) if delay: r += "\tcdelay({0:d});\n".format(delay) r += "\n" r += "}\n" r += "#endif\n" return r