lfps: add initial LFPSTransmitter and use it in LFPS poc

This commit is contained in:
Florent Kermarrec 2019-09-20 15:11:29 +02:00
parent db431b7d1a
commit b564e88a82
2 changed files with 63 additions and 35 deletions

View File

@ -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()

View File

@ -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)),
]