diff --git a/docs/boards_inventory.md b/docs/boards_inventory.md index a529365e1..3679efc5a 100644 --- a/docs/boards_inventory.md +++ b/docs/boards_inventory.md @@ -93,7 +93,7 @@ python3 .github/scripts/generate_board_inventory.py --write | `icepi_zero` | icepi_zero | trellis | `50000000.0` | SDCard, SPI SDCard, SPI Flash, Video Terminal, Video Framebuffer | included | | `intergalaktik_ulx5m_gs` | intergalaktik_ulx5m_gs | colognechip | `20000000.0` | SDCard, SPI SDCard, SPI Flash | included | | `isx_im1283` | isx_im1283 | vivado | `80000000.0` | SDCard, SPI SDCard | included | -| `jungle_electronics_fireant` | jungle_electronics_fireant | efinity | `33333000.0` | - | toolchain-gated: Require Efinity toolchain. | +| `jungle_electronics_fireant` | jungle_electronics_fireant | efinity | `33330000.0` | - | toolchain-gated: Require Efinity toolchain. | | `kosagi_fomu` | kosagi_fomu_pvt | icestorm | `12000000.0` | - | included | | `kosagi_netv2` | kosagi_netv2 | vivado | `100000000.0` | Ethernet, SDCard, SPI SDCard, PCIe | included | | `krtkl_snickerdoodle` | krtkl_snickerdoodle | vivado | `100000000.0` | - | included | diff --git a/litex_boards/platforms/efinix_t120_f576_dev_kit.py b/litex_boards/platforms/efinix_t120_f576_dev_kit.py index c44e571e4..f4465ee96 100644 --- a/litex_boards/platforms/efinix_t120_f576_dev_kit.py +++ b/litex_boards/platforms/efinix_t120_f576_dev_kit.py @@ -179,6 +179,48 @@ def i2c_pmod_io(pmod): ), ] +# DDR Configuration -------------------------------------------------------------------------------- + +ddr_config = { + "preset_id" : 173, + "memory_type" : "LPDDR3", + "controller_width" : 32, + "dram_width" : 32, + "memory_density" : "8G", + "speedbin" : 800, + "fpga_config" : { + "FPGA_ITERM" : "120", + "FPGA_OTERM" : "34", + }, + "memory_config" : { + "RTT_NOM" : "RZQ/2", + "MEM_OTERM" : "40", + "CL" : "RL=6/WL=3", + }, + "memory_timing" : { + "tRAS" : 42.0, + "tRC" : 60.0, + "tRP" : 18.0, + "tRCD" : 18.0, + "tREFI" : 3.9, + "tRFC" : 210.0, + "tRTP" : 10.0, + "tWTR" : 10.0, + "tRRD" : 10.0, + "tFAW" : 50.0, + }, + "control_config" : { + "AMAP" : "ROW-COL_HIGH-BANK-COL_LOW", + "EN_AUTO_PWR_DN" : "Off", + "EN_AUTO_SELF_REF" : "No", + }, + "gate_delay_config" : { + "EN_DLY_OVR" : "No", + "GATE_C_DLY" : 3, + "GATE_F_DLY" : 0, + }, +} + # Platform ----------------------------------------------------------------------------------------- class Platform(EfinixPlatform): @@ -188,6 +230,8 @@ class Platform(EfinixPlatform): def __init__(self, toolchain="efinity"): EfinixPlatform.__init__(self, "T120F576I4", _io, _connectors, iobank_info=_bank_info, toolchain=toolchain) + self.ddr_config = ddr_config + self.ddr_size = 0x1000_0000 # 256MB per target port. def create_programmer(self): return EfinixProgrammer() diff --git a/litex_boards/targets/efinix_t120_f576_dev_kit.py b/litex_boards/targets/efinix_t120_f576_dev_kit.py index 0625e0838..4aef44409 100755 --- a/litex_boards/targets/efinix_t120_f576_dev_kit.py +++ b/litex_boards/targets/efinix_t120_f576_dev_kit.py @@ -17,11 +17,10 @@ from litex.build.generic_platform import Pins, Subsignal, IOStandard from litex.soc.cores.clock import * +from litex.soc.cores.led import LedChaser +from litex.soc.cores.ram.efinix_ddr import EfinixTrionDDR, add_efinix_trion_ddr from litex.soc.integration.soc import * -from litex.soc.integration.soc import SoCRegion from litex.soc.integration.builder import * -from litex.soc.cores.led import LedChaser -from litex.soc.interconnect import axi from liteeth.phy.trionrgmii import LiteEthPHYRGMII @@ -52,6 +51,18 @@ def __init__(self, platform, sys_clk_freq): pll.register_clkin(clk40, platform.default_clk_freq) pll.create_clkout(self.cd_sys, sys_clk_freq, with_reset=True, name="axi_clk") + +class _CRG_DDR(LiteXModule): + def __init__(self, platform): + clk50 = platform.request("dram_pll_refclk") + rst_n = platform.request("user_btn_n", 1) + + # PLL. + self.pll = pll = TRIONPLL(platform) + self.comb += pll.reset.eq(~rst_n) + pll.register_clkin(clk50, 50e6) + pll.create_clkout(None, 400e6) + # BaseSoC ------------------------------------------------------------------------------------------ class BaseSoC(SoCCore): @@ -80,6 +91,12 @@ def __init__(self, sys_clk_freq=75e6, # SoCCore ---------------------------------------------------------------------------------- SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on Efinix Trion T120 BGA576 Dev Kit", **kwargs) + # LPDDR3 SDRAM ----------------------------------------------------------------------------- + if not self.integrated_main_ram_size: + self.ddr_crg = _CRG_DDR(platform) + self.ddr = EfinixTrionDDR(platform=platform, **platform.ddr_config) + add_efinix_trion_ddr(self, self.ddr, size=platform.ddr_size) + # SPI Flash -------------------------------------------------------------------------------- if with_spi_flash: from litespi.modules import W25Q128JV @@ -92,7 +109,7 @@ def __init__(self, sys_clk_freq=75e6, pads = platform.request_all("user_led"), sys_clk_freq = sys_clk_freq) - # I2C --------------------------------------------------------------------------------------- + # I2C -------------------------------------------------------------------------------------- if with_i2c: from litex.soc.cores.bitbang import I2CMaster platform.add_extension(efinix_t120_f576_dev_kit.i2c_pmod_io("pmod_a")) @@ -144,241 +161,6 @@ def eth_lan8720_rmii_pmod_io(pmod): if with_ethernet: self.add_ethernet(phy=self.ethphy, dynamic_ip=eth_dynamic_ip, local_ip=eth_ip, remote_ip=remote_ip, software_debug=False) - # LPDDR3 SDRAM ----------------------------------------------------------------------------- - if not self.integrated_main_ram_size: - # DRAM / PLL Blocks. - # ------------------ - dram_pll_refclk = platform.request("dram_pll_refclk") - platform.toolchain.excluded_ios.append(dram_pll_refclk) - self.platform.toolchain.additional_sdc_commands.append(f"create_clock -period {1e9/50e6} dram_pll_refclk") - - from litex.build.efinix import InterfaceWriterBlock, InterfaceWriterXMLBlock - import xml.etree.ElementTree as et - - class PLLDRAMBlock(InterfaceWriterBlock): - @staticmethod - def generate(): - return """ -design.create_block("dram_pll", block_type="PLL") -design.set_property("dram_pll", {"REFCLK_FREQ":"50.0"}, block_type="PLL") -design.gen_pll_ref_clock("dram_pll", pll_res="PLL_BR0", refclk_src="EXTERNAL", refclk_name="dram_pll_clkin", ext_refclk_no="0") -design.set_property("dram_pll","LOCKED_PIN","dram_pll_locked", block_type="PLL") -design.set_property("dram_pll","RSTN_PIN","dram_pll_rst_n", block_type="PLL") -design.set_property("dram_pll", {"CLKOUT0_PIN" : "dram_pll_CLKOUT0"}, block_type="PLL") -design.set_property("dram_pll","CLKOUT0_PHASE","0","PLL") -calc_result = design.auto_calc_pll_clock("dram_pll", {"CLKOUT0_FREQ": "400.0"}) -""" - platform.toolchain.ifacewriter.blocks.append(PLLDRAMBlock()) - - class DRAMXMLBlock(InterfaceWriterXMLBlock): - @staticmethod - def generate(root, namespaces): - # CHECKME: Switch to DDRDesignService? - ddr_info = root.find("efxpt:ddr_info", namespaces) - - ddr = et.SubElement(ddr_info, "efxpt:ddr", - name = "ddr_inst1", - ddr_def = "DDR_0", - cs_preset_id = "173", - cs_mem_type = "LPDDR3", - cs_ctrl_width = "x32", - cs_dram_width = "x32", - cs_dram_density = "8G", - cs_speedbin = "800", - target0_enable = "true", - target1_enable = "true", - ctrl_type = "none" - ) - - ddr_clk_name = self.crg.cd_sys.clk.name_override # FIXME: can't know this information otherwise - - gen_pin_target0 = et.SubElement(ddr, "efxpt:gen_pin_target0") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_wdata", type_name=f"WDATA_0", is_bus="true") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_wready", type_name=f"WREADY_0", is_bus="false") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_wid", type_name=f"WID_0", is_bus="true") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_bready", type_name=f"BREADY_0", is_bus="false") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_rdata", type_name=f"RDATA_0", is_bus="true") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_aid", type_name=f"AID_0", is_bus="true") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_bvalid", type_name=f"BVALID_0", is_bus="false") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_rlast", type_name=f"RLAST_0", is_bus="false") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_bid", type_name=f"BID_0", is_bus="true") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_asize", type_name=f"ASIZE_0", is_bus="true") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_atype", type_name=f"ATYPE_0", is_bus="false") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_aburst", type_name=f"ABURST_0", is_bus="true") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_wvalid", type_name=f"WVALID_0", is_bus="false") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_wlast", type_name=f"WLAST_0", is_bus="false") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_aaddr", type_name=f"AADDR_0", is_bus="true") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_rid", type_name=f"RID_0", is_bus="true") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_avalid", type_name=f"AVALID_0", is_bus="false") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_rvalid", type_name=f"RVALID_0", is_bus="false") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_alock", type_name=f"ALOCK_0", is_bus="true") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_rready", type_name=f"RREADY_0", is_bus="false") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_rresp", type_name=f"RRESP_0", is_bus="true") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_wstrb", type_name=f"WSTRB_0", is_bus="true") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_aready", type_name=f"AREADY_0", is_bus="false") - et.SubElement(gen_pin_target0, "efxpt:pin", name="axi0_alen", type_name=f"ALEN_0", is_bus="true") - et.SubElement(gen_pin_target0, "efxpt:pin", name=ddr_clk_name, type_name=f"ACLK_0", is_bus="false", is_clk="true", is_clk_invert="false") - - gen_pin_target1 = et.SubElement(ddr, "efxpt:gen_pin_target1") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_wdata", type_name=f"WDATA_1", is_bus="true") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_wready", type_name=f"WREADY_1", is_bus="false") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_wid", type_name=f"WID_1", is_bus="true") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_bready", type_name=f"BREADY_1", is_bus="false") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_rdata", type_name=f"RDATA_1", is_bus="true") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_aid", type_name=f"AID_1", is_bus="true") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_bvalid", type_name=f"BVALID_1", is_bus="false") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_rlast", type_name=f"RLAST_1", is_bus="false") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_bid", type_name=f"BID_1", is_bus="true") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_asize", type_name=f"ASIZE_1", is_bus="true") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_atype", type_name=f"ATYPE_1", is_bus="false") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_aburst", type_name=f"ABURST_1", is_bus="true") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_wvalid", type_name=f"WVALID_1", is_bus="false") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_wlast", type_name=f"WLAST_1", is_bus="false") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_aaddr", type_name=f"AADDR_1", is_bus="true") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_rid", type_name=f"RID_1", is_bus="true") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_avalid", type_name=f"AVALID_1", is_bus="false") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_rvalid", type_name=f"RVALID_1", is_bus="false") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_alock", type_name=f"ALOCK_1", is_bus="true") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_rready", type_name=f"RREADY_1", is_bus="false") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_rresp", type_name=f"RRESP_1", is_bus="true") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_wstrb", type_name=f"WSTRB_1", is_bus="true") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_aready", type_name=f"AREADY_1", is_bus="false") - et.SubElement(gen_pin_target1, "efxpt:pin", name="axi1_alen", type_name=f"ALEN_1", is_bus="true") - et.SubElement(gen_pin_target1, "efxpt:pin", name=ddr_clk_name, type_name=f"ACLK_1", is_bus="false", is_clk="true", is_clk_invert="false") - - gen_pin_config = et.SubElement(ddr, "efxpt:gen_pin_config") - et.SubElement(gen_pin_config, "efxpt:pin", name="", type_name="CFG_SEQ_RST", is_bus="false") - et.SubElement(gen_pin_config, "efxpt:pin", name="", type_name="CFG_SCL_IN", is_bus="false") - et.SubElement(gen_pin_config, "efxpt:pin", name="", type_name="CFG_SEQ_START", is_bus="false") - et.SubElement(gen_pin_config, "efxpt:pin", name="", type_name="RSTN", is_bus="false") - et.SubElement(gen_pin_config, "efxpt:pin", name="", type_name="CFG_SDA_IN", is_bus="false") - et.SubElement(gen_pin_config, "efxpt:pin", name="", type_name="CFG_SDA_OEN", is_bus="false") - - cs_fpga = et.SubElement(ddr, "efxpt:cs_fpga") - et.SubElement(cs_fpga, "efxpt:param", name="FPGA_ITERM", value="120", value_type="str") - et.SubElement(cs_fpga, "efxpt:param", name="FPGA_OTERM", value="34", value_type="str") - - cs_memory = et.SubElement(ddr, "efxpt:cs_memory") - et.SubElement(cs_memory, "efxpt:param", name="RTT_NOM", value="RZQ/2", value_type="str") - et.SubElement(cs_memory, "efxpt:param", name="MEM_OTERM", value="40", value_type="str") - et.SubElement(cs_memory, "efxpt:param", name="CL", value="RL=6/WL=3", value_type="str") - - timing = et.SubElement(ddr, "efxpt:cs_memory_timing") - et.SubElement(timing, "efxpt:param", name="tRAS", value="42.000", value_type="float") - et.SubElement(timing, "efxpt:param", name="tRC", value="60.000", value_type="float") - et.SubElement(timing, "efxpt:param", name="tRP", value="18.000", value_type="float") - et.SubElement(timing, "efxpt:param", name="tRCD", value="18.000", value_type="float") - et.SubElement(timing, "efxpt:param", name="tREFI", value="3.900", value_type="float") - et.SubElement(timing, "efxpt:param", name="tRFC", value="210.000", value_type="float") - et.SubElement(timing, "efxpt:param", name="tRTP", value="10.000", value_type="float") - et.SubElement(timing, "efxpt:param", name="tWTR", value="10.000", value_type="float") - et.SubElement(timing, "efxpt:param", name="tRRD", value="10.000", value_type="float") - et.SubElement(timing, "efxpt:param", name="tFAW", value="50.000", value_type="float") - - cs_control = et.SubElement(ddr, "efxpt:cs_control") - et.SubElement(cs_control, "efxpt:param", name="AMAP", value="ROW-COL_HIGH-BANK-COL_LOW", value_type="str") - et.SubElement(cs_control, "efxpt:param", name="EN_AUTO_PWR_DN", value="Off", value_type="str") - et.SubElement(cs_control, "efxpt:param", name="EN_AUTO_SELF_REF", value="No", value_type="str") - - cs_gate_delay = et.SubElement(ddr, "efxpt:cs_gate_delay") - et.SubElement(cs_gate_delay, "efxpt:param", name="EN_DLY_OVR", value="No", value_type="str") - et.SubElement(cs_gate_delay, "efxpt:param", name="GATE_C_DLY", value="3", value_type="int") - et.SubElement(cs_gate_delay, "efxpt:param", name="GATE_F_DLY", value="0", value_type="int") - - platform.toolchain.ifacewriter.xml_blocks.append(DRAMXMLBlock()) - - # DRAM Rst. - # --------- - dram_pll_rst_n = platform.add_iface_io("dram_pll_rst_n") - self.comb += dram_pll_rst_n.eq(platform.request("user_btn_n", 1)) - - # DRAM AXI-Ports. - # -------------- - for n, data_width in { - 0: 256, # target0: 256-bit. - 1: 128, # target1: 128-bit - }.items(): - axi_port = axi.AXIInterface(data_width=data_width, address_width=28, id_width=8) # 256MB. - ios = [(f"axi{n}", 0, - Subsignal("wdata", Pins(data_width)), - Subsignal("wready", Pins(1)), - Subsignal("wid", Pins(8)), - Subsignal("bready", Pins(1)), - Subsignal("rdata", Pins(data_width)), - Subsignal("aid", Pins(8)), - Subsignal("bvalid", Pins(1)), - Subsignal("rlast", Pins(1)), - Subsignal("bid", Pins(8)), - Subsignal("asize", Pins(3)), - Subsignal("atype", Pins(1)), - Subsignal("aburst", Pins(2)), - Subsignal("wvalid", Pins(1)), - Subsignal("aaddr", Pins(32)), - Subsignal("rid", Pins(8)), - Subsignal("avalid", Pins(1)), - Subsignal("rvalid", Pins(1)), - Subsignal("alock", Pins(2)), - Subsignal("rready", Pins(1)), - Subsignal("rresp", Pins(2)), - Subsignal("wstrb", Pins(data_width//8)), - Subsignal("aready", Pins(1)), - Subsignal("alen", Pins(8)), - Subsignal("wlast", Pins(1)), - )] - io = platform.add_iface_ios(ios) - rw_n = axi_port.ar.valid - self.comb += [ - # Pseudo AW/AR Channels. - io.atype.eq(~rw_n), - io.aaddr.eq( Mux(rw_n, axi_port.ar.addr, axi_port.aw.addr)), - io.aid.eq( Mux(rw_n, axi_port.ar.id, axi_port.aw.id)), - io.alen.eq( Mux(rw_n, axi_port.ar.len, axi_port.aw.len)), - io.asize.eq( Mux(rw_n, axi_port.ar.size, axi_port.aw.size)), - io.aburst.eq( Mux(rw_n, axi_port.ar.burst, axi_port.aw.burst)), - io.alock.eq( Mux(rw_n, axi_port.ar.lock, axi_port.aw.lock)), - io.avalid.eq( Mux(rw_n, axi_port.ar.valid, axi_port.aw.valid)), - axi_port.aw.ready.eq(~rw_n & io.aready), - axi_port.ar.ready.eq( rw_n & io.aready), - - # R Channel. - axi_port.r.id.eq(io.rid), - axi_port.r.data.eq(io.rdata), - axi_port.r.last.eq(io.rlast), - axi_port.r.resp.eq(io.rresp), - axi_port.r.valid.eq(io.rvalid), - io.rready.eq(axi_port.r.ready), - - # W Channel. - io.wid.eq(axi_port.w.id), - io.wstrb.eq(axi_port.w.strb), - io.wdata.eq(axi_port.w.data), - io.wlast.eq(axi_port.w.last), - io.wvalid.eq(axi_port.w.valid), - axi_port.w.ready.eq(io.wready), - - # B Channel. - axi_port.b.id.eq(io.bid), - axi_port.b.valid.eq(io.bvalid), - io.bready.eq(axi_port.b.ready), - ] - - # Connect AXI interface to the main bus of the SoC. - axi_lite_port = axi.AXILiteInterface(data_width=data_width, address_width=28) - self.submodules += axi.AXILite2AXI(axi_lite_port, axi_port) - self.bus.add_slave( - f"target{n}", - axi_lite_port, - SoCRegion(origin=0x4000_0000 + 0x1000_0000*n, size=0x1000_0000), # 256MB. - strip_origin=True, - ) - - # Use DRAM's target0 port as Main Ram ----------------------------------------------------- - self.bus.add_region("main_ram", SoCRegion( - origin = 0x4000_0000, - size = 0x1000_0000, # 256MB. - linker = True) - ) - # Build -------------------------------------------------------------------------------------------- def main():