add remaining files
This commit is contained in:
parent
514b649bfc
commit
46c84dfc20
|
@ -4,3 +4,5 @@ test
|
|||
*.vcd
|
||||
*.cfg
|
||||
*.txt
|
||||
# Bitstream build directories have _build as their suffixes
|
||||
*_build
|
|
@ -0,0 +1,25 @@
|
|||
from migen import *
|
||||
|
||||
|
||||
class BiDirectionalIO(Module):
|
||||
def __init__(self, i_pads, o_pads):
|
||||
self.i = Signal(4)
|
||||
self.o = Signal(4)
|
||||
self.t = Signal(4)
|
||||
|
||||
for i in range(4):
|
||||
self.specials += Instance("OBUFTDS",
|
||||
i_I=self.i[i],
|
||||
o_O=o_pads[i].p,
|
||||
o_OB=o_pads[i].n,
|
||||
# Always chain the 3-states input to serializer
|
||||
# Vivado will complain otherwise
|
||||
i_T=self.t[i],
|
||||
)
|
||||
|
||||
for i in range(4):
|
||||
self.specials += Instance("IBUFDS",
|
||||
i_I=i_pads[i].p,
|
||||
i_IB=i_pads[i].n,
|
||||
o_O=self.o[i],
|
||||
)
|
|
@ -0,0 +1,60 @@
|
|||
import argparse
|
||||
import tempfile
|
||||
import subprocess
|
||||
|
||||
|
||||
def get_load_cmd(platform, variant):
|
||||
return \
|
||||
'''target create xc7.spi0.proxy testee -chain-position xc7.tap
|
||||
flash bank spi0 jtagspi 0 0 0 0 xc7.spi0.proxy 0x2
|
||||
gdb_port disabled
|
||||
tcl_port disabled
|
||||
telnet_port disabled
|
||||
set error_msg "Trying to use configured scan chain anyway"
|
||||
if {[string first $error_msg [capture "init"]] != -1} {
|
||||
puts "Found error and exiting"
|
||||
exit}
|
||||
xadc_report xc7.tap
|
||||
pld load 0 {bscan_spi_xc7a100t.bit}
|
||||
flash probe spi0
|
||||
flash erase_sector spi0 0 42
|
||||
flash write_bank spi0 {''' + "{}".format(get_bitstream_path(platform, variant)) + '''} 0x0
|
||||
flash verify_bank spi0 {''' + "{}".format(get_bitstream_path(platform, variant)) + '''} 0x0
|
||||
xc7_program xc7.tap
|
||||
exit'''
|
||||
|
||||
def get_build_dir(platform, variant):
|
||||
return "{}_{}_build".format(platform, variant)
|
||||
|
||||
def get_bitstream_path(platform, variant):
|
||||
return get_build_dir(platform, variant)+"/top.bit"
|
||||
|
||||
def run(platform, script):
|
||||
# Dump script to a temp file
|
||||
with tempfile.NamedTemporaryFile(mode="w", delete=False) as f:
|
||||
f.write(script)
|
||||
|
||||
board_path = {
|
||||
"kasli": "board/kasli.cfg",
|
||||
"efc": "efc.cfg",
|
||||
}
|
||||
subprocess.run([
|
||||
"openocd", "-f", board_path[platform], "-f", f.name
|
||||
])
|
||||
|
||||
supported_platform = [ "kasli", "efc" ]
|
||||
supported_variants = [ "master", "satellite" ]
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("platform")
|
||||
parser.add_argument("variant")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.platform not in supported_platform:
|
||||
raise ValueError("Unsupported platform")
|
||||
if args.variant not in supported_variants:
|
||||
raise ValueError("Unsupported variant")
|
||||
|
||||
script = get_load_cmd(args.platform, args.variant)
|
||||
run(args.platform, script)
|
36
kasli_crg.py
36
kasli_crg.py
|
@ -4,7 +4,7 @@ from migen.genlib.resetsync import AsyncResetSynchronizer
|
|||
|
||||
|
||||
class TransceiverCRG(Module):
|
||||
def __init__(self, platform, clk125):
|
||||
def __init__(self, platform, clk125, gte=True):
|
||||
self.platform = platform
|
||||
|
||||
# Generated clock domains
|
||||
|
@ -19,11 +19,35 @@ class TransceiverCRG(Module):
|
|||
clk125_buf = Signal()
|
||||
clk125_div2 = Signal()
|
||||
|
||||
self.specials += Instance("IBUFDS_GTE2",
|
||||
i_CEB=0,
|
||||
i_I=clk125.p, i_IB=clk125.n,
|
||||
o_O=clk125_buf,
|
||||
o_ODIV2=clk125_div2)
|
||||
if gte:
|
||||
self.specials += Instance("IBUFDS_GTE2",
|
||||
i_CEB=0,
|
||||
i_I=clk125.p, i_IB=clk125.n,
|
||||
o_O=clk125_buf,
|
||||
o_ODIV2=clk125_div2)
|
||||
else:
|
||||
self.specials += Instance("IBUFDS",
|
||||
i_I=clk125.p,
|
||||
i_IB=clk125.n,
|
||||
o_O=clk125_buf)
|
||||
|
||||
div2_pll_fb = Signal()
|
||||
inner_pll_locked = Signal()
|
||||
|
||||
self.specials += Instance("PLLE2_BASE",
|
||||
p_CLKIN1_PERIOD=8.0,
|
||||
i_CLKIN1=clk125_buf,
|
||||
|
||||
i_CLKFBIN=div2_pll_fb,
|
||||
o_CLKFBOUT=div2_pll_fb,
|
||||
o_LOCKED=inner_pll_locked,
|
||||
|
||||
# VCO @ 1GHz
|
||||
p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1,
|
||||
|
||||
# 200MHz for IDELAYCTRL
|
||||
p_CLKOUT0_DIVIDE=16, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=clk125_div2,
|
||||
),
|
||||
|
||||
# MMCM to generate different frequencies
|
||||
mmcm_fb = Signal()
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
from migen import *
|
||||
from sync_serdes import *
|
||||
from migen.genlib.fifo import SyncFIFO
|
||||
from migen.build.platforms.sinara import kasli
|
||||
from migen.genlib.misc import WaitTimer
|
||||
from kasli_crg import TransceiverCRG
|
||||
from eem_helpers import generate_pads
|
||||
from uart import UART
|
||||
from io_loopback import SingleIOLoopback
|
||||
|
||||
|
||||
class SingleSerDesLoopBack(Module):
|
||||
def __init__(self, io_pad, sys_clk_freq, debug):
|
||||
self.uart_rx = Signal()
|
||||
self.uart_tx = Signal()
|
||||
|
||||
self.submodules.uart = UART(round((115200/sys_clk_freq)*2**32))
|
||||
self.comb += [
|
||||
self.uart.phy_rx.eq(self.uart_rx),
|
||||
self.uart_tx.eq(self.uart.phy_tx),
|
||||
]
|
||||
|
||||
self.submodules.tx = SingleLineTX()
|
||||
self.submodules.rx = SingleLineRX()
|
||||
|
||||
# Debugging reader
|
||||
self.submodules.bitslip_reader = BitSlipReader()
|
||||
self.submodules.postslip_reader = BitSlipReader()
|
||||
|
||||
# Alignment modules
|
||||
self.submodules.slave_aligner = SlaveAligner()
|
||||
|
||||
# The actual channel
|
||||
self.submodules.channel = SingleIOLoopback(io_pad)
|
||||
|
||||
# Attach FIFO to UART TX, send rate is too slow w.r.t sysclk
|
||||
self.submodules.tx_fifo = SyncFIFO(8, 64)
|
||||
|
||||
self.comb += [
|
||||
# Repetitively send 0b00100
|
||||
self.tx.txdata.eq(0b00100),
|
||||
|
||||
# Loopback channel
|
||||
self.channel.i.eq(self.tx.ser_out),
|
||||
self.rx.ser_in_no_dly.eq(self.channel.o),
|
||||
self.channel.t.eq(self.tx.t_out),
|
||||
|
||||
# TX path
|
||||
self.uart.tx_data.eq(self.tx_fifo.dout),
|
||||
self.uart.tx_stb.eq(self.tx_fifo.readable),
|
||||
self.tx_fifo.re.eq(self.uart.tx_ack),
|
||||
]
|
||||
|
||||
# Debugging logics
|
||||
self.comb += [
|
||||
self.bitslip_reader.loopback_rxdata.eq(self.rx.rxdata),
|
||||
self.postslip_reader.loopback_rxdata.eq(self.rx.rxdata),
|
||||
self.slave_aligner.loopback_rxdata.eq(self.rx.rxdata),
|
||||
|
||||
self.rx.master_bitslip.eq(
|
||||
self.bitslip_reader.bitslip
|
||||
| self.slave_aligner.master_bitslip
|
||||
| self.postslip_reader.bitslip
|
||||
),
|
||||
self.rx.slave_bitslip.eq(
|
||||
self.bitslip_reader.bitslip
|
||||
| self.slave_aligner.master_bitslip
|
||||
| self.postslip_reader.bitslip
|
||||
),
|
||||
]
|
||||
|
||||
bitslip_count = Signal(3)
|
||||
|
||||
fsm = FSM(reset_state="WAIT_DONE")
|
||||
self.submodules += fsm
|
||||
|
||||
fsm.act("WAIT_DONE",
|
||||
self.bitslip_reader.start.eq(1),
|
||||
If(self.bitslip_reader.done,
|
||||
NextValue(bitslip_count, 0),
|
||||
NextState("WRITE_UPPER"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("WRITE_UPPER",
|
||||
If(bitslip_count == 5,
|
||||
NextState("WAIT_BITSLIP_ALIGNED"),
|
||||
).Elif(self.tx_fifo.writable,
|
||||
self.tx_fifo.we.eq(1),
|
||||
self.tx_fifo.din.eq(self.bitslip_reader.data_result[bitslip_count][8:]),
|
||||
NextState("WRITE_LOWER"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("WRITE_LOWER",
|
||||
If(self.tx_fifo.writable,
|
||||
self.tx_fifo.we.eq(1),
|
||||
self.tx_fifo.din.eq(self.bitslip_reader.data_result[bitslip_count][:8]),
|
||||
NextValue(bitslip_count, bitslip_count + 1),
|
||||
NextState("WRITE_UPPER"),
|
||||
)
|
||||
)
|
||||
|
||||
fsm.act("WAIT_BITSLIP_ALIGNED",
|
||||
self.slave_aligner.start.eq(1),
|
||||
If(self.slave_aligner.done,
|
||||
NextState("BARRIER_UPPER"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("BARRIER_UPPER",
|
||||
If(self.tx_fifo.writable,
|
||||
self.tx_fifo.we.eq(1),
|
||||
self.tx_fifo.din.eq(0xFF),
|
||||
NextState("BARRIER_LOWER"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("BARRIER_LOWER",
|
||||
If(self.tx_fifo.writable,
|
||||
self.tx_fifo.we.eq(1),
|
||||
self.tx_fifo.din.eq(0xFF),
|
||||
NextState("REWAIT_BITSLIP_READ_DONE"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("REWAIT_BITSLIP_READ_DONE",
|
||||
self.postslip_reader.start.eq(1),
|
||||
If(self.postslip_reader.done,
|
||||
NextValue(bitslip_count, 0),
|
||||
NextState("REWRITE_UPPER"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("REWRITE_UPPER",
|
||||
If(bitslip_count == 5,
|
||||
NextState("TERMINATE"),
|
||||
).Elif(self.tx_fifo.writable,
|
||||
self.tx_fifo.we.eq(1),
|
||||
self.tx_fifo.din.eq(self.postslip_reader.data_result[bitslip_count][8:]),
|
||||
NextState("REWRITE_LOWER"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("REWRITE_LOWER",
|
||||
If(self.tx_fifo.writable,
|
||||
self.tx_fifo.we.eq(1),
|
||||
self.tx_fifo.din.eq(self.postslip_reader.data_result[bitslip_count][:8]),
|
||||
NextValue(bitslip_count, bitslip_count + 1),
|
||||
NextState("REWRITE_UPPER"),
|
||||
)
|
||||
)
|
||||
|
||||
fsm.act("TERMINATE",
|
||||
NextState("TERMINATE"),
|
||||
)
|
||||
|
||||
self.comb += self.tx.txdata.eq(0b00100)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
platform = kasli.Platform(hw_rev="v2.0")
|
||||
|
||||
# Generate pads for the I/O blocks
|
||||
eem = 3
|
||||
generate_pads(platform, eem)
|
||||
pad = platform.request("dio{}".format(eem), 0)
|
||||
|
||||
crg = TransceiverCRG(platform, platform.request("clk125_gtp"))
|
||||
top = SingleSerDesLoopBack(pad, crg.sys_clk_freq, True)
|
||||
|
||||
# Wire up UART core to the pads
|
||||
uart_pads = platform.request("serial")
|
||||
top.comb += [
|
||||
top.uart_rx.eq(uart_pads.rx),
|
||||
uart_pads.tx.eq(top.uart_tx),
|
||||
]
|
||||
|
||||
top.submodules += crg
|
||||
platform.build(top)
|
|
@ -33,7 +33,7 @@ class MultiTransceiverChannel(Module):
|
|||
self.submodules.channel = IOLoopBack(io_pads)
|
||||
|
||||
# FIFO to record transmission received
|
||||
rx_records = SyncFIFO(16, 32)
|
||||
rx_records = SyncFIFO(16, 128)
|
||||
self.submodules += rx_records
|
||||
|
||||
# Attach FIFO to UART TX, send rate is too slow w.r.t sysclk
|
||||
|
@ -154,52 +154,66 @@ class MultiTransceiverChannel(Module):
|
|||
NextState("WAIT_GROUP_ALIGN"),
|
||||
)
|
||||
|
||||
data = [ Signal(8) for _ in range(2) ]
|
||||
|
||||
tx_fsm.act("WAIT_GROUP_ALIGN",
|
||||
If(self.rx.delay_done,
|
||||
NextState("SEND_ARB_DATA1"),
|
||||
NextValue(data[0], 0x80),
|
||||
NextValue(data[1], 0x7F),
|
||||
NextState("TERMINATE"),
|
||||
),
|
||||
)
|
||||
|
||||
tx_fsm.act("SEND_ARB_DATA1",
|
||||
self.encoder.d[0].eq(0xDE),
|
||||
self.encoder.d[1].eq(0xAD),
|
||||
self.encoder.k[0].eq(0),
|
||||
self.encoder.k[1].eq(0),
|
||||
NextState("SEND_ARB_DATA2"),
|
||||
)
|
||||
|
||||
tx_fsm.act("SEND_ARB_DATA2",
|
||||
self.encoder.d[0].eq(0xBE),
|
||||
self.encoder.d[1].eq(0xEF),
|
||||
self.encoder.k[0].eq(0),
|
||||
self.encoder.k[1].eq(0),
|
||||
NextState("SEND_ARB_DATA3"),
|
||||
)
|
||||
|
||||
tx_fsm.act("SEND_ARB_DATA3",
|
||||
self.encoder.d[0].eq(0xBA),
|
||||
self.encoder.d[1].eq(0xD0),
|
||||
self.encoder.k[0].eq(0),
|
||||
self.encoder.k[1].eq(0),
|
||||
NextState("SEND_ARB_DATA4"),
|
||||
)
|
||||
|
||||
tx_fsm.act("SEND_ARB_DATA4",
|
||||
self.encoder.d[0].eq(0xCA),
|
||||
self.encoder.d[1].eq(0xFE),
|
||||
self.encoder.k[0].eq(0),
|
||||
self.encoder.k[1].eq(0),
|
||||
NextState("TERMINATE"),
|
||||
)
|
||||
|
||||
tx_fsm.act("TERMINATE",
|
||||
self.encoder.d[0].eq(0xAD),
|
||||
self.encoder.d[1].eq(0xDE),
|
||||
self.encoder.d[0].eq(data[0]),
|
||||
self.encoder.d[1].eq(data[1]),
|
||||
self.encoder.k[0].eq(0),
|
||||
self.encoder.k[1].eq(0),
|
||||
NextValue(data[0], data[0] + 1),
|
||||
NextValue(data[1], data[1] - 1),
|
||||
NextState("TERMINATE"),
|
||||
)
|
||||
|
||||
# tx_fsm.act("SEND_ARB_DATA1",
|
||||
# self.encoder.d[0].eq(0xDE),
|
||||
# self.encoder.d[1].eq(0xAD),
|
||||
# self.encoder.k[0].eq(0),
|
||||
# self.encoder.k[1].eq(0),
|
||||
# NextState("SEND_ARB_DATA2"),
|
||||
# )
|
||||
|
||||
# tx_fsm.act("SEND_ARB_DATA2",
|
||||
# self.encoder.d[0].eq(0xBE),
|
||||
# self.encoder.d[1].eq(0xEF),
|
||||
# self.encoder.k[0].eq(0),
|
||||
# self.encoder.k[1].eq(0),
|
||||
# NextState("SEND_ARB_DATA3"),
|
||||
# )
|
||||
|
||||
# tx_fsm.act("SEND_ARB_DATA3",
|
||||
# self.encoder.d[0].eq(0xBA),
|
||||
# self.encoder.d[1].eq(0xD0),
|
||||
# self.encoder.k[0].eq(0),
|
||||
# self.encoder.k[1].eq(0),
|
||||
# NextState("SEND_ARB_DATA4"),
|
||||
# )
|
||||
|
||||
# tx_fsm.act("SEND_ARB_DATA4",
|
||||
# self.encoder.d[0].eq(0xCA),
|
||||
# self.encoder.d[1].eq(0xFE),
|
||||
# self.encoder.k[0].eq(0),
|
||||
# self.encoder.k[1].eq(0),
|
||||
# NextState("TERMINATE"),
|
||||
# )
|
||||
|
||||
# tx_fsm.act("TERMINATE",
|
||||
# self.encoder.d[0].eq(0xAD),
|
||||
# self.encoder.d[1].eq(0xDE),
|
||||
# self.encoder.k[0].eq(0),
|
||||
# self.encoder.k[1].eq(0),
|
||||
# NextState("TERMINATE"),
|
||||
# )
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
@ -224,7 +238,7 @@ if __name__ == "__main__":
|
|||
# Generate pads for the I/O blocks
|
||||
# Using EEM1 for both as both EFC and Kasli has EEM1
|
||||
# EEM1 are not interconnected
|
||||
eem = 0
|
||||
eem = 4
|
||||
generate_pads(platform, eem)
|
||||
pads = [
|
||||
platform.request("dio{}".format(eem), i) for i in range(4)
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
from migen import *
|
||||
from migen.genlib.fifo import SyncFIFO
|
||||
from migen.genlib.misc import WaitTimer
|
||||
from migen.build.platforms.sinara import kasli, efc
|
||||
from eem_helpers import generate_pads
|
||||
from serdes_comm import BiDirectionalIO
|
||||
from sync_serdes import SingleLineRX, BitSlipReader, SlaveAligner
|
||||
from uart_log import UARTLogger
|
||||
from kasli_crg import TransceiverCRG
|
||||
|
||||
|
||||
class SingleLineReader(Module):
|
||||
def __init__(self, uart_log, i_pads, o_pads):
|
||||
# UART Logger
|
||||
self.submodules.uart_logger = uart_log
|
||||
|
||||
# Recorder
|
||||
self.submodules.rx_buffer = SyncFIFO(10, 64)
|
||||
|
||||
# PHY Channel
|
||||
self.submodules.channel = BiDirectionalIO(i_pads, o_pads)
|
||||
|
||||
# Single line RX SERDES
|
||||
self.submodules.rx = SingleLineRX()
|
||||
|
||||
# bitslip reader
|
||||
self.submodules.bitslip_reader = BitSlipReader()
|
||||
self.submodules.postslip_reader = BitSlipReader()
|
||||
|
||||
# Alignment modules
|
||||
self.submodules.slave_aligner = SlaveAligner()
|
||||
|
||||
# Connect SERDES to PHY
|
||||
self.comb += [
|
||||
self.rx.ser_in_no_dly.eq(self.channel.o[0]),
|
||||
]
|
||||
|
||||
# Debugging logics
|
||||
self.comb += [
|
||||
self.bitslip_reader.loopback_rxdata.eq(self.rx.rxdata),
|
||||
self.postslip_reader.loopback_rxdata.eq(self.rx.rxdata),
|
||||
self.slave_aligner.loopback_rxdata.eq(self.rx.rxdata),
|
||||
|
||||
self.rx.master_bitslip.eq(
|
||||
self.bitslip_reader.bitslip
|
||||
| self.slave_aligner.master_bitslip
|
||||
| self.postslip_reader.bitslip
|
||||
),
|
||||
self.rx.slave_bitslip.eq(
|
||||
self.bitslip_reader.bitslip
|
||||
| self.slave_aligner.master_bitslip
|
||||
| self.postslip_reader.bitslip
|
||||
),
|
||||
]
|
||||
|
||||
bitslip_count = Signal(3)
|
||||
|
||||
fsm = FSM(reset_state="WAIT_DONE")
|
||||
self.submodules += fsm
|
||||
|
||||
fsm.act("WAIT_DONE",
|
||||
self.bitslip_reader.start.eq(1),
|
||||
If(self.bitslip_reader.done,
|
||||
NextValue(bitslip_count, 0),
|
||||
NextState("WRITE_UPPER"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("WRITE_UPPER",
|
||||
If(bitslip_count == 5,
|
||||
NextState("WAIT_BITSLIP_ALIGNED"),
|
||||
).Elif(self.uart_logger.tx_fifo.writable,
|
||||
self.uart_logger.tx_fifo.we.eq(1),
|
||||
self.uart_logger.tx_fifo.din.eq(self.bitslip_reader.data_result[bitslip_count][8:]),
|
||||
NextState("WRITE_LOWER"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("WRITE_LOWER",
|
||||
If(self.uart_logger.tx_fifo.writable,
|
||||
self.uart_logger.tx_fifo.we.eq(1),
|
||||
self.uart_logger.tx_fifo.din.eq(self.bitslip_reader.data_result[bitslip_count][:8]),
|
||||
NextValue(bitslip_count, bitslip_count + 1),
|
||||
NextState("WRITE_UPPER"),
|
||||
)
|
||||
)
|
||||
|
||||
fsm.act("WAIT_BITSLIP_ALIGNED",
|
||||
self.slave_aligner.start.eq(1),
|
||||
If(self.slave_aligner.done,
|
||||
NextState("BARRIER_UPPER"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("BARRIER_UPPER",
|
||||
If(self.uart_logger.tx_fifo.writable,
|
||||
self.uart_logger.tx_fifo.we.eq(1),
|
||||
self.uart_logger.tx_fifo.din.eq(0xFF),
|
||||
NextState("BARRIER_LOWER"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("BARRIER_LOWER",
|
||||
If(self.uart_logger.tx_fifo.writable,
|
||||
self.uart_logger.tx_fifo.we.eq(1),
|
||||
self.uart_logger.tx_fifo.din.eq(0xFF),
|
||||
NextState("REWAIT_BITSLIP_READ_DONE"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("REWAIT_BITSLIP_READ_DONE",
|
||||
self.postslip_reader.start.eq(1),
|
||||
If(self.postslip_reader.done,
|
||||
NextValue(bitslip_count, 0),
|
||||
NextState("REWRITE_UPPER"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("REWRITE_UPPER",
|
||||
If(bitslip_count == 5,
|
||||
NextState("TERMINATE"),
|
||||
).Elif(self.uart_logger.tx_fifo.writable,
|
||||
self.uart_logger.tx_fifo.we.eq(1),
|
||||
self.uart_logger.tx_fifo.din.eq(self.postslip_reader.data_result[bitslip_count][8:]),
|
||||
NextState("REWRITE_LOWER"),
|
||||
),
|
||||
)
|
||||
|
||||
fsm.act("REWRITE_LOWER",
|
||||
If(self.uart_logger.tx_fifo.writable,
|
||||
self.uart_logger.tx_fifo.we.eq(1),
|
||||
self.uart_logger.tx_fifo.din.eq(self.postslip_reader.data_result[bitslip_count][:8]),
|
||||
NextValue(bitslip_count, bitslip_count + 1),
|
||||
NextState("REWRITE_UPPER"),
|
||||
)
|
||||
)
|
||||
|
||||
fsm.act("TERMINATE",
|
||||
NextState("TERMINATE"),
|
||||
)
|
||||
|
||||
# self.submodules.wait_timer = WaitTimer(127)
|
||||
# shift_count = Signal(5)
|
||||
|
||||
# self.submodules.fsm = FSM(reset_state="WAIT")
|
||||
|
||||
# self.fsm.act("WAIT",
|
||||
# self.wait_timer.wait.eq(1),
|
||||
# If(shift_count == 10,
|
||||
# NextState("DUMP_UPPER"),
|
||||
# ).Elif(self.wait_timer.done,
|
||||
# NextState("MEASURE"),
|
||||
# ),
|
||||
# )
|
||||
|
||||
# self.fsm.act("MEASURE",
|
||||
# If(self.rx_buffer.writable,
|
||||
# self.rx_buffer.we.eq(1),
|
||||
# self.rx_buffer.din.eq(self.rx.rxdata),
|
||||
# NextState("SHIFT1"),
|
||||
# ),
|
||||
# )
|
||||
|
||||
# self.fsm.act("SHIFT1",
|
||||
# self.rx.master_bitslip.eq(1),
|
||||
# self.rx.slave_bitslip.eq(1),
|
||||
# NextState("GAP"),
|
||||
# )
|
||||
|
||||
# self.fsm.act("GAP",
|
||||
# NextState("SHIFT2"),
|
||||
# )
|
||||
|
||||
# self.fsm.act("SHIFT2",
|
||||
# self.rx.master_bitslip.eq(1),
|
||||
# self.rx.slave_bitslip.eq(1),
|
||||
# NextValue(shift_count, shift_count + 1),
|
||||
# NextState("WAIT"),
|
||||
# )
|
||||
|
||||
# self.fsm.act("DUMP_UPPER",
|
||||
# If(self.rx_buffer.readable,
|
||||
# If(self.uart_logger.tx_fifo.writable,
|
||||
# self.uart_logger.tx_fifo.we.eq(1),
|
||||
# self.uart_logger.tx_fifo.din.eq(self.rx_buffer.dout[8:]),
|
||||
# NextState("DUMP_LOWER"),
|
||||
# ),
|
||||
# ).Else(
|
||||
# NextState("TERMINATE"),
|
||||
# )
|
||||
# )
|
||||
|
||||
# self.fsm.act("DUMP_LOWER",
|
||||
# If(self.uart_logger.tx_fifo.writable,
|
||||
# self.uart_logger.tx_fifo.we.eq(1),
|
||||
# self.uart_logger.tx_fifo.din.eq(self.rx_buffer.dout[:8]),
|
||||
# self.rx_buffer.re.eq(1),
|
||||
# NextState("DUMP_UPPER"),
|
||||
# ),
|
||||
# )
|
||||
|
||||
# self.fsm.act("TERMINATE",
|
||||
# NextState("TERMINATE"),
|
||||
# )
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
import functools
|
||||
import os
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("platform")
|
||||
args = parser.parse_args()
|
||||
|
||||
platform_dict = {
|
||||
"kasli": kasli.Platform(hw_rev="v2.0"),
|
||||
"efc": efc.Platform(),
|
||||
}
|
||||
|
||||
sysclk_name = {
|
||||
"kasli": "clk125_gtp",
|
||||
"efc": "gtp_clk",
|
||||
}
|
||||
|
||||
platform = platform_dict[args.platform]
|
||||
sysclk = platform.request(sysclk_name[args.platform])
|
||||
|
||||
# Generate pads for the I/O blocks
|
||||
for eem in range(2):
|
||||
generate_pads(platform, eem)
|
||||
data_eem = 0
|
||||
|
||||
i_pads = [
|
||||
platform.request("dio{}".format(data_eem), i) for i in range(4)
|
||||
]
|
||||
o_pads = [
|
||||
platform.request("dio{}".format(data_eem), i+4) for i in range(4)
|
||||
]
|
||||
|
||||
crg = TransceiverCRG(platform, sysclk)
|
||||
uart_logger = UARTLogger(crg.sys_clk_freq)
|
||||
top = SingleLineReader(uart_logger, i_pads, o_pads)
|
||||
|
||||
# Wire up UART core to the pads
|
||||
uart_pads = platform.request("serial")
|
||||
top.comb += [
|
||||
uart_logger.uart_rx.eq(uart_pads.rx),
|
||||
uart_pads.tx.eq(uart_logger.uart_tx),
|
||||
]
|
||||
|
||||
top.submodules += crg
|
||||
|
||||
output_dir = "{}_{}_build".format(args.platform, "satellite")
|
||||
platform.build(top, build_dir=output_dir)
|
|
@ -0,0 +1,395 @@
|
|||
from migen import *
|
||||
from sync_serdes import MultiLineRX, MultiLineTX
|
||||
from multi_coders import MultiEncoder, CrossbarDecoder
|
||||
from migen.build.platforms.sinara import kasli, efc
|
||||
from eem_helpers import generate_pads
|
||||
from kasli_crg import TransceiverCRG
|
||||
from uart import UART
|
||||
from migen.genlib.fifo import SyncFIFO
|
||||
|
||||
|
||||
class BiDirectionalIO(Module):
|
||||
def __init__(self, i_pads, o_pads):
|
||||
self.i = Signal(4)
|
||||
self.o = Signal(4)
|
||||
self.t = Signal(4)
|
||||
|
||||
for i in range(4):
|
||||
self.specials += Instance("OBUFTDS",
|
||||
i_I=self.i[i],
|
||||
o_O=o_pads[i].p,
|
||||
o_OB=o_pads[i].n,
|
||||
# Always chain the 3-states input to serializer
|
||||
# Vivado will complain otherwise
|
||||
i_T=self.t[i],
|
||||
)
|
||||
|
||||
for i in range(4):
|
||||
self.specials += Instance("IBUFDS",
|
||||
i_I=i_pads[i].p,
|
||||
i_IB=i_pads[i].n,
|
||||
o_O=self.o[i],
|
||||
)
|
||||
|
||||
|
||||
class ClockOut(Module):
|
||||
def __init__(self, clk_out):
|
||||
self.clk = Signal()
|
||||
# clk_buffer = Signal()
|
||||
# clk_se = Signal()
|
||||
|
||||
# self.specials += Instance("BUFIO",
|
||||
# i_I=self.clk,
|
||||
# o_O=clk_buffer,
|
||||
# )
|
||||
|
||||
# self.specials += Instance("ODDR",
|
||||
# i_C=clk_buffer, i_CE=1, i_D1=0, i_D2=1, o_Q=clk_se),
|
||||
|
||||
self.specials += Instance("OBUFDS",
|
||||
i_I=self.clk,
|
||||
o_O=clk_out.p,
|
||||
o_OB=clk_out.n,
|
||||
)
|
||||
|
||||
|
||||
class Master(Module):
|
||||
def __init__(self, i_pads, o_pads):
|
||||
self.sysclk = ClockSignal("sys")
|
||||
self.submodules.tx = MultiLineTX()
|
||||
self.submodules.rx = MultiLineRX()
|
||||
self.submodules.channel = BiDirectionalIO(i_pads, o_pads)
|
||||
|
||||
self.submodules.encoder = MultiEncoder(lsb_first=False)
|
||||
decoders = [ CrossbarDecoder(lsb_first=False) for _ in range(2) ]
|
||||
self.submodules += decoders
|
||||
|
||||
self.comb += [
|
||||
# Transmitter to SERDES
|
||||
self.channel.i.eq(self.tx.ser_out),
|
||||
self.channel.t.eq(self.tx.t_out),
|
||||
|
||||
# SERDES to receiver
|
||||
self.rx.ser_in_no_dly.eq(self.channel.o),
|
||||
|
||||
# Connect encoders & decoders by default
|
||||
# Overrule the encoder connection during alignment
|
||||
self.tx.txdata.eq(Cat(self.encoder.output[0], self.encoder.output[1])),
|
||||
decoders[0].raw_input.eq(self.rx.rxdata[:10]),
|
||||
decoders[1].raw_input.eq(self.rx.rxdata[10:]),
|
||||
]
|
||||
|
||||
tx_fsm = FSM(reset_state="SEND_TRAINING")
|
||||
self.submodules += tx_fsm
|
||||
|
||||
tx_fsm.act("SEND_TRAINING",
|
||||
self.tx.txdata.eq(0b00100001000010000100),
|
||||
# Keep sending the training sequence unless
|
||||
# an identifier is received
|
||||
NextState("SEND_TRAINING"),
|
||||
# If(self.rx.rxdata == 0b11111111111111111111,
|
||||
# NextState("WAIT_IDENT_END"),
|
||||
# ),
|
||||
)
|
||||
|
||||
tx_fsm.act("WAIT_IDENT_END",
|
||||
self.tx.txdata.eq(0),
|
||||
If(self.rx.rxdata != 0b11111111111111111111,
|
||||
NextState("SEND_ZERO"),
|
||||
),
|
||||
)
|
||||
|
||||
send_zero_duration = Signal(3)
|
||||
|
||||
tx_fsm.act("SEND_ZERO",
|
||||
self.tx.txdata.eq(0),
|
||||
If(send_zero_duration == 0b111,
|
||||
NextState("SEND_PULSE"),
|
||||
).Else(
|
||||
NextValue(send_zero_duration, send_zero_duration + 1),
|
||||
),
|
||||
)
|
||||
|
||||
tx_fsm.act("SEND_PULSE",
|
||||
self.tx.txdata.eq(0b11111111111111111111),
|
||||
self.encoder.start.eq(1),
|
||||
# Slave decoder start will be triggered by this state
|
||||
NextState("WAIT_GROUP_ALIGN"),
|
||||
)
|
||||
|
||||
data = [ Signal(8) for _ in range(2) ]
|
||||
|
||||
tx_fsm.act("WAIT_GROUP_ALIGN",
|
||||
# Wait for the identifier from the slave
|
||||
# TODO: Align the master receiver after
|
||||
If(self.rx.rxdata == 0b11111111111111111111,
|
||||
NextValue(data[0], 0x80),
|
||||
NextValue(data[1], 0x7F),
|
||||
NextState("TERMINATE"),
|
||||
),
|
||||
)
|
||||
|
||||
tx_fsm.act("TERMINATE",
|
||||
self.encoder.d[0].eq(0x89),
|
||||
self.encoder.d[1].eq(0x75),
|
||||
NextValue(data[0], data[0] + 1),
|
||||
NextValue(data[1], data[1] - 1),
|
||||
NextState("TERMINATE"),
|
||||
)
|
||||
|
||||
|
||||
class Satellite(Module):
|
||||
def __init__(self, i_pads, o_pads, sys_clk_freq):
|
||||
self.uart_rx = Signal()
|
||||
self.uart_tx = Signal()
|
||||
|
||||
self.submodules.uart = UART(round((115200/sys_clk_freq)*2**32))
|
||||
self.comb += [
|
||||
self.uart.phy_rx.eq(self.uart_rx),
|
||||
self.uart_tx.eq(self.uart.phy_tx),
|
||||
]
|
||||
|
||||
# Attach FIFO to UART TX, send rate is too slow w.r.t sysclk
|
||||
self.submodules.tx_fifo = SyncFIFO(8, 64)
|
||||
|
||||
self.comb += [
|
||||
# UART TX path
|
||||
self.uart.tx_data.eq(self.tx_fifo.dout),
|
||||
self.uart.tx_stb.eq(self.tx_fifo.readable),
|
||||
self.tx_fifo.re.eq(self.uart.tx_ack),
|
||||
]
|
||||
|
||||
self.submodules.tx = MultiLineTX()
|
||||
self.submodules.rx = MultiLineRX()
|
||||
self.submodules.channel = BiDirectionalIO(i_pads, o_pads)
|
||||
|
||||
self.submodules.encoder = MultiEncoder(lsb_first=False)
|
||||
decoders = [ CrossbarDecoder(lsb_first=False) for _ in range(2) ]
|
||||
self.submodules += decoders
|
||||
|
||||
self.comb += [
|
||||
# Transmitter to SERDES
|
||||
self.channel.i.eq(self.tx.ser_out),
|
||||
self.channel.t.eq(self.tx.t_out),
|
||||
|
||||
# SERDES to receiver
|
||||
self.rx.ser_in_no_dly.eq(self.channel.o),
|
||||
|
||||
# Immediately start alignment for RX
|
||||
self.rx.start.eq(1),
|
||||
|
||||
# Connect encoders & decoders by default
|
||||
# Overrule the encoder connection during alignment
|
||||
self.tx.txdata.eq(Cat(self.encoder.output[0], self.encoder.output[1])),
|
||||
decoders[0].raw_input.eq(self.rx.rxdata[:10]),
|
||||
decoders[1].raw_input.eq(self.rx.rxdata[10:]),
|
||||
|
||||
# Start decoder after delay_done is set
|
||||
decoders[0].start.eq(self.rx.delay_done),
|
||||
decoders[1].start.eq(self.rx.delay_done),
|
||||
]
|
||||
|
||||
rx_fsm = FSM(reset_state="WAIT_ALIGN_DELAY")
|
||||
self.submodules += rx_fsm
|
||||
|
||||
log_buffer = SyncFIFO(20, 128)
|
||||
self.submodules += log_buffer
|
||||
|
||||
rx_fsm.act("WAIT_ALIGN_DELAY",
|
||||
If(self.rx.align_done & log_buffer.writable,
|
||||
log_buffer.we.eq(1),
|
||||
log_buffer.din.eq(self.rx.rxdata),
|
||||
),
|
||||
If(~log_buffer.writable,
|
||||
NextState("DUMP_LOG_UPPER"),
|
||||
),
|
||||
If(self.rx.delay_done,
|
||||
NextState("LOG_TRAFFIC"),
|
||||
),
|
||||
)
|
||||
|
||||
rx_fsm.act("LOG_TRAFFIC",
|
||||
If(log_buffer.writable,
|
||||
log_buffer.we.eq(1),
|
||||
log_buffer.din[0:8].eq(decoders[0].d),
|
||||
log_buffer.din[10:18].eq(decoders[1].d),
|
||||
# log_buffer.din.eq(self.rx.rxdata),
|
||||
).Else(
|
||||
NextState("DUMP_LOG_UPPER"),
|
||||
),
|
||||
)
|
||||
|
||||
rx_fsm.act("DUMP_LOG_UPPER",
|
||||
If(log_buffer.readable,
|
||||
If(self.tx_fifo.writable,
|
||||
self.tx_fifo.we.eq(1),
|
||||
self.tx_fifo.din.eq(log_buffer.dout[18:20]),
|
||||
NextState("DUMP_LOG_LOWER"),
|
||||
),
|
||||
).Else(
|
||||
NextState("TERMINATE")
|
||||
),
|
||||
)
|
||||
|
||||
rx_fsm.act("DUMP_LOG_LOWER",
|
||||
If(self.tx_fifo.writable,
|
||||
self.tx_fifo.we.eq(1),
|
||||
self.tx_fifo.din.eq(log_buffer.dout[10:18]),
|
||||
# log_buffer.re.eq(1),
|
||||
NextState("DUMP_LOG_UPPER_SECOND"),
|
||||
),
|
||||
)
|
||||
|
||||
rx_fsm.act("DUMP_LOG_UPPER_SECOND",
|
||||
If(self.tx_fifo.writable,
|
||||
self.tx_fifo.we.eq(1),
|
||||
self.tx_fifo.din.eq(log_buffer.dout[8:10]),
|
||||
NextState("DUMP_LOG_LOWER_SECOND"),
|
||||
),
|
||||
)
|
||||
|
||||
rx_fsm.act("DUMP_LOG_LOWER_SECOND",
|
||||
If(self.tx_fifo.writable,
|
||||
self.tx_fifo.we.eq(1),
|
||||
self.tx_fifo.din.eq(log_buffer.dout[:8]),
|
||||
log_buffer.re.eq(1),
|
||||
NextState("DUMP_LOG_UPPER"),
|
||||
),
|
||||
)
|
||||
|
||||
rx_fsm.act("TERMINATE",
|
||||
NextState("TERMINATE"),
|
||||
)
|
||||
|
||||
tx_fsm = FSM(reset_state="WAIT_RX_INTRA_ALIGN")
|
||||
self.submodules += tx_fsm
|
||||
|
||||
tx_fsm.act("WAIT_RX_INTRA_ALIGN",
|
||||
# Note: (Redundant) Only send something when aligned
|
||||
self.tx.txdata.eq(0),
|
||||
If(self.rx.align_done,
|
||||
NextState("SEND_INTRA_ALIGN_IDENT"),
|
||||
),
|
||||
)
|
||||
|
||||
# Master receiver is not aligned yet
|
||||
# We need to account for the possibility of group delay
|
||||
# and SERDES misalignment
|
||||
# 4 cycles of full 1s seems sufficiently detectable
|
||||
ident_timer = Signal(2)
|
||||
|
||||
tx_fsm.act("SEND_INTRA_ALIGN_IDENT",
|
||||
self.tx.txdata.eq(0b11111111111111111111),
|
||||
If(ident_timer == 0b11,
|
||||
NextValue(ident_timer, 0),
|
||||
NextState("WAIT_RX_GROUP_ALIGN"),
|
||||
).Else(
|
||||
NextValue(ident_timer, ident_timer + 1)
|
||||
),
|
||||
)
|
||||
|
||||
tx_fsm.act("WAIT_RX_GROUP_ALIGN",
|
||||
self.tx.txdata.eq(0),
|
||||
If(self.rx.delay_done,
|
||||
NextState("SEND_RX_DELAY_IDENT"),
|
||||
),
|
||||
)
|
||||
|
||||
tx_fsm.act("SEND_RX_DELAY_IDENT",
|
||||
self.tx.txdata.eq(0b11111111111111111111),
|
||||
If(ident_timer == 0b11,
|
||||
NextValue(ident_timer, 0),
|
||||
NextState("TERMINATE"),
|
||||
).Else(
|
||||
NextValue(ident_timer, ident_timer + 1)
|
||||
),
|
||||
)
|
||||
|
||||
tx_fsm.act("TERMINATE",
|
||||
# TODO: Release the TX serdes to the encoders
|
||||
self.tx.txdata.eq(0),
|
||||
NextState("TERMINATE"),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
import functools
|
||||
import os
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("platform")
|
||||
parser.add_argument("variant")
|
||||
args = parser.parse_args()
|
||||
|
||||
platform_dict = {
|
||||
"kasli": kasli.Platform(hw_rev="v2.0"),
|
||||
"efc": efc.Platform(),
|
||||
}
|
||||
|
||||
sysclk_name = {
|
||||
"kasli": "clk125_gtp",
|
||||
"efc": "gtp_clk",
|
||||
}
|
||||
|
||||
platform = platform_dict[args.platform]
|
||||
|
||||
# Generate pads for the I/O blocks
|
||||
for eem in range(2):
|
||||
generate_pads(platform, eem)
|
||||
data_eem = 0
|
||||
clk_eem = 1
|
||||
|
||||
clk_pad = platform.request("dio{}".format(clk_eem), 0)
|
||||
|
||||
# Manage clock source
|
||||
if args.variant == "master":
|
||||
sysclk = platform.request(sysclk_name[args.platform])
|
||||
# Fan out clock through EEM1 pair 0
|
||||
# clkout = ClockOut(clk_pad)
|
||||
elif args.variant == "satellite":
|
||||
# Receive clock from EEM1 pair 0
|
||||
sysclk = clk_pad
|
||||
|
||||
if args.variant == "master":
|
||||
i_pads = [
|
||||
platform.request("dio{}".format(data_eem), i) for i in range(4)
|
||||
]
|
||||
o_pads = [
|
||||
platform.request("dio{}".format(data_eem), i+4) for i in range(4)
|
||||
]
|
||||
elif args.variant == "satellite":
|
||||
i_pads = [
|
||||
platform.request("dio{}".format(data_eem), i) for i in range(4)
|
||||
]
|
||||
o_pads = [
|
||||
platform.request("dio{}".format(data_eem), i+4) for i in range(4)
|
||||
]
|
||||
else:
|
||||
raise ValueError("variant {} not implemented".format(args.variant))
|
||||
|
||||
crg = TransceiverCRG(platform, sysclk, gte=(args.variant == "master"))
|
||||
|
||||
variant = {
|
||||
"master": functools.partial(Master, i_pads, o_pads),
|
||||
"satellite": functools.partial(Satellite, i_pads, o_pads, crg.sys_clk_freq),
|
||||
}
|
||||
module_cls = variant[args.variant]
|
||||
|
||||
top = module_cls()
|
||||
|
||||
# Wire up UART core to the pads
|
||||
if args.variant == "satellite":
|
||||
uart_pads = platform.request("serial")
|
||||
top.comb += [
|
||||
top.uart_rx.eq(uart_pads.rx),
|
||||
uart_pads.tx.eq(top.uart_tx),
|
||||
]
|
||||
|
||||
top.submodules += crg
|
||||
# if args.variant == "master":
|
||||
# top.submodules += clkout
|
||||
# top.comb += clkout.clk.eq(top.sysclk)
|
||||
|
||||
output_dir = "{}_{}_build".format(args.platform, args.variant)
|
||||
platform.build(top, build_dir=output_dir)
|
|
@ -0,0 +1,50 @@
|
|||
from migen import *
|
||||
from migen.build.platforms.sinara import kasli, efc
|
||||
from sync_serdes import MultiLineTX
|
||||
from bidirectionalIO import BiDirectionalIO
|
||||
from eem_helpers import generate_pads
|
||||
from kasli_crg import TransceiverCRG
|
||||
|
||||
|
||||
class ShortPulseTX(Module):
|
||||
def __init__(self, i_pads, o_pads):
|
||||
# TX serdes
|
||||
self.submodules.tx = MultiLineTX()
|
||||
# TX PHY
|
||||
self.submodules.channel = BiDirectionalIO(i_pads, o_pads)
|
||||
|
||||
self.comb += [
|
||||
# Transmitter to SERDES
|
||||
self.channel.i.eq(self.tx.ser_out),
|
||||
self.channel.t.eq(self.tx.t_out),
|
||||
|
||||
# # SERDES to receiver
|
||||
# self.rx.ser_in_no_dly.eq(self.channel.o),
|
||||
|
||||
# Hardwire TX with 1 pulse signal
|
||||
self.tx.txdata.eq(0b00000000000000010000)
|
||||
]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
platform = efc.Platform()
|
||||
|
||||
# Generate pads for the I/O blocks
|
||||
for eem in range(2):
|
||||
generate_pads(platform, eem)
|
||||
data_eem = 0
|
||||
|
||||
i_pads = [
|
||||
platform.request("dio{}".format(data_eem), i) for i in range(4)
|
||||
]
|
||||
o_pads = [
|
||||
platform.request("dio{}".format(data_eem), i+4) for i in range(4)
|
||||
]
|
||||
|
||||
crg = TransceiverCRG(platform, platform.request("gtp_clk"))
|
||||
top = ShortPulseTX(i_pads, o_pads)
|
||||
|
||||
top.submodules += crg
|
||||
|
||||
output_dir = "{}_{}_build".format("efc", "master")
|
||||
platform.build(top, build_dir=output_dir)
|
|
@ -1,7 +1,7 @@
|
|||
from migen import *
|
||||
from sync_serdes import *
|
||||
from migen.genlib.fifo import SyncFIFO
|
||||
from migen.build.platforms.sinara import kasli
|
||||
from migen.build.platforms.sinara import kasli, efc
|
||||
from migen.genlib.misc import WaitTimer
|
||||
from kasli_crg import TransceiverCRG
|
||||
from eem_helpers import generate_pads
|
||||
|
@ -470,14 +470,15 @@ class SingleSerDesLoopBack(Module):
|
|||
|
||||
|
||||
if __name__ == "__main__":
|
||||
platform = kasli.Platform(hw_rev="v2.0")
|
||||
# platform = kasli.Platform(hw_rev="v2.0")
|
||||
platform = efc.Platform()
|
||||
|
||||
# Generate pads for the I/O blocks
|
||||
eem = 1
|
||||
generate_pads(platform, eem)
|
||||
pad = platform.request("dio{}".format(eem), 0)
|
||||
|
||||
crg = TransceiverCRG(platform, platform.request("clk125_gtp"))
|
||||
crg = TransceiverCRG(platform, platform.request("gtp_clk"))
|
||||
top = SingleSerDesLoopBack(pad, crg.sys_clk_freq, True)
|
||||
|
||||
# Wire up UART core to the pads
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
from migen import *
|
||||
from migen.genlib.fifo import SyncFIFO
|
||||
from uart import UART
|
||||
|
||||
|
||||
class UARTLogger(Module):
|
||||
def __init__(self, sys_clk_freq):
|
||||
# UART PHY interface
|
||||
self.uart_rx = Signal()
|
||||
self.uart_tx = Signal()
|
||||
|
||||
# Attach FIFO to UART TX, send rate is too slow w.r.t sysclk
|
||||
self.submodules.tx_fifo = SyncFIFO(8, 64)
|
||||
|
||||
self.submodules.uart = UART(round((115200/sys_clk_freq)*2**32))
|
||||
self.comb += [
|
||||
# PHY connection
|
||||
self.uart.phy_rx.eq(self.uart_rx),
|
||||
self.uart_tx.eq(self.uart.phy_tx),
|
||||
|
||||
# UART TX path
|
||||
self.uart.tx_data.eq(self.tx_fifo.dout),
|
||||
self.uart.tx_stb.eq(self.tx_fifo.readable),
|
||||
self.tx_fifo.re.eq(self.uart.tx_ack),
|
||||
]
|
Loading…
Reference in New Issue