Skip to content

Commit 262b697

Browse files
committed
targets: add XCU1525 full DDR map mode
Add a --ddram-full-map option for SQRL XCU1525, using VexiiRiscv RV64 physical addressing and remapping non-main DDR windows around the Vexii high I/O region. Validated on SQRL XCU1525 with channels 0 and 1: Vivado 2024.1 timing met, bitstream loaded, and BIOS trained/memtested both DDR controllers via the regular UART.
1 parent 979b0c7 commit 262b697

1 file changed

Lines changed: 52 additions & 3 deletions

File tree

litex_boards/targets/sqrl_xcu1525.py

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from litex_boards.platforms import sqrl_xcu1525
1616

1717
from litex.soc.cores.clock import *
18-
from litex.soc.integration.soc import SoCIORegion
18+
from litex.soc.integration.soc import SoCIORegion, SoCRegion
1919
from litex.soc.integration.soc_core import *
2020
from litex.soc.integration.builder import *
2121
from litex.soc.cores.led import LedChaser
@@ -43,6 +43,11 @@
4343
}
4444
DDRAM_CSR_ORIGIN = 0x20000000
4545
DDRAM_DEBUG_ORIGIN = 0x20010000
46+
DDRAM_FULL_MAP_PHYSICAL_WIDTH = 38
47+
DDRAM_FULL_MAP_IO_REGIONS = {
48+
DDRAM_CSR_ORIGIN : 0x02000000,
49+
0xf0000000 : 0x10000000,
50+
}
4651

4752
def parse_qsfp_port(port):
4853
if port not in QSFP_PORTS:
@@ -105,6 +110,17 @@ def ddram_windows_overlap(origins, window_size, origin, size):
105110
for ddram_origin in origins.values()
106111
)
107112

113+
def remap_ddram_origins_around_vexii_io(origins, main_channel):
114+
remapped = {}
115+
high_origin = 0x1_0000_0000
116+
for channel in sorted(origins):
117+
origin = origins[channel]
118+
if channel != main_channel and origin >= 0xc0000000:
119+
origin = high_origin
120+
high_origin += DDRAM_CHANNEL_SIZE
121+
remapped[channel] = origin
122+
return remapped
123+
108124
# CRG ----------------------------------------------------------------------------------------------
109125

110126
class _CRG(LiteXModule):
@@ -137,6 +153,16 @@ def __init__(self, platform, sys_clk_freq, ddram_channel, with_qsfp=False):
137153
]
138154

139155
self.idelayctrl = USPIDELAYCTRL(cd_ref=self.cd_idelay, cd_sys=self.cd_sys)
156+
platform.add_platform_command(
157+
"set_false_path -quiet "
158+
"-to [get_cells -quiet -hierarchical -filter {{NAME =~ *idelayctrl*ic_reset_reg*}}]"
159+
)
160+
platform.add_platform_command(
161+
"set_false_path -quiet "
162+
"-to [get_pins -quiet -of_objects "
163+
"[get_cells -quiet -hierarchical -filter {{REF_NAME == IDELAYCTRL}}] "
164+
"-filter {{REF_PIN_NAME == RST}}]"
165+
)
140166

141167
# BaseSoC ------------------------------------------------------------------------------------------
142168

