Merge pull request #491 from hansfbaier/stlv7325-hdmi

STL7325: Add Video, and connectors (FMC, BTB, 2.54mm)
This commit is contained in:
enjoy-digital 2023-04-07 09:06:55 +02:00 committed by GitHub
commit a8eb0b20c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 487 additions and 275 deletions

View File

@ -8,12 +8,19 @@ from litex.build.generic_platform import *
from litex.build.xilinx import Xilinx7SeriesPlatform from litex.build.xilinx import Xilinx7SeriesPlatform
from litex.build.openocd import OpenOCD from litex.build.openocd import OpenOCD
# This board is available here:
# https://www.aliexpress.com/item/1005001275162791.html
# IOs ---------------------------------------------------------------------------------------------- # IOs ----------------------------------------------------------------------------------------------
def _get_io(voltage="2.5V"):
assert voltage in ["2.5V", "3.3V"]
VCCIO = str(25 if voltage == "2.5V" else 33)
_io = [ _io = [
# Clk / Rst # Clk / Rst
("cpu_reset_n", 0, Pins("AC16"), IOStandard("LVCMOS15")), ("cpu_reset_n", 0, Pins("AC16"), IOStandard("LVCMOS15")),
("clk100", 0, Pins("F17"), IOStandard("LVCMOS25")),
("clk100", 0, Pins("F17"), IOStandard("LVCMOS" + VCCIO)),
("clk200", 0, ("clk200", 0,
Subsignal("p", Pins("AB11"), IOStandard("DIFF_SSTL15")), Subsignal("p", Pins("AB11"), IOStandard("DIFF_SSTL15")),
Subsignal("n", Pins("AC11"), IOStandard("DIFF_SSTL15")) Subsignal("n", Pins("AC11"), IOStandard("DIFF_SSTL15"))
@ -45,14 +52,14 @@ _io = [
("i2c", 0, ("i2c", 0,
Subsignal("scl", Pins("U19")), Subsignal("scl", Pins("U19")),
Subsignal("sda", Pins("U20")), Subsignal("sda", Pins("U20")),
IOStandard("LVCMOS25") IOStandard("LVCMOS" + VCCIO)
), ),
# Serial # Serial
("serial", 0, ("serial", 0,
Subsignal("tx", Pins("M25")), # CH340_TX Subsignal("tx", Pins("M25")), # CH340_TX
Subsignal("rx", Pins("L25")), # CH340_RX Subsignal("rx", Pins("L25")), # CH340_RX
IOStandard("LVCMOS25") IOStandard("LVCMOS" + VCCIO)
), ),
# DDR3 SDRAM # DDR3 SDRAM
@ -115,14 +122,12 @@ _io = [
Subsignal("rx_n", Pins("R3")), Subsignal("rx_n", Pins("R3")),
Subsignal("tx_p", Pins("P2")), Subsignal("tx_p", Pins("P2")),
Subsignal("tx_n", Pins("P1")), Subsignal("tx_n", Pins("P1")),
IOStandard("LVCMOS33"),
), ),
("sata", 1, ("sata", 1,
Subsignal("rx_p", Pins("N4")), Subsignal("rx_p", Pins("N4")),
Subsignal("rx_n", Pins("N3")), Subsignal("rx_n", Pins("N3")),
Subsignal("tx_p", Pins("M2")), Subsignal("tx_p", Pins("M2")),
Subsignal("tx_n", Pins("M1")), Subsignal("tx_n", Pins("M1")),
IOStandard("LVCMOS33"),
), ),
# SDCard # SDCard
@ -132,14 +137,14 @@ _io = [
Subsignal("mosi", Pins("U21"), Misc("PULLUP True")), Subsignal("mosi", Pins("U21"), Misc("PULLUP True")),
Subsignal("miso", Pins("N16"), Misc("PULLUP True")), Subsignal("miso", Pins("N16"), Misc("PULLUP True")),
Misc("SLEW=FAST"), Misc("SLEW=FAST"),
IOStandard("LVCMOS25") IOStandard("LVCMOS" + VCCIO)
), ),
("sdcard", 0, ("sdcard", 0,
Subsignal("clk", Pins("N21")), Subsignal("clk", Pins("N21")),
Subsignal("cmd", Pins("U21"), Misc("PULLUP True")), Subsignal("cmd", Pins("U21"), Misc("PULLUP True")),
Subsignal("data", Pins("N16 U16 N22 P19"), Misc("PULLUP True")), Subsignal("data", Pins("N16 U16 N22 P19"), Misc("PULLUP True")),
Misc("SLEW=FAST"), Misc("SLEW=FAST"),
IOStandard("LVCMOS25") IOStandard("LVCMOS" + VCCIO)
), ),
# GMII Ethernet # GMII Ethernet
@ -182,18 +187,18 @@ _io = [
# HDMI out # HDMI out
("hdmi_out", 0, ("hdmi_out", 0,
Subsignal("clk_p", Pins("R21"), IOStandard("TMDS_33")), Subsignal("clk_p", Pins("R21"), IOStandard("TMDS_33" if VCCIO == "33" else "LVDS_25")),
Subsignal("clk_n", Pins("P21"), IOStandard("TMDS_33")), Subsignal("clk_n", Pins("P21"), IOStandard("TMDS_33" if VCCIO == "33" else "LVDS_25")),
Subsignal("data0_p", Pins("N18"), IOStandard("TMDS_33")), Subsignal("data0_p", Pins("N18"), IOStandard("TMDS_33" if VCCIO == "33" else "LVDS_25")),
Subsignal("data0_n", Pins("M19"), IOStandard("TMDS_33")), Subsignal("data0_n", Pins("M19"), IOStandard("TMDS_33" if VCCIO == "33" else "LVDS_25")),
Subsignal("data1_p", Pins("M21"), IOStandard("TMDS_33")), Subsignal("data1_p", Pins("M21"), IOStandard("TMDS_33" if VCCIO == "33" else "LVDS_25")),
Subsignal("data1_n", Pins("M22"), IOStandard("TMDS_33")), Subsignal("data1_n", Pins("M22"), IOStandard("TMDS_33" if VCCIO == "33" else "LVDS_25")),
Subsignal("data2_p", Pins("K25"), IOStandard("TMDS_33")), Subsignal("data2_p", Pins("K25"), IOStandard("TMDS_33" if VCCIO == "33" else "LVDS_25")),
Subsignal("data2_n", Pins("K26"), IOStandard("TMDS_33")), Subsignal("data2_n", Pins("K26"), IOStandard("TMDS_33" if VCCIO == "33" else "LVDS_25")),
Subsignal("scl", Pins("K21"), IOStandard("LVCMOS33")), Subsignal("scl", Pins("K21"), IOStandard("LVCMOS" + VCCIO)),
Subsignal("sda", Pins("L23"), IOStandard("LVCMOS33")), Subsignal("sda", Pins("L23"), IOStandard("LVCMOS" + VCCIO)),
Subsignal("hdp", Pins("N26"), IOStandard("LVCMOS33")), Subsignal("hdp", Pins("N26"), IOStandard("LVCMOS" + VCCIO)),
Subsignal("cec", Pins("M26"), IOStandard("LVCMOS33")), Subsignal("cec", Pins("M26"), IOStandard("LVCMOS" + VCCIO)),
), ),
# PCIe # PCIe
@ -268,8 +273,8 @@ _io = [
# SI5338 (optional part per seller?) # SI5338 (optional part per seller?)
("si5338_i2c", 0, ("si5338_i2c", 0,
Subsignal("sck", Pins("U19"), IOStandard("LVCMOS25")), Subsignal("sck", Pins("U19"), IOStandard("LVCMOS" + VCCIO)),
Subsignal("sda", Pins("U20"), IOStandard("LVCMOS25")) Subsignal("sda", Pins("U20"), IOStandard("LVCMOS" + VCCIO))
), ),
("si5338_clkin", 0, # CLK2A/B ("si5338_clkin", 0, # CLK2A/B
Subsignal("p", Pins("K6"), IOStandard("LVDS_25")), Subsignal("p", Pins("K6"), IOStandard("LVDS_25")),
@ -277,23 +282,196 @@ _io = [
), ),
] ]
return _io
# Connectors --------------------------------------------------------------------------------------- # Connectors ---------------------------------------------------------------------------------------
_connectors = [ _connectors = [
# TODO; add FMC / BTB ("LPC", {
] # Row C
"DP0_C2M_P" : "", # not connected
"DP0_C2M_N" : "", # not connected
"DP0_M2C_P" : "", # not connected
"DP0_M2C_N" : "", # not connected
"LA06_P" : "AE23",
"LA06_N" : "AF23",
"LA10_P" : "AD26",
"LA10_N" : "AE26",
"LA14_P" : "Y25",
"LA14_N" : "Y26",
"LA18_CC_P" : "U26",
"LA18_CC_N" : "V26",
"LA27_P" : "R26",
"LA27_N" : "P26",
# Row D
"GBTCLK0_M2C_P" : "", # not connected
"GBTCLK0_M2C_N" : "", # not connected
"LA01_CC_P" : "AE22",
"LA01_CC_N" : "AF22",
"LA05_P" : "AF24",
"LA05_N" : "AF25",
"LA09_P" : "AB22",
"LA09_N" : "AC22",
"LA13_P" : "AB26",
"LA13_N" : "AC26",
"LA17_CC_P" : "W25",
"LA17_CC_N" : "W26",
"LA23_P" : "AA23",
"LA23_N" : "AB24",
"LA26_P" : "U17",
"LA26_N" : "T17",
# Row G
"CLK1_M2C_P" : "Y23",
"CLK1_M2C_N" : "AA24",
"LA00_CC_P" : "AA25",
"LA00_CC_N" : "AB25",
"LA03_P" : "U24",
"LA03_N" : "U25",
"LA08_P" : "T24",
"LA08_N" : "T25",
"LA12_P" : "R22",
"LA12_N" : "R23",
"LA16_P" : "R25",
"LA16_N" : "P25",
"LA20_P" : "P24",
"LA20_N" : "N24",
"LA22_P" : "P23",
"LA22_N" : "N23",
"LA25_P" : "V21",
"LA25_N" : "W21",
"LA29_P" : "R16",
"LA29_N" : "R17",
"LA31_P" : "P16",
"LA31_N" : "N17",
"LA33_P" : "T22",
"LA33_N" : "T23",
# Row H
"CLK0_M2C_P" : "Y22",
"CLK0_M2C_N" : "AA22",
"LA02_P" : "V23",
"LA02_N" : "V24",
"LA04_P" : "AD21",
"LA04_N" : "AE21",
"LA07_P" : "AB21",
"LA07_N" : "AC21",
"LA11_P" : "AD23",
"LA11_N" : "AD24",
"LA15_P" : "AD25",
"LA15_N" : "AE25",
"LA19_P" : "AC23",
"LA19_N" : "AC24",
"LA21_P" : "W23",
"LA21_N" : "W24",
"LA24_P" : "T18",
"LA24_N" : "T19",
"LA28_P" : "R18",
"LA28_N" : "P18",
"LA30_P" : "U22",
"LA30_N" : "V22",
"LA32_P" : "T20",
"LA32_N" : "R20",
}
),
("BTB-A", {
15: "K23", # P
16: "J23", # N
18: "M24", # P
19: "L24", # N
20: "J24", # P
21: "J25", # N
23: "H21", # P
24: "G21", # N
25: "E21", # P
26: "E22", # N
28: "G22", # P
29: "F23", # N
30: "E25", # P
31: "D25", # N
33: "D23", # P
34: "D24", # N
35: "F22", # P
36: "E23", # N
}),
("BTB-B", {
13: "L22", # P
14: "K22", # N
15: "N19", # P
16: "M20", # N
18: "J21", # P
19: "H22", # N
20: "J26", # P
21: "H26", # N
23: "G25", # P
24: "G26", # N
25: "F25", # P
26: "E26", # N
28: "D26", # P
29: "C26", # N
30: "A23", # P
31: "A24", # N
33: "B20", # P
34: "A20", # N
35: "B26",
}),
("AB", {
# N P
1: "J20", 2: "K20",
3: "G20", 4: "H19",
5: "L20", 6: "L19",
9: "E20", 10: "F19",
11: "H18", 12: "H17",
13: "F18", 14: "G17",
15: "G16", 16: "H16",
19: "F24", 20: "G24",
21: "F20", 22: "G19",
23: "L18", 24: "M17",
25: "H24", 26: "H23",
}),
("C", {
2: "D19", # P
3: "D20", # N
7: "D18", # N
8: "E18", # P
10: "E16", # N
11: "E15", # P
}),
("DE", {
1: "J18", 2: "J19", # P N
3: "L17", 4: "K18", # P N
5: "K16", 6: "K17", # P N
9: "C19", 10: "B19", # P N
11: "C18", 12: "C17", # N P
13: "C16", 14: "B16", # P N
15: "D15", 16: "D16", # P N
19: "G15", 20: "F15", # P N
21: "J15", 22: "J16", # P N
23: "A18", 24: "A19", # P N
25: "B17", 26: "A17", # P N
}),
]
# Platform ----------------------------------------------------------------------------------------- # Platform -----------------------------------------------------------------------------------------
class Platform(Xilinx7SeriesPlatform): class Platform(Xilinx7SeriesPlatform):
default_clk_name = "clk200" default_clk_name = "clk200"
default_clk_period = 1e9/200e6 default_clk_period = 1e9/200e6
def __init__(self): def __init__(self, vccio="2.5V"):
Xilinx7SeriesPlatform.__init__(self, "xc7k325t-ffg676-2", _io, _connectors, toolchain="vivado") Xilinx7SeriesPlatform.__init__(self, "xc7k325t-ffg676-2", _get_io(vccio), _connectors, toolchain="vivado")
self.add_platform_command(""" self.add_platform_command("""
set_property CFGBVS VCCO [current_design] set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 2.5 [current_design] set_property CONFIG_VOLTAGE 2.5 [current_design]
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
""") """)
self.toolchain.bitstream_commands = ["set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]"] self.toolchain.bitstream_commands = ["set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]"]
self.toolchain.additional_commands = ["write_cfgmem -force -format bin -interface spix4 -size 16 -loadbit \"up 0x0 {build_name}.bit\" -file {build_name}.bin"] self.toolchain.additional_commands = ["write_cfgmem -force -format bin -interface spix4 -size 16 -loadbit \"up 0x0 {build_name}.bit\" -file {build_name}.bin"]
@ -303,6 +481,7 @@ set_property CONFIG_VOLTAGE 2.5 [current_design]
def do_finalize(self, fragment): def do_finalize(self, fragment):
Xilinx7SeriesPlatform.do_finalize(self, fragment) Xilinx7SeriesPlatform.do_finalize(self, fragment)
self.add_period_constraint(self.lookup_request("clk100", loose=True), 1e9/100e6)
self.add_period_constraint(self.lookup_request("clk200", loose=True), 1e9/200e6) self.add_period_constraint(self.lookup_request("clk200", loose=True), 1e9/200e6)
self.add_period_constraint(self.lookup_request("eth_clocks:rx", 0, loose=True), 1e9/125e6) self.add_period_constraint(self.lookup_request("eth_clocks:rx", 0, loose=True), 1e9/125e6)
self.add_period_constraint(self.lookup_request("eth_clocks:tx", 0, loose=True), 1e9/125e6) self.add_period_constraint(self.lookup_request("eth_clocks:tx", 0, loose=True), 1e9/125e6)

View File

@ -22,6 +22,7 @@ from litex.soc.integration.soc_core import *
from litex.soc.integration.builder import * from litex.soc.integration.builder import *
from litex.soc.cores.led import LedChaser from litex.soc.cores.led import LedChaser
from litex.soc.cores.bitbang import I2CMaster from litex.soc.cores.bitbang import I2CMaster
from litex.soc.cores.video import VideoS7HDMIPHY
from litedram.modules import MT8JTF12864 from litedram.modules import MT8JTF12864
from litedram.phy import s7ddrphy from litedram.phy import s7ddrphy
@ -39,11 +40,14 @@ class _CRG(LiteXModule):
self.cd_sys = ClockDomain() self.cd_sys = ClockDomain()
self.cd_sys4x = ClockDomain() self.cd_sys4x = ClockDomain()
self.cd_idelay = ClockDomain() self.cd_idelay = ClockDomain()
self.cd_hdmi = ClockDomain()
self.cd_hdmi5x = ClockDomain()
# # # # # #
# Clk/Rst. # Clk/Rst.
clk200 = platform.request("clk200") clk200 = platform.request("clk200")
clk100 = platform.request("clk100")
rst_n = platform.request("cpu_reset_n") rst_n = platform.request("cpu_reset_n")
# PLL. # PLL.
@ -55,12 +59,19 @@ class _CRG(LiteXModule):
pll.create_clkout(self.cd_idelay, 200e6) pll.create_clkout(self.cd_idelay, 200e6)
platform.add_false_path_constraints(self.cd_sys.clk, pll.clkin) # Ignore sys_clk to pll.clkin path created by SoC's rst. platform.add_false_path_constraints(self.cd_sys.clk, pll.clkin) # Ignore sys_clk to pll.clkin path created by SoC's rst.
self.submodules.pll2 = pll2 = S7PLL(speedgrade=-2)
self.comb += pll2.reset.eq(~rst_n | self.rst)
pll2.register_clkin(clk100, 100e6)
pll2.create_clkout(self.cd_hdmi, 25e6, margin=0)
pll2.create_clkout(self.cd_hdmi5x, 125e6, margin=0)
self.idelayctrl = S7IDELAYCTRL(self.cd_idelay) self.idelayctrl = S7IDELAYCTRL(self.cd_idelay)
# BaseSoC ------------------------------------------------------------------------------------------ # BaseSoC ------------------------------------------------------------------------------------------
class BaseSoC(SoCCore): class BaseSoC(SoCCore):
def __init__(self, sys_clk_freq=100e6, def __init__(self, sys_clk_freq=100e6,
vccio = "2.5V",
with_ethernet = False, with_ethernet = False,
with_etherbone = False, with_etherbone = False,
local_ip = "192.168.1.50", local_ip = "192.168.1.50",
@ -70,8 +81,11 @@ class BaseSoC(SoCCore):
with_pcie = False, with_pcie = False,
with_sata = False, with_sata = False,
with_jtagbone = True, with_jtagbone = True,
with_video_colorbars = False,
with_video_framebuffer = False,
with_video_terminal = False,
**kwargs): **kwargs):
platform = sitlinv_stlv7325.Platform() platform = sitlinv_stlv7325.Platform(vccio)
# CRG -------------------------------------------------------------------------------------- # CRG --------------------------------------------------------------------------------------
self.crg = _CRG(platform, sys_clk_freq) self.crg = _CRG(platform, sys_clk_freq)
@ -151,6 +165,16 @@ class BaseSoC(SoCCore):
# Core # Core
self.add_sata(phy=self.sata_phy, mode="read+write") self.add_sata(phy=self.sata_phy, mode="read+write")
# HDMI Options -----------------------------------------------------------------------------
if (with_video_colorbars or with_video_framebuffer or with_video_terminal):
self.submodules.videophy = VideoS7HDMIPHY(platform.request("hdmi_out"), clock_domain="hdmi")
if with_video_colorbars:
self.add_video_colorbars(phy=self.videophy, timings="640x480@60Hz", clock_domain="hdmi")
if with_video_terminal:
self.add_video_terminal(phy=self.videophy, timings="640x480@60Hz", clock_domain="hdmi")
if with_video_framebuffer:
self.add_video_framebuffer(phy=self.videophy, timings="640x480@60Hz", clock_domain="hdmi")
# Leds ------------------------------------------------------------------------------------- # Leds -------------------------------------------------------------------------------------
if with_led_chaser: if with_led_chaser:
self.leds = LedChaser( self.leds = LedChaser(
@ -166,6 +190,7 @@ def main():
from litex.build.parser import LiteXArgumentParser from litex.build.parser import LiteXArgumentParser
parser = LiteXArgumentParser(platform=sitlinv_stlv7325.Platform, description="LiteX SoC on AliExpress STLV7325.") parser = LiteXArgumentParser(platform=sitlinv_stlv7325.Platform, description="LiteX SoC on AliExpress STLV7325.")
parser.add_target_argument("--sys-clk-freq", default=100e6, type=float, help="System clock frequency.") parser.add_target_argument("--sys-clk-freq", default=100e6, type=float, help="System clock frequency.")
parser.add_target_argument("--vccio", default="2.5V", type=str, help="IO Voltage (set by J4), can be 2.5V or 3.3V")
ethopts = parser.target_group.add_mutually_exclusive_group() ethopts = parser.target_group.add_mutually_exclusive_group()
ethopts.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support.") ethopts.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support.")
ethopts.add_argument("--with-etherbone", action="store_true", help="Enable Etherbone support.") ethopts.add_argument("--with-etherbone", action="store_true", help="Enable Etherbone support.")
@ -179,12 +204,17 @@ def main():
sdopts = parser.target_group.add_mutually_exclusive_group() sdopts = parser.target_group.add_mutually_exclusive_group()
sdopts.add_argument("--with-spi-sdcard", action="store_true", help="Enable SPI-mode SDCard support.") sdopts.add_argument("--with-spi-sdcard", action="store_true", help="Enable SPI-mode SDCard support.")
sdopts.add_argument("--with-sdcard", action="store_true", help="Enable SDCard support.") sdopts.add_argument("--with-sdcard", action="store_true", help="Enable SDCard support.")
viopts = parser.target_group.add_mutually_exclusive_group()
viopts.add_argument("--with-video-terminal", action="store_true", help="Enable Video Terminal (HDMI).")
viopts.add_argument("--with-video-framebuffer", action="store_true", help="Enable Video Framebuffer (HDMI).")
viopts.add_argument("--with-video-colorbars", action="store_true", help="Enable Video Colorbars (HDMI).")
args = parser.parse_args() args = parser.parse_args()
assert not (args.with_etherbone and args.eth_dynamic_ip) assert not (args.with_etherbone and args.eth_dynamic_ip)
soc = BaseSoC( soc = BaseSoC(
sys_clk_freq = args.sys_clk_freq, sys_clk_freq = args.sys_clk_freq,
vccio = args.vccio,
with_ethernet = args.with_ethernet, with_ethernet = args.with_ethernet,
with_etherbone = args.with_etherbone, with_etherbone = args.with_etherbone,
local_ip = args.local_ip, local_ip = args.local_ip,
@ -193,6 +223,9 @@ def main():
with_pcie = args.with_pcie, with_pcie = args.with_pcie,
with_sata = args.with_sata, with_sata = args.with_sata,
with_jtagbone = args.with_jtagbone, with_jtagbone = args.with_jtagbone,
with_video_colorbars = args.with_video_colorbars,
with_video_framebuffer = args.with_video_framebuffer,
with_video_terminal = args.with_video_terminal,
**parser.soc_argdict **parser.soc_argdict
) )
if args.with_spi_sdcard: if args.with_spi_sdcard: