mirror of
https://github.com/enjoy-digital/usb3_pipe.git
synced 2025-01-04 10:18:41 +08:00
lfps: add initial LFPSTransmitter and use it in LFPS poc
This commit is contained in:
parent
db431b7d1a
commit
b564e88a82
@ -4,7 +4,6 @@
|
|||||||
# PCIe Screamer with PCIe Riser connected to a Host
|
# PCIe Screamer with PCIe Riser connected to a Host
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.misc import WaitTimer
|
|
||||||
|
|
||||||
from litex.build.generic_platform import *
|
from litex.build.generic_platform import *
|
||||||
from litex.build.xilinx import XilinxPlatform
|
from litex.build.xilinx import XilinxPlatform
|
||||||
@ -17,7 +16,7 @@ from litex.soc.cores.uart import UARTWishboneBridge
|
|||||||
|
|
||||||
from gtp_7series import GTPQuadPLL, GTP
|
from gtp_7series import GTPQuadPLL, GTP
|
||||||
|
|
||||||
from usb3_pipe.lfps import LFPSReceiver
|
from usb3_pipe.lfps import LFPSReceiver, LFPSTransmitter
|
||||||
|
|
||||||
from litescope import LiteScopeAnalyzer
|
from litescope import LiteScopeAnalyzer
|
||||||
|
|
||||||
@ -78,9 +77,9 @@ class _CRG(Module):
|
|||||||
pll.create_clkout(self.cd_sys, sys_clk_freq)
|
pll.create_clkout(self.cd_sys, sys_clk_freq)
|
||||||
pll.create_clkout(self.cd_clk125, 125e6)
|
pll.create_clkout(self.cd_clk125, 125e6)
|
||||||
|
|
||||||
# USB3Sniffer --------------------------------------------------------------------------------------
|
# USB3LFPS -----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class USB3Sniffer(SoCMini):
|
class USB3LFPS(SoCMini):
|
||||||
def __init__(self, platform):
|
def __init__(self, platform):
|
||||||
sys_clk_freq = int(100e6)
|
sys_clk_freq = int(100e6)
|
||||||
SoCMini.__init__(self, platform, sys_clk_freq, ident="USB3LFPS", ident_version=True)
|
SoCMini.__init__(self, platform, sys_clk_freq, ident="USB3LFPS", ident_version=True)
|
||||||
@ -121,55 +120,47 @@ class USB3Sniffer(SoCMini):
|
|||||||
self.crg.cd_sys.clk,
|
self.crg.cd_sys.clk,
|
||||||
gtp.cd_rx.clk)
|
gtp.cd_rx.clk)
|
||||||
|
|
||||||
# Redirect RXELECIDLE to GPIO (for scope observation) and Analyzer -------------------------
|
# Override GTP parameters/signals for LFPS -------------------------------------------------
|
||||||
|
txelecidle = Signal()
|
||||||
rxelecidle = Signal()
|
rxelecidle = Signal()
|
||||||
gtp.gtp_params.update(
|
gtp.gtp_params.update(
|
||||||
p_PCS_RSVD_ATTR = 0x000000000100, # bit 8 enable OOB detection
|
p_PCS_RSVD_ATTR = 0x000000000100, # bit 8 enable OOB
|
||||||
p_RXOOB_CLK_CFG = "PMA",
|
p_RXOOB_CLK_CFG = "PMA",
|
||||||
p_RXOOB_CFG = 0b0000110,
|
p_RXOOB_CFG = 0b0000110,
|
||||||
i_RXELECIDLEMODE = 0b00,
|
i_RXELECIDLEMODE = 0b00,
|
||||||
o_RXELECIDLE = rxelecidle)
|
o_RXELECIDLE = rxelecidle,
|
||||||
|
i_TXELECIDLE = txelecidle)
|
||||||
|
|
||||||
|
# Redirect Elec Idle signals to GPIOs --s----------------------------------------------------
|
||||||
self.comb += platform.request("user_gpio", 0).eq(rxelecidle)
|
self.comb += platform.request("user_gpio", 0).eq(rxelecidle)
|
||||||
|
self.comb += platform.request("user_gpio", 1).eq(txelecidle)
|
||||||
|
|
||||||
# LFPS Polling Receive ---------------------------------------------------------------------
|
# LFPS Polling Receive ---------------------------------------------------------------------
|
||||||
lfps_receiver = LFPSReceiver(sys_clk_freq)
|
lfps_receiver = LFPSReceiver(sys_clk_freq=sys_clk_freq)
|
||||||
self.submodules += lfps_receiver
|
self.submodules += lfps_receiver
|
||||||
self.comb += lfps_receiver.idle.eq(rxelecidle)
|
self.comb += lfps_receiver.idle.eq(rxelecidle)
|
||||||
|
|
||||||
# LFPS Polling Transmit --------------------------------------------------------------------
|
# LFPS Polling Transmit --------------------------------------------------------------------
|
||||||
# 5Gbps linerate / 4ns per words
|
lfps_transmitter = LFPSTransmitter(sys_clk_freq=sys_clk_freq, lfps_clk_freq=25e6)
|
||||||
# 25MHz burst can be generated with 5 all ones / 5 all zeroes cycles.
|
self.submodules += lfps_transmitter
|
||||||
txelecidle = Signal()
|
|
||||||
lfps_polling_pattern = Signal(20)
|
|
||||||
lfps_polling_count = Signal(4)
|
|
||||||
self.sync.tx += [
|
|
||||||
lfps_polling_count.eq(lfps_polling_count + 1),
|
|
||||||
If(lfps_polling_count == 4,
|
|
||||||
lfps_polling_count.eq(0),
|
|
||||||
lfps_polling_pattern.eq(~lfps_polling_pattern),
|
|
||||||
)
|
|
||||||
]
|
|
||||||
lfps_burst_timer = WaitTimer(int(1e-6*sys_clk_freq))
|
|
||||||
lfps_repeat_timer = WaitTimer(int(10e-6*sys_clk_freq))
|
|
||||||
self.submodules += lfps_burst_timer, lfps_repeat_timer
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
lfps_burst_timer.wait.eq(~lfps_repeat_timer.done),
|
txelecidle.eq(lfps_transmitter.idle),
|
||||||
lfps_repeat_timer.wait.eq(~lfps_repeat_timer.done),
|
gtp.tx_produce_pattern.eq(~lfps_transmitter.idle),
|
||||||
|
gtp.tx_pattern.eq(lfps_transmitter.pattern)
|
||||||
]
|
]
|
||||||
|
|
||||||
self.comb += gtp.tx_produce_pattern.eq(1)
|
|
||||||
self.comb += gtp.tx_pattern.eq(lfps_polling_pattern)
|
|
||||||
self.comb += txelecidle.eq(lfps_burst_timer.done)
|
|
||||||
gtp.gtp_params.update(i_TXELECIDLE=txelecidle) # FIXME: check TX OOB settings
|
|
||||||
self.comb += platform.request("user_gpio", 1).eq(txelecidle)
|
|
||||||
|
|
||||||
# Analyzer ---------------------------------------------------------------------------------
|
# Analyzer ---------------------------------------------------------------------------------
|
||||||
analyzer_signals = [
|
analyzer_signals = [
|
||||||
rxelecidle,
|
rxelecidle,
|
||||||
|
txelecidle,
|
||||||
|
|
||||||
lfps_receiver.polling,
|
lfps_receiver.polling,
|
||||||
lfps_receiver.count,
|
lfps_receiver.count,
|
||||||
lfps_receiver.found,
|
lfps_receiver.found,
|
||||||
lfps_receiver.fsm,
|
lfps_receiver.fsm,
|
||||||
|
|
||||||
|
lfps_transmitter.idle,
|
||||||
|
lfps_transmitter.pattern
|
||||||
]
|
]
|
||||||
self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals, 4096, clock_domain="sys",
|
self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals, 4096, clock_domain="sys",
|
||||||
csr_csv="analyzer.csv")
|
csr_csv="analyzer.csv")
|
||||||
@ -179,7 +170,7 @@ class USB3Sniffer(SoCMini):
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
platform = Platform()
|
platform = Platform()
|
||||||
soc = USB3Sniffer(platform)
|
soc = USB3LFPS(platform)
|
||||||
builder = Builder(soc, output_dir="build", csr_csv="csr.csv")
|
builder = Builder(soc, output_dir="build", csr_csv="csr.csv")
|
||||||
vns = builder.build()
|
vns = builder.build()
|
||||||
|
|
||||||
|
@ -2,10 +2,12 @@ from math import ceil
|
|||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.cdc import MultiReg
|
from migen.genlib.cdc import MultiReg
|
||||||
|
from migen.genlib.misc import WaitTimer
|
||||||
|
|
||||||
# Constants/Helpers --------------------------------------------------------------------------------
|
# Constants/Helpers --------------------------------------------------------------------------------
|
||||||
|
|
||||||
lfps_period_range = {20e-9, 100e-9}
|
lfps_clk_freq_min = 1/100e-9
|
||||||
|
lfps_clk_freq_max = 1/20e-9
|
||||||
|
|
||||||
class LFPSTiming:
|
class LFPSTiming:
|
||||||
def __init__(self, t_typ=None, t_min=None, t_max=None):
|
def __init__(self, t_typ=None, t_min=None, t_max=None):
|
||||||
@ -55,8 +57,8 @@ U3WakeupLFPS = LFPS(burst=U3WakeupLFPSBurst)
|
|||||||
|
|
||||||
class LFPSReceiver(Module):
|
class LFPSReceiver(Module):
|
||||||
def __init__(self, sys_clk_freq):
|
def __init__(self, sys_clk_freq):
|
||||||
self.idle = Signal()
|
self.idle = Signal() # i
|
||||||
self.polling = Signal()
|
self.polling = Signal() # o
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
@ -95,3 +97,38 @@ class LFPSReceiver(Module):
|
|||||||
NextState("TBURST")
|
NextState("TBURST")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# LFPS Transmitter ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class LFPSTransmitter(Module):
|
||||||
|
def __init__(self, sys_clk_freq, lfps_clk_freq):
|
||||||
|
self.idle = Signal() # o
|
||||||
|
self.pattern = Signal(20) # o
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
# Burst clock generation -------------------------------------------------------------------
|
||||||
|
assert lfps_clk_freq >= lfps_clk_freq_min
|
||||||
|
assert lfps_clk_freq <= lfps_clk_freq_max
|
||||||
|
clk = Signal()
|
||||||
|
clk_timer = WaitTimer(ceil(sys_clk_freq/(2*lfps_clk_freq)) - 1)
|
||||||
|
self.submodules += clk_timer
|
||||||
|
self.comb += clk_timer.wait.eq(~clk_timer.done)
|
||||||
|
self.sync += If(clk_timer.done, clk.eq(~clk))
|
||||||
|
|
||||||
|
# Polling LFPS generation ------------------------------------------------------------------
|
||||||
|
burst_cycles = ns_to_cycles(sys_clk_freq, PollingLFPS.burst.t_typ)
|
||||||
|
repeat_cycles = ns_to_cycles(sys_clk_freq, PollingLFPS.repeat.t_typ)
|
||||||
|
burst_timer = WaitTimer(burst_cycles)
|
||||||
|
repeat_timer = WaitTimer(repeat_cycles)
|
||||||
|
self.submodules += burst_timer, repeat_timer
|
||||||
|
self.comb += [
|
||||||
|
burst_timer.wait.eq(~repeat_timer.done),
|
||||||
|
repeat_timer.wait.eq(~repeat_timer.done),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Output -----------------------------------------------------------------------------------
|
||||||
|
self.comb += [
|
||||||
|
self.idle.eq(burst_timer.done),
|
||||||
|
self.pattern.eq(Replicate(clk, 20)),
|
||||||
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user