@@ -148,6 +174,7 @@ def __init__(self, sys_clk_freq=125e6, ddram_channel=0,
148174
pcie_lanes = 4,
149175
pcie_ndmas = 1,
150176
pcie_address_width = 32,
177+
ddram_full_map = False,
151178
with_pcie_dma_status = False,
152179
with_pcie_dma_monitor = False,
153180
with_sdram_bist = False,
@@ -169,8 +196,22 @@ def __init__(self, sys_clk_freq=125e6, ddram_channel=0,
169196
bus_address_width = kwargs.get("bus_address_width", 32)
170197
ddram_window_size = DDRAM_CHANNEL_SIZE
171198
ddram_origins = get_ddram_origins(ddram_channels, ddram_main_channel, ddram_window_size)
199+
is_vexiiriscv = kwargs.get("cpu_type", "vexriscv") == "vexiiriscv"
200+
if ddram_full_map and is_vexiiriscv:
201+
ddram_origins = remap_ddram_origins_around_vexii_io(ddram_origins, ddram_main_channel)
172202
ddram_end = ddram_window_end(ddram_origins, ddram_window_size)
173-
if ddram_end > 2**bus_address_width and bus_address_width <= 32:
203+
if ddram_full_map:
204+
if bus_address_width <= 32:
205+
kwargs["bus_address_width"] = 64
206+
bus_address_width = 64
207+
if ddram_end > 2**bus_address_width:
208+
kwargs["bus_address_width"] = 64
209+
if is_vexiiriscv:
210+
from litex.soc.cores.cpu.vexiiriscv.core import VexiiRiscv
211+
VexiiRiscv.set_physical_width(max(DDRAM_FULL_MAP_PHYSICAL_WIDTH, ddram_end.bit_length()))
212+
if VexiiRiscv.io_regions == {0x8000_0000: 0x8000_0000}:
213+
VexiiRiscv.io_regions = dict(DDRAM_FULL_MAP_IO_REGIONS)
214+
elif ddram_end > 2**bus_address_width and bus_address_width <= 32:
174215
ddram_window_size = DDRAM_32BIT_WINDOW_SIZE
175216
ddram_origins = get_ddram_origins(ddram_channels, ddram_main_channel, ddram_window_size)
176217
ddram_end = ddram_window_end(ddram_origins, ddram_window_size)
@@ -213,6 +254,11 @@ def __init__(self, sys_clk_freq=125e6, ddram_channel=0,
213254
is_main = channel == ddram_main_channel
214255
sdram_name = "sdram" if is_main else f"sdram{channel}"
215256
origin = ddram_origins[channel]
257+
cached = is_main if ddram_full_map else not (0x8000_0000 <= origin < 0x1_0000_0000)
258+
if ddram_full_map and not is_main:
259+
ddram_io_region = SoCRegion(origin=origin, size=ddram_window_size, cached=False)
260+
if not self.bus.check_region_is_io(ddram_io_region):
261+
self.bus.add_region(f"ddram{channel}_io", SoCIORegion(origin=origin, size=ddram_window_size))
216262
self.add_sdram(sdram_name,
217263
phy = phy,
218264
module = MT40A512M8(sys_clk_freq, "1:4"),
@@ -224,12 +270,13 @@ def __init__(self, sys_clk_freq=125e6, ddram_channel=0,
224270
phy_name = phy_name,
225271
ddrctrl_name = f"ddrctrl{channel}",
226272
with_bist = with_sdram_bist,
227-
cached = not (0x8000_0000 <= origin < 0x1_0000_0000),
273+
cached = cached,
228274
l2_cache_size = kwargs.get("l2_size", 8192)
229275
)
230276
self.add_constant("DDRAM_CHANNELS", len(ddram_channels))
231277
self.add_constant("DDRAM_MAIN_CHANNEL", ddram_main_channel)
232278
self.add_constant("DDRAM_WINDOW_SIZE", ddram_window_size)
279+
self.add_constant("DDRAM_FULL_MAP", int(ddram_full_map))
233280
# Workadound for Vivado 2018.2 DRC, can be ignored and probably fixed on newer Vivado versions.
234281
platform.add_platform_command("set_property SEVERITY {{Warning}} [get_drc_checks PDCN-2736]")
235282

@@ -337,6 +384,7 @@ def main():
337384
parser.add_target_argument("--sys-clk-freq", default=125e6, type=float, help="System clock frequency.")
338385
parser.add_target_argument("--ddram-channel", default=0, type=lambda x: int(x, 0), choices=range(4), help="Legacy single DDRAM channel selector.")
339386
parser.add_target_argument("--ddram-channels", default=None, help="DDRAM channels to map (comma/range list or all).")
387+
parser.add_target_argument("--ddram-full-map", action="store_true", help="Map selected DDRAM channels at their full native address windows.")
340388
parser.add_target_argument("--with-pcie", action="store_true", help="Enable PCIe support.")
341389
parser.add_target_argument("--pcie-lanes", default=4, type=int, choices=[2, 4, 8, 16], help="PCIe lane count.")
342390
parser.add_target_argument("--pcie-ndmas", default=1, type=int, help="Number of PCIe DMA channels.")
@@ -376,6 +424,7 @@ def main():
376424
soc = BaseSoC(
377425
sys_clk_freq = args.sys_clk_freq,
378426
ddram_channels = ddram_channels,
427+
ddram_full_map = args.ddram_full_map,
379428
with_pcie = args.with_pcie,
380429
pcie_lanes = args.pcie_lanes,
381430
pcie_ndmas = args.pcie_ndmas,

0 commit comments

Comments
 (0)