Skip to content

Commit fe7793d

Browse files
committed
targets/sipeed: Align GW5 DDR system clocks
GW5DDRPHY uses sys as the primitive PCLK and sys2x as FCLK. The PHY initialization sequence stops and restarts sys2x, but the GW5 targets generated sys from a separate PLL output. This did not preserve a deterministic PCLK/FCLK relationship across initialization. Generate only sys2x from the PLL when DDR3 is enabled, gate it with DHCE, and derive sys through a resettable divide-by-two CLKDIV. This matches the working GW2 targets and Gowin's GW5 DDR reference clock topology. Non-DDR configurations keep their direct PLL-generated sys clock.
1 parent 8bf5de7 commit fe7793d

3 files changed

Lines changed: 36 additions & 6 deletions

File tree

litex_boards/targets/sipeed_tang_console.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ def __init__(self, platform, sys_clk_freq,
7373
self.pll = pll = GW5APLL(devicename=platform.devicename, device=platform.device)
7474
self.comb += pll.reset.eq(~por_done | rst)
7575
pll.register_clkin(clk50, 50e6)
76-
pll.create_clkout(self.cd_sys, sys_clk_freq, with_reset=not with_ddr3)
76+
if with_ddr3:
77+
# Keep sys/sys2x phase-aligned across the PHY stop/reset sequence.
78+
pll.create_clkout(self.cd_sys2x_i, 2*sys_clk_freq)
79+
else:
80+
pll.create_clkout(self.cd_sys, sys_clk_freq)
7781

7882
# SDRAM clock
7983
if with_sdram:
@@ -88,13 +92,19 @@ def __init__(self, platform, sys_clk_freq,
8892

8993
# DDR3 clock
9094
if with_ddr3:
91-
pll.create_clkout(self.cd_sys2x_i, 2*sys_clk_freq)
9295
self.specials += [
9396
Instance("DHCE",
9497
i_CLKIN = self.cd_sys2x_i.clk,
9598
i_CEN = self.stop,
9699
o_CLKOUT = self.cd_sys2x.clk
97100
),
101+
Instance("CLKDIV",
102+
p_DIV_MODE = "2",
103+
i_CALIB = 0,
104+
i_HCLKIN = self.cd_sys2x.clk,
105+
i_RESETN = ~self.reset,
106+
o_CLKOUT = self.cd_sys.clk
107+
),
98108
AsyncResetSynchronizer(self.cd_sys, ~pll.locked | self.reset),
99109
]
100110
# Init clock domain

litex_boards/targets/sipeed_tang_mega_138k.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ def __init__(self, platform, sys_clk_freq, cpu_clk_freq=0,
8181
self.pll = pll = GW5APLL(devicename=platform.devicename, device=platform.device)
8282
self.comb += pll.reset.eq(~por_done | self.rst)
8383
pll.register_clkin(clk50, 50e6)
84-
pll.create_clkout(self.cd_sys, sys_clk_freq, with_reset=not with_ddr3)
84+
if with_ddr3:
85+
# Keep sys/sys2x phase-aligned across the PHY stop/reset sequence.
86+
pll.create_clkout(self.cd_sys2x_i, 2*sys_clk_freq)
87+
else:
88+
pll.create_clkout(self.cd_sys, sys_clk_freq)
8589
if cpu_clk_freq:
8690
pll.create_clkout(self.cd_cpu, cpu_clk_freq, with_reset=False)
8791
platform.toolchain.additional_cst_commands.append("INS_LOC \"PLL\" PLL_R[0]") # Magic incantation for Gowin-AE350 CPU :)
@@ -99,13 +103,19 @@ def __init__(self, platform, sys_clk_freq, cpu_clk_freq=0,
99103

100104
# DDR3 clock
101105
if with_ddr3:
102-
pll.create_clkout(self.cd_sys2x_i, 2*sys_clk_freq)
103106
self.specials += [
104107
Instance("DHCE",
105108
i_CLKIN = self.cd_sys2x_i.clk,
106109
i_CEN = self.stop,
107110
o_CLKOUT = self.cd_sys2x.clk
108111
),
112+
Instance("CLKDIV",
113+
p_DIV_MODE = "2",
114+
i_CALIB = 0,
115+
i_HCLKIN = self.cd_sys2x.clk,
116+
i_RESETN = ~self.reset,
117+
o_CLKOUT = self.cd_sys.clk
118+
),
109119
AsyncResetSynchronizer(self.cd_sys, ~pll.locked | self.reset),
110120
]
111121
# Init clock domain

litex_boards/targets/sipeed_tang_mega_138k_pro.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,11 @@ def __init__(self, platform, sys_clk_freq, cpu_clk_freq=0,
7676
self.pll = pll = GW5APLL(devicename=platform.devicename, device=platform.device)
7777
self.comb += pll.reset.eq(~por_done | rst)
7878
pll.register_clkin(clk50, 50e6)
79-
pll.create_clkout(self.cd_sys, sys_clk_freq, with_reset=not with_ddr3)
79+
if with_ddr3:
80+
# Keep sys/sys2x phase-aligned across the PHY stop/reset sequence.
81+
pll.create_clkout(self.cd_sys2x_i, 2*sys_clk_freq)
82+
else:
83+
pll.create_clkout(self.cd_sys, sys_clk_freq)
8084
if cpu_clk_freq:
8185
pll.create_clkout(self.cd_cpu, cpu_clk_freq, with_reset=False)
8286
platform.toolchain.additional_cst_commands.append("INS_LOC \"PLL\" PLL_R[0]") # Magic incantation for Gowin-AE350 CPU :)
@@ -94,13 +98,19 @@ def __init__(self, platform, sys_clk_freq, cpu_clk_freq=0,
9498

9599
# DDR3 clock
96100
if with_ddr3:
97-
pll.create_clkout(self.cd_sys2x_i, 2*sys_clk_freq)
98101
self.specials += [
99102
Instance("DHCE",
100103
i_CLKIN = self.cd_sys2x_i.clk,
101104
i_CEN = self.stop,
102105
o_CLKOUT = self.cd_sys2x.clk
103106
),
107+
Instance("CLKDIV",
108+
p_DIV_MODE = "2",
109+
i_CALIB = 0,
110+
i_HCLKIN = self.cd_sys2x.clk,
111+
i_RESETN = ~self.reset,
112+
o_CLKOUT = self.cd_sys.clk
113+
),
104114
AsyncResetSynchronizer(self.cd_sys, ~pll.locked | self.reset),
105115
]
106116
# Init clock domain

0 commit comments

Comments
 (0)