Skip to content

Commit 54eb65a

Browse files
authored
add QMTech Cyclone10 Starter Kit support - 10CL080 (#683)
1 parent 9630096 commit 54eb65a

2 files changed

Lines changed: 367 additions & 0 deletions

File tree

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
#
2+
# This file is part of LiteX-Boards.
3+
#
4+
# Copyright (c) 2025 Denis Bodor <lefinnois@lefinnois.net>
5+
# Copyright (c) 2021 Hans Baier <hansfbaier@gmail.com>
6+
# SPDX-License-Identifier: BSD-2-Clause
7+
8+
from litex.build.generic_platform import *
9+
from litex.build.altera import AlteraPlatform
10+
from litex.build.altera.programmer import USBBlaster
11+
12+
# IOs ----------------------------------------------------------------------------------------------
13+
14+
_io = [
15+
# Clk
16+
("clk50", 0, Pins("G1"), IOStandard("3.3-V LVTTL")),
17+
18+
# fitted LEDs, active low
19+
("user_led", 0, Pins("V10"), IOStandard("3.3-V LVTTL")), # D1
20+
("user_led", 1, Pins("U9"), IOStandard("3.3-V LVTTL")), # D2
21+
("user_led", 2, Pins("V9"), IOStandard("3.3-V LVTTL")), # D3
22+
("user_led", 3, Pins("V8"), IOStandard("3.3-V LVTTL")), # D4
23+
("user_led", 4, Pins("V5"), IOStandard("3.3-V LVTTL")), # D5
24+
("user_led", 5, Pins("Y4"), IOStandard("3.3-V LVTTL")), # D6
25+
26+
# 7-segments display
27+
("seven_seg_ctl", 0,
28+
Subsignal("dig", Pins("U11 V16 AA18")),
29+
Subsignal("segments", Pins("W14 AB19 AB18 V13 U12 V15 AA19 U14")), # A B C D E F G dot
30+
IOStandard("3.3-V LVTTL")
31+
),
32+
33+
# Button
34+
("key", 0, Pins("P4"), IOStandard("3.3-V LVTTL")),
35+
("key", 1, Pins("P3"), IOStandard("3.3-V LVTTL")),
36+
37+
("serial", 0,
38+
# Onboard CH340N
39+
Subsignal("tx", Pins("AA21"), IOStandard("3.3-V LVTTL")),
40+
Subsignal("rx", Pins("AA22"), IOStandard("3.3-V LVTTL"))
41+
),
42+
43+
# SPIFlash (W25Q128)
44+
("spiflash", 0,
45+
Subsignal("cs_n", Pins("E2")),
46+
Subsignal("clk", Pins("K2")),
47+
Subsignal("mosi", Pins("D1")),
48+
Subsignal("miso", Pins("K1")),
49+
IOStandard("3.3-V LVTTL"),
50+
),
51+
52+
# SDR SDRAM
53+
("sdram_clock", 0, Pins("W8"), IOStandard("3.3-V LVTTL")),
54+
("sdram", 0,
55+
Subsignal("a", Pins(
56+
"V2 V1 U2 U1 T4 T5 V3 Y3",
57+
"V4 W6 W1 Y6 W7")),
58+
Subsignal("ba", Pins("Y1 W2")),
59+
Subsignal("cs_n", Pins("Y2")),
60+
Subsignal("cke", Pins("Y7")),
61+
Subsignal("ras_n", Pins("AA3")),
62+
Subsignal("cas_n", Pins("AB3")),
63+
Subsignal("we_n", Pins("AA4")),
64+
Subsignal("dq", Pins(
65+
"AB9 AA9 AB8 AA8 AB7 AA7 AB5 AA5",
66+
"W10 Y10 V11 V12 Y13 W13 V14 W15"),
67+
Misc("FAST_OUTPUT_ENABLE_REGISTER ON"),
68+
Misc("FAST_INPUT_REGISTER ON")),
69+
Subsignal("dm", Pins("AB4 Y8")),
70+
Misc("CURRENT_STRENGTH_NEW \"MAXIMUM CURRENT\""),
71+
Misc("FAST_OUTPUT_REGISTER ON"),
72+
Misc("ALLOW_SYNCH_CTRL_USAGE OFF"),
73+
IOStandard("3.3-V LVTTL")
74+
),
75+
76+
# SD card
77+
("sdcard", 0,
78+
Subsignal("data", Pins(f"U19 U20 Y17 W17")),
79+
Subsignal("cmd", Pins(f"W19")),
80+
Subsignal("clk", Pins(f"W20")),
81+
Subsignal("cd", Pins(f"T18")),
82+
Misc("FAST_OUTPUT_REGISTER ON"),
83+
IOStandard("3.3-V LVTTL"),
84+
),
85+
("spisdcard", 0,
86+
Subsignal("clk", Pins("W20")),
87+
Subsignal("mosi", Pins("W19"), Misc("WEAK_PULL_UP_RESISTOR ON")),
88+
Subsignal("cs_n", Pins("W17"), Misc("WEAK_PULL_UP_RESISTOR ON")),
89+
Subsignal("miso", Pins("U19"), Misc("WEAK_PULL_UP_RESISTOR ON")),
90+
IOStandard("3.3-V LVTTL"),
91+
),
92+
93+
# Ethernet RTL8211EG
94+
("eth_clocks", 0,
95+
Subsignal("tx", Pins("U21")),
96+
Subsignal("gtx", Pins("J22")),
97+
Subsignal("rx", Pins("D22")),
98+
IOStandard("3.3-V LVTTL")
99+
),
100+
("eth", 0,
101+
Subsignal("rst_n", Pins("P21")),
102+
Subsignal("mdio", Pins("Y22")),
103+
Subsignal("mdc", Pins("Y21")),
104+
Subsignal("rx_dv", Pins("B21")),
105+
Subsignal("rx_er", Pins("H21")),
106+
Subsignal("rx_data", Pins("B22 C21 C22 D21 E21 E22 F21 F22")),
107+
Subsignal("tx_en", Pins("M21")),
108+
Subsignal("tx_er", Pins("W22")),
109+
Subsignal("tx_data", Pins("M22 P22 R21 R22 U22 V21 V22 W21")),
110+
Subsignal("col", Pins("H22")),
111+
Subsignal("crs", Pins("J21")),
112+
IOStandard("3.3-V LVTTL")
113+
),
114+
115+
# HDMI out
116+
("hdmi_out", 0,
117+
Subsignal("clk_p", Pins("AA14")),
118+
Subsignal("clk_n", Pins("AB14")),
119+
Subsignal("data0_p", Pins("AA15")),
120+
Subsignal("data0_n", Pins("AB15")),
121+
Subsignal("data1_p", Pins("AA16")),
122+
Subsignal("data1_n", Pins("AB16")),
123+
Subsignal("data2_p", Pins("AA20")),
124+
Subsignal("data2_n", Pins("AB20")),
125+
Subsignal("scl", Pins("AB13")),
126+
Subsignal("sda", Pins("AA10")),
127+
Subsignal("hdp", Pins("AB10")),
128+
Subsignal("cec", Pins("AA13")),
129+
IOStandard("3.3-V LVTTL")
130+
),
131+
]
132+
133+
_connectors = [
134+
("J12", {
135+
1: "B1", 2: "B2",
136+
3: "B3", 4: "A3",
137+
5: "B4", 6: "A4",
138+
7: "B5", 8: "A5",
139+
9: "B6", 10: "A6",
140+
# 11: VIN_5V, 12: GND,
141+
13: "A7", 14: "B7",
142+
15: "A8", 16: "B8",
143+
17: "A9", 18: "B9",
144+
19: "A10", 20: "B10",
145+
21: "D15", 22: "C15",
146+
23: "B13", 24: "A13",
147+
25: "B14", 26: "A14",
148+
27: "B15", 28: "A15",
149+
# 29: 3V3, 30: GND,
150+
31: "B16", 32: "A16",
151+
33: "B17", 34: "A17",
152+
35: "B18", 36: "A18",
153+
37: "B19", 38: "A19",
154+
39: "B20", 40: "A20",
155+
}),
156+
157+
("J13", {
158+
1: "F10", 2: "D10",
159+
3: "F11", 4: "E11",
160+
5: "E13", 6: "E12",
161+
7: "D13", 8: "C13",
162+
9: "C10", 10: "E14",
163+
# 11: VIN_5V, 12: GND,
164+
13: "E15", 14: "E16",
165+
15: "C17", 16: "D17",
166+
17: "F17", 18: "C19",
167+
19: "C20", 20: "D19",
168+
21: "H17", 22: "D20",
169+
23: "F19", 24: "F20",
170+
25: "L22", 26: "L21",
171+
27: "M19", 28: "M20",
172+
# 29: 3V3, 30: GND,
173+
31: "N19", 32: "N20",
174+
33: "N18", 34: "P20",
175+
35: "H19", 36: "H18",
176+
37: "J18", 38: "H20",
177+
39: "K19", 40: "K18",
178+
}),
179+
180+
("JP1", {
181+
# 1: 3V3, 2: GND,
182+
3: "C8", 4: "E9", # with 4K7 pullup both
183+
5: "E7", 6: "C7",
184+
7: "E1", 8: "E6",
185+
9: "F1", 10: "F2",
186+
11: "C4", 12: "E5",
187+
13: "D2", 14: "C3",
188+
15: "G4", 16: "E4",
189+
17: "G3", 18: "E3",
190+
}),
191+
192+
("J10", {
193+
1: "J1", 2: "J2",
194+
3: "H1", 4: "H2",
195+
5: "P5", 6: "R5",
196+
7: "M5", 8: "N5",
197+
# 9: GND, 10: GND,
198+
# 11: 3V3, 12: 3V3,
199+
}),
200+
201+
("J11", {
202+
1: "R2", 2: "R1",
203+
3: "P2", 4: "P1",
204+
5: "N2", 6: "N1",
205+
7: "M2", 8: "M1",
206+
# 9: GND, 10: GND,
207+
# 11: 3V3, 12: 3V3,
208+
}),
209+
]
210+
211+
# Platform -----------------------------------------------------------------------------------------
212+
213+
class Platform(AlteraPlatform):
214+
default_clk_name = "clk50"
215+
default_clk_period = 1e9/50e6
216+
217+
def __init__(self, toolchain="quartus", with_core_resources=True):
218+
device = "10CL080YU484C8G"
219+
io = _io
220+
connectors = _connectors
221+
222+
AlteraPlatform.__init__(self, device, io, connectors, toolchain=toolchain)
223+
224+
# Generate PLL clock in STA
225+
self.toolchain.additional_sdc_commands.append("derive_pll_clocks")
226+
# Calculates clock uncertainties
227+
self.toolchain.additional_sdc_commands.append("derive_clock_uncertainty")
228+
229+
def create_programmer(self):
230+
return USBBlaster()
231+
232+
def do_finalize(self, fragment):
233+
AlteraPlatform.do_finalize(self, fragment)
234+
self.add_period_constraint(self.lookup_request("clk50", loose=True), 1e9/50e6)
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#!/usr/bin/env python3
2+
3+
#
4+
# This file is part of LiteX-Boards.
5+
#
6+
# Copyright (c) 2025 Denis Bodor <lefinnois@lefinnois.net>
7+
# Copyright (c) 2021 Hans Baier <hansfbaier@gmail.com>
8+
# SPDX-License-Identifier: BSD-2-Clause
9+
10+
from migen import *
11+
from migen.genlib.resetsync import AsyncResetSynchronizer
12+
13+
from litex.gen import *
14+
15+
from litex.build.io import DDROutput
16+
17+
from litex_boards.platforms import qmtech_cyclone10_starterkit
18+
19+
from litex.soc.cores.clock import Cyclone10LPPLL
20+
from litex.soc.integration.soc_core import *
21+
from litex.soc.integration.builder import *
22+
from litex.soc.cores.led import LedChaser
23+
24+
from litedram.modules import W9825G6KH6
25+
from litedram.phy import GENSDRPHY, HalfRateGENSDRPHY
26+
27+
# RTL8211EG is RGMII/GMII - This is not compatible with Cyclone10 for now
28+
#from liteeth.phy.mii import LiteEthPHYRGMII
29+
30+
# CRG ----------------------------------------------------------------------------------------------
31+
32+
class _CRG(LiteXModule):
33+
def __init__(self, platform, sys_clk_freq, sdram_rate="1:1"):
34+
self.rst = Signal()
35+
self.cd_sys = ClockDomain()
36+
37+
if sdram_rate == "1:2":
38+
self.cd_sys2x = ClockDomain()
39+
self.cd_sys2x_ps = ClockDomain()
40+
else:
41+
self.cd_sys_ps = ClockDomain()
42+
43+
# # #
44+
45+
# Clk / Rst
46+
clk50 = platform.request("clk50")
47+
48+
# PLL
49+
self.pll = pll = Cyclone10LPPLL(speedgrade="-C8")
50+
self.comb += pll.reset.eq(self.rst)
51+
pll.register_clkin(clk50, 50e6)
52+
pll.create_clkout(self.cd_sys, sys_clk_freq)
53+
if sdram_rate == "1:2":
54+
pll.create_clkout(self.cd_sys2x, 2*sys_clk_freq)
55+
# theoretically 90 degrees, but increase to relax timing
56+
pll.create_clkout(self.cd_sys2x_ps, 2*sys_clk_freq, phase=180)
57+
else:
58+
pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=90)
59+
60+
# SDRAM clock
61+
sdram_clk = ClockSignal("sys2x_ps" if sdram_rate == "1:2" else "sys_ps")
62+
self.specials += DDROutput(1, 0, platform.request("sdram_clock"), sdram_clk)
63+
64+
# BaseSoC ------------------------------------------------------------------------------------------
65+
66+
class BaseSoC(SoCCore):
67+
def __init__(self, sys_clk_freq=50e6,
68+
with_led_chaser = True,
69+
sdram_rate = "1:1",
70+
**kwargs):
71+
platform = qmtech_cyclone10_starterkit.Platform()
72+
73+
# CRG --------------------------------------------------------------------------------------
74+
self.crg = _CRG(platform, sys_clk_freq, sdram_rate=sdram_rate)
75+
76+
# SoCCore ----------------------------------------------------------------------------------
77+
SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on QMTECH Cyclone10 Starter Kit", **kwargs)
78+
79+
# SDR SDRAM --------------------------------------------------------------------------------
80+
if not self.integrated_main_ram_size:
81+
sdrphy_cls = HalfRateGENSDRPHY if sdram_rate == "1:2" else GENSDRPHY
82+
self.sdrphy = sdrphy_cls(platform.request("sdram"), sys_clk_freq)
83+
self.add_sdram("sdram",
84+
phy = self.sdrphy,
85+
module = W9825G6KH6(sys_clk_freq, sdram_rate),
86+
l2_cache_size = kwargs.get("l2_size", 8192)
87+
)
88+
89+
# Leds -------------------------------------------------------------------------------------
90+
if with_led_chaser:
91+
self.leds = LedChaser(
92+
pads = platform.request_all("user_led"),
93+
sys_clk_freq = sys_clk_freq)
94+
95+
seven_seg_display = platform.request("seven_seg_ctl")
96+
self.comb += seven_seg_display.dig.eq(0b111)
97+
self.leds7 = LedChaser(
98+
pads = seven_seg_display.segments,
99+
sys_clk_freq = sys_clk_freq)
100+
101+
# Build --------------------------------------------------------------------------------------------
102+
103+
def main():
104+
from litex.build.parser import LiteXArgumentParser
105+
parser = LiteXArgumentParser(platform=qmtech_cyclone10_starterkit.Platform, description="LiteX SoC on QMTECH Cyclone10 Starter Kit.")
106+
parser.add_target_argument("--sys-clk-freq", default=50e6, type=float, help="System clock frequency.")
107+
parser.add_target_argument("--sdram-rate", default="1:2", help="SDRAM Rate (1:1 Full Rate or 1:2 Half Rate).")
108+
sdopts = parser.target_group.add_mutually_exclusive_group()
109+
sdopts.add_argument("--with-spi-sdcard", action="store_true", help="Enable SPI-mode SDCard support.")
110+
sdopts.add_argument("--with-sdcard", action="store_true", help="Enable SDCard support.")
111+
args = parser.parse_args()
112+
113+
soc = BaseSoC(
114+
sys_clk_freq = args.sys_clk_freq,
115+
sdram_rate = args.sdram_rate,
116+
**parser.soc_argdict
117+
)
118+
119+
if args.with_sdcard:
120+
soc.add_sdcard()
121+
if args.with_spi_sdcard:
122+
soc.add_spi_sdcard()
123+
124+
builder = Builder(soc, **parser.builder_argdict)
125+
if args.build:
126+
builder.build(**parser.toolchain_argdict)
127+
128+
if args.load:
129+
prog = soc.platform.create_programmer()
130+
prog.load_bitstream(builder.get_bitstream_filename(mode="sram"))
131+
132+
if __name__ == "__main__":
133+
main()

0 commit comments

Comments
 (0)