Last active
November 14, 2018 13:12
-
-
Save felixheld/5966c2032ae85d352b129fe574f37010 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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