Skip to content

Commit

Permalink
bench/serwb: efinix_trion_t120_bga576_dev_kit example
Browse files Browse the repository at this point in the history
  • Loading branch information
trabucayre committed Nov 17, 2023
1 parent a37aa37 commit a162e7e
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 3 deletions.
214 changes: 214 additions & 0 deletions bench/serwb/efinix_trion_t120_bga576_dev_kit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
#!/usr/bin/env python3

#
# This file is part of LiteX-Boards.
#
# Copyright (c) 2021 Franck Jullien <franck.jullien@collshade.fr>
# Copyright (c) 2021 Florent Kermarrec <florent@enjoy-digital.fr>
# SPDX-License-Identifier: BSD-2-Clause

from migen import *
from migen.genlib.resetsync import AsyncResetSynchronizer

from litex.gen import *

from litex.build.generic_platform import *
from litex_boards.platforms import efinix_trion_t120_bga576_dev_kit

from litex.soc.cores.clock import TRIONPLL

from litex.soc.integration.soc_core import *
from litex.soc.integration.soc import SoCRegion
from litex.soc.integration.builder import *

from litex.soc.interconnect import wishbone

from liteiclink.serwb.phy import SERWBPHY
from liteiclink.serwb.genphy import SERWBPHY as SERWBLowSpeedPHY
from liteiclink.serwb.core import SERWBCore

from litescope import LiteScopeAnalyzer

# IOs ----------------------------------------------------------------------------------------------
master_connector = "P2"
slave_connector = "P3"
serwb_io = [
("serwb_master", 0,
Subsignal("clk_p", Pins(f"{master_connector}:1"), IOStandard("1.8_V_LVCMOS")),
Subsignal("clk_n", Pins(f"{master_connector}:3"), IOStandard("1.8_V_LVCMOS")),
Subsignal("tx_p", Pins(f"{master_connector}:7"), IOStandard("1.8_V_LVCMOS")),
Subsignal("tx_n", Pins(f"{master_connector}:9"), IOStandard("1.8_V_LVCMOS")),
Subsignal("rx_p", Pins(f"{slave_connector}:13"), IOStandard("1.8_V_LVCMOS")),
Subsignal("rx_n", Pins(f"{slave_connector}:15"), IOStandard("1.8_V_LVCMOS")),
),

("serwb_slave", 0,
Subsignal("clk_p", Pins(f"{slave_connector}:1"), IOStandard("1.8_V_LVCMOS")),
Subsignal("clk_n", Pins(f"{slave_connector}:3"), IOStandard("1.8_V_LVCMOS")),
Subsignal("tx_p", Pins(f"{master_connector}:13"), IOStandard("1.8_V_LVCMOS")),
Subsignal("tx_n", Pins(f"{master_connector}:15"), IOStandard("1.8_V_LVCMOS")),
Subsignal("rx_p", Pins(f"{slave_connector}:7"), IOStandard("1.8_V_LVCMOS")),
Subsignal("rx_n", Pins(f"{slave_connector}:9"), IOStandard("1.8_V_LVCMOS")),
),
]

# CRG ----------------------------------------------------------------------------------------------

class _CRG(LiteXModule):
def __init__(self, platform, sys_clk_freq):
self.cd_sys = ClockDomain()
self.cd_sys4x = ClockDomain()

# # #

clk40 = platform.request("clk40")
rst_n = platform.request("user_btn", 0)


# PLL
self.pll = pll = TRIONPLL(platform)
self.comb += pll.reset.eq(~rst_n)
pll.register_clkin(clk40, 40e6)
pll.create_clkout(self.cd_sys, sys_clk_freq, with_reset=True, name="sys")
pll.create_clkout(self.cd_sys4x, 4*sys_clk_freq, phase=90, with_reset=True, name="sys4x")

# BaseSoC ------------------------------------------------------------------------------------------

class SerWBTestSoC(SoCMini):
mem_map = {
"serwb": 0x30000000,
}
mem_map.update(SoCMini.mem_map)

def __init__(self, platform, with_analyzer=True):
sys_clk_freq = 40e6

# USBUART PMOD as Serial--------------------------------------------------------------------
platform.add_extension(efinix_trion_t120_bga576_dev_kit.usb_pmod_io("pmod_e"))

# CRG --------------------------------------------------------------------------------------
self.crg = _CRG(platform, sys_clk_freq)

# SoCCore ----------------------------------------------------------------------------------
SoCMini.__init__(self, platform, sys_clk_freq,
csr_data_with = 32,
ident = "LiteICLink SerWB bench on Nexys Video on Efinix Trion T120 BGA576 Dev Kit",
ident_version = True,
with_uart = True,
uart_name = "uartbone")

# SerWB ------------------------------------------------------------------------------------
# SerWB simple test with a SerWB Master added as a Slave peripheral to the SoC and connected
# to a SerWB Slave with a SRAM attached. Access to this SRAM is then tested from the main
# SoC through SerWB:
# +--------+ +-------+ +-------+ +------+
# | | | +-ck-> | | |
# | Test +----+ SerWB +-tx-> SerWB +----> Test |
# | SoC | WB |Master | |Slave | WB | SRAM |
# | +<---+ <-rx-+ <----+ |
# +--------+ +-------+ +-------+ +------+
# ------------------------------------------------------------------------------------------

# SerWB Master ---------------------------------------------------------------------------
# PHY
serwb_master_phy = SERWBPHY(
device = self.platform.device,
pads = self.platform.request("serwb_master"),
mode = "master",
)
self.submodules.serwb_master_phy = serwb_master_phy

# Core
serwb_master_core = SERWBCore(serwb_master_phy, self.clk_freq, mode="slave",
etherbone_buffer_depth = 1,
tx_buffer_depth = 8,
rx_buffer_depth = 8)
self.submodules += serwb_master_core

# Connect as peripheral to main SoC.
self.bus.add_slave("serwb", serwb_master_core.bus, SoCRegion(origin=0x30000000, size=8192))

# SerWB Slave ----------------------------------------------------------------------------
# PHY
serwb_slave_phy = SERWBPHY(
device = self.platform.device,
pads = self.platform.request("serwb_slave"),
mode = "slave",
)
self.clock_domains.cd_serwb = ClockDomain()
if hasattr(serwb_slave_phy.serdes, "clocking"):
self.comb += self.cd_serwb.clk.eq(serwb_slave_phy.serdes.clocking.refclk)
else:
self.comb += self.cd_serwb.clk.eq(ClockSignal("sys"))
self.specials += AsyncResetSynchronizer(self.cd_serwb, ResetSignal("sys"))
serwb_slave_phy = ClockDomainsRenamer("serwb")(serwb_slave_phy)
self.submodules.serwb_slave_phy = serwb_slave_phy

# Core
serwb_slave_core = SERWBCore(serwb_slave_phy, self.clk_freq, mode="master",
etherbone_buffer_depth = 1,
tx_buffer_depth = 8,
rx_buffer_depth = 8)
serwb_slave_core = ClockDomainsRenamer("serwb")(serwb_slave_core)
self.submodules += serwb_slave_core

# Wishbone SRAM
serwb_sram = ClockDomainsRenamer("serwb")(wishbone.SRAM(8192))
self.submodules += serwb_sram
self.comb += serwb_slave_core.bus.connect(serwb_sram.bus)

# Analyzer ---------------------------------------------------------------------------------
if with_analyzer:
analyzer_signals = [
self.serwb_master_phy.init.fsm,
self.serwb_master_phy.serdes.rx.data,
self.serwb_master_phy.serdes.rx.comma,
self.serwb_master_phy.serdes.rx.idle,
self.serwb_master_phy.serdes.tx.data,
self.serwb_master_phy.serdes.tx.comma,
self.serwb_master_phy.serdes.tx.idle,
self.serwb_master_phy.serdes.rx.datapath.decoder.source,

self.serwb_slave_phy.init.fsm,
self.serwb_slave_phy.serdes.rx.data,
self.serwb_slave_phy.serdes.rx.comma,
self.serwb_slave_phy.serdes.rx.idle,
self.serwb_slave_phy.serdes.tx.data,
self.serwb_slave_phy.serdes.tx.comma,
self.serwb_slave_phy.serdes.tx.idle,
self.serwb_slave_phy.serdes.rx.datapath.decoder.source,
]
self.analyzer = LiteScopeAnalyzer(analyzer_signals, 256, csr_csv="analyzer.csv")

# Build --------------------------------------------------------------------------------------------

def main():
from litex.build.parser import LiteXArgumentParser
parser = LiteXArgumentParser(platform=efinix_trion_t120_bga576_dev_kit.Platform, description="LiteICLink SerWB bench on Efinix Trion T120 BGA576 Dev Kit.")
parser.add_target_argument("--flash", action="store_true", help="Flash bitstream.")
parser.add_argument("--with-analyzer", action="store_true", help="Add LiteScope Analyzer")
args = parser.parse_args()

platform = efinix_trion_t120_bga576_dev_kit.Platform()
platform.add_extension(serwb_io)

soc = SerWBTestSoC(platform, with_analyzer=args.with_analyzer)
builder = Builder(soc, csr_csv="csr.csv")
builder.build(run=args.build, **parser.toolchain_argdict)

if args.load:
from litex.build.openfpgaloader import OpenFPGALoader
prog = OpenFPGALoader("trion_t120_bga576_jtag")
prog.load_bitstream(builder.get_bitstream_filename(mode="sram"))

if args.flash:
from litex.build.openfpgaloader import OpenFPGALoader
prog = OpenFPGALoader("trion_t120_bga576")
prog.flash(0, builder.get_bitstream_filename(mode="flash", ext=".hex")) # FIXME

if __name__ == "__main__":
main()

# ./efinix_trion_t120_bga576_dev_kit.py --build --load
# litex_server --uart --uart-port=/dev/ttyUSBX
# ./test_serwb.py --ident --init --sram --access
6 changes: 3 additions & 3 deletions liteiclink/serwb/efinixserdes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

from liteiclink.serwb.datapath import TXDatapath, RXDatapath

from liteiclink.serwb.phy import _SerdesControl
from liteiclink.serwb.phy import _SerdesMasterInit
from liteiclink.serwb.phy import _SerdesSlaveInit
#from liteiclink.serwb.phy import _SerdesControl
#from liteiclink.serwb.phy import _SerdesMasterInit
#from liteiclink.serwb.phy import _SerdesSlaveInit

# BitSlip ------------------------------------------------------------------------------------------

Expand Down
7 changes: 7 additions & 0 deletions liteiclink/serwb/phy.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from liteiclink.serwb.kuserdes import KUSerdes
from liteiclink.serwb.s7serdes import S7Serdes
from liteiclink.serwb.efinixserdes import EfinixSerdes


# SerDes Initialization/Synchronisation ------------------------------------------------------------
Expand Down Expand Up @@ -377,6 +378,12 @@ def __init__(self, device, pads, mode="master", init_timeout=2**15):
elif device[:4] == "xc7a":
taps = 32
self.serdes = S7Serdes(pads, mode)
elif device[:2] == "Ti":
taps = 64
self.serdes = EfinixSerdes(pads, mode)
elif device[:2] == "T1":
taps = 4 # FIXME: no delay
self.serdes = EfinixSerdes(pads, mode)
else:
raise NotImplementedError

Expand Down

0 comments on commit a162e7e

Please sign in to comment.