Skip to content

Instantly share code, notes, and snippets.

@felixheld
Last active November 14, 2018 13:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save felixheld/5966c2032ae85d352b129fe574f37010 to your computer and use it in GitHub Desktop.
Save felixheld/5966c2032ae85d352b129fe574f37010 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
from litex.build.generic_platform import *
from litex.build.xilinx import XilinxPlatform
_io = [
("clk25", 0, Pins("C18"), IOStandard("LVCMOS18")),
("user_led", 0, Pins("E21"), IOStandard("LVCMOS18")),
("user_led", 1, Pins("E22"), IOStandard("LVCMOS18")),
("user_led", 2, Pins("G21"), IOStandard("LVCMOS18")),
("user_led", 3, Pins("G22"), IOStandard("LVCMOS18")),
("spiflash_4x", 0, # clock needs to be accessed through STARTUPE2
Subsignal("cs_n", Pins("T19")),
Subsignal("dq", Pins("P22", "R22", "P21", "R21")),
IOStandard("LVCMOS33")
),
("spiflash_1x", 0, # clock needs to be accessed through STARTUPE2
Subsignal("cs_n", Pins("T19")),
Subsignal("mosi", Pins("P22")),
Subsignal("miso", Pins("R22")),
Subsignal("wp", Pins("P21")),
Subsignal("hold", Pins("R21")),
IOStandard("LVCMOS33")
),
("serial", 0,
Subsignal("tx", Pins("AA19")),
Subsignal("rx", Pins("AB20")),
IOStandard("LVCMOS33"),
Misc("PULLUP=TRUE") # remove Misc("PULLUP=TRUE")
),
("aux", 0, Pins("AB18"), IOStandard("LVCMOS33"), Misc("PULLUP=TRUE")), # remove Misc("PULLUP=TRUE")
("aux", 1, Pins("AA18"), IOStandard("LVCMOS33"), Misc("PULLUP=TRUE")), # remove Misc("PULLUP=TRUE")
# main data connection to the axiom beta
("axiom_data", 0,
Subsignal("n0p", Pins("N18")),
Subsignal("n0n", Pins("N19")),
Subsignal("n1p", Pins("N22")),
Subsignal("n1n", Pins("M22")),
Subsignal("n2p", Pins("N20")),
Subsignal("n2n", Pins("M20")),
Subsignal("n3p", Pins("K18")),
Subsignal("n3n", Pins("K19")),
Subsignal("n4p", Pins("J19")),
Subsignal("n4n", Pins("H19")),
Subsignal("n5p", Pins("J22")),
Subsignal("n5n", Pins("H22")),
Subsignal("s0p", Pins("T1")),
Subsignal("s0n", Pins("U1")),
Subsignal("s1p", Pins("W1")),
Subsignal("s1n", Pins("Y1")),
Subsignal("s2p", Pins("AA1")),
Subsignal("s2n", Pins("AB1")),
Subsignal("s3p", Pins("AB3")), # swapped
Subsignal("s3n", Pins("AB2")), # swapped
Subsignal("s4p", Pins("V4")), # swapped
Subsignal("s4n", Pins("W4")), # swapped
Subsignal("s5p", Pins("AB7")), # swapped
Subsignal("s5n", Pins("AB6")), # swapped
IOStandard("LVCMOS25"),
Misc("PULLUP=TRUE") # remove Misc("PULLUP=TRUE")
#IOStandard("LVDS_25"),
#Misc("DIFF_TERM=TRUE"),
),
("sync_in", 0,
Subsignal("hsync", Pins("F3")),
Subsignal("vsync", Pins("G1")),
Subsignal("odd_even", Pins("F1")),
Subsignal("vformat", Pins("G2")),
IOStandard("LVCMOS18")
),
# GTP reference clock from si534x
("sdi_refclk", 0,
Subsignal("p", Pins("F6")), # swapped
Subsignal("n", Pins("E6")), # swapped
),
# clock feedback path from FPGA to si534x
("sdi_refclk_fbout", 0,
Subsignal("p", Pins("R1")),
Subsignal("n", Pins("P1")),
IOStandard("LVCMOS18")
),
("si534x_spi", 0,
Subsignal("clk", Pins("M1")),
Subsignal("cs_n", Pins("L1")),
Subsignal("mosi", Pins("N2")),
Subsignal("miso", Pins("M2")),
IOStandard("LVCMOS18")
),
("si534x_ctl", 0,
Subsignal("rst_n", Pins("M3")),
Subsignal("oe_n", Pins("P4")),
Subsignal("lol_n", Pins("L3")),
Subsignal("irq_n", Pins("K3")),
IOStandard("LVCMOS18")
),
("sdi_out", 0,
Subsignal("p", Pins("B4")),
Subsignal("n", Pins("A4")),
),
("sdi_out_spi", 0,
Subsignal("clk", Pins("B1")),
Subsignal("cs_n", Pins("E1")),
Subsignal("mosi", Pins("E2")),
Subsignal("miso", Pins("D1")),
IOStandard("LVCMOS18")
),
("sdi_out_gpio", 0,
Subsignal("gpio0", Pins("B2")),
Subsignal("gpio1", Pins("A1")),
IOStandard("LVCMOS18")
),
("sdi_out", 1,
Subsignal("p", Pins("B6")),
Subsignal("n", Pins("A6")),
),
("sdi_out_spi", 1,
Subsignal("clk", Pins("C20")),
Subsignal("cs_n", Pins("A18")),
Subsignal("mosi", Pins("B18")),
Subsignal("miso", Pins("A19")),
IOStandard("LVCMOS18")
),
("sdi_out_gpio", 1,
Subsignal("gpio0", Pins("D20")),
Subsignal("gpio1", Pins("D21")),
IOStandard("LVCMOS18")
),
("sdi_in", 0,
Subsignal("p", Pins("B8")),
Subsignal("n", Pins("A8")),
),
("sdi_in_spi", 0,
Subsignal("clk", Pins("B21")),
Subsignal("cs_n", Pins("A20")),
Subsignal("mosi", Pins("B20")),
Subsignal("miso", Pins("A21")),
IOStandard("LVCMOS18")
),
("sdi_in_gpio", 0,
Subsignal("gpio0", Pins("C22")),
Subsignal("gpio1", Pins("D22")),
IOStandard("LVCMOS18")
),
]
class Platform(XilinxPlatform):
default_clk_name = "clk25"
default_clk_period = 40.0
def __init__(self):
XilinxPlatform.__init__(self, "xc7a35t-fgg484-2", _io, toolchain="vivado")
self.add_platform_command("""
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [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 top.bit\" -file top.bin"]
# part of this code is borrowed from https://lab.whitequark.org/notes/2016-10-18/implementing-an-uart-in-verilog-and-migen/
from migen import *
from photonsdi.boards.platforms import axiom_photonsdi_hw
class BaudrateGenerator(Module):
def __init__(self, clkin, baudrate):
self.baud_strobe = Signal()
def _uart_divisor(sysclk, baudrate):
return int((sysclk + baudrate / 2) // baudrate)
divisor = _uart_divisor(clkin, baudrate)
baud_cntr = Signal(max = divisor)
self.sync += [
If(0 == baud_cntr,
baud_cntr.eq(divisor - 1),
self.baud_strobe.eq(1)
).Else(
baud_cntr.eq(baud_cntr - 1),
self.baud_strobe.eq(0)
)
]
class UARTTXConst(Module):
def __init__(self, data, i_tx_baud_strobe, tx_start, o_tx):
tx_number_of_bits = 8
tx_shiftreg = Signal(tx_number_of_bits)
tx_bitnumber = Signal(max=tx_number_of_bits)
self.submodules.tx_fsm = FSM(reset_state="IDLE")
self.tx_fsm.act("IDLE",
NextValue(o_tx, 1),
If(i_tx_baud_strobe,
If(tx_start,
NextValue(tx_shiftreg, data),
NextState("START")
)
)
)
self.tx_fsm.act("START",
If(i_tx_baud_strobe,
NextState("DATA"),
NextValue(o_tx, 0),
NextValue(tx_bitnumber, 0)
)
)
self.tx_fsm.act("DATA",
If(i_tx_baud_strobe,
NextValue(o_tx, tx_shiftreg[0]),
NextValue(tx_shiftreg, Cat(tx_shiftreg[1:8], 0)), # would it be better to replace the 0 with a tx_shiftreg[0]?
NextValue(tx_bitnumber, tx_bitnumber + 1),
If(tx_bitnumber == tx_number_of_bits - 1,
NextState("STOP")
)
)
)
self.tx_fsm.act("STOP",
If(i_tx_baud_strobe,
NextState("IDLE"),
NextValue(o_tx, 1)
)
)
class MultiUARTTXConst(Module):
def __init__(self, sys_clk_freq, baud_rate, channel_count, offset):
self.tx = Signal(channel_count)
self.submodules.baudrate_generator = BaudrateGenerator(sys_clk_freq, baud_rate)
tx_data = Signal(channel_count)
tx_oe = Signal(channel_count)
tx_start = Signal()
bit_times_between_tx_begins = 16
bit_time_counter = Signal(max=bit_times_between_tx_begins)
active_output_number = Signal(max=channel_count)
self.sync += [
tx_oe.eq(1 << active_output_number),
If(self.baudrate_generator.baud_strobe,
If(0 == bit_time_counter,
bit_time_counter.eq(bit_times_between_tx_begins - 1),
tx_start.eq(1),
If(0 == active_output_number,
active_output_number.eq(channel_count - 1)
).Else(
active_output_number.eq(active_output_number - 1)
)
).Else(
bit_time_counter.eq(bit_time_counter - 1),
tx_start.eq(0)
)
)
]
for i in range(channel_count):
self.submodules += UARTTXConst(offset + i, self.baudrate_generator.baud_strobe, tx_start, tx_data[i])
t = TSTriple()
self.comb += [
t.o.eq(tx_data[i]),
t.oe.eq(tx_oe[i])
]
self.specials += t.get_tristate(self.tx[i])
class Iotest(Module):
def __init__(self, platform):
clk_freq = int((1 / (platform.default_clk_period)) * 1000000000)
serial = platform.request("serial")
aux1 = platform.request("aux")
aux2 = platform.request("aux")
axiom_data = platform.request("axiom_data")
_list_of_pins = [
serial.tx,
serial.rx,
aux1,
aux2,
axiom_data.n0p,
axiom_data.n0n,
axiom_data.n1p,
axiom_data.n1n,
axiom_data.n2p,
axiom_data.n2n,
axiom_data.n3p,
axiom_data.n3n,
axiom_data.n4p,
axiom_data.n4n,
axiom_data.n5p,
axiom_data.n5n,
axiom_data.s0p,
axiom_data.s0n,
axiom_data.s1p,
axiom_data.s1n,
axiom_data.s2p,
axiom_data.s2n,
axiom_data.s3p, # swapped
axiom_data.s3n, # swapped
axiom_data.s4p, # swapped
axiom_data.s4n, # swapped
axiom_data.s5p, # swapped
axiom_data.s5n, # swapped
]
output_count = len(_list_of_pins)
self.submodules.test_signal_generator = MultiUARTTXConst(clk_freq, 115200, output_count, 0x20)
for i in range(output_count):
self.comb += _list_of_pins[i].eq(self.test_signal_generator.tx[i])
def main():
platform = axiom_photonsdi_hw.Platform()
dut = Iotest(platform)
platform.build(dut)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment