<< [[amaranth - python hardware description language|amaranth]], [[glasgow]] `/software/glasgow/platform/rev_c123.py` ## TTL pins ```python Resource("port_a", 0, Subsignal("io", Pins("A1"), Attrs(PULLUP=1)), Subsignal("oe", Pins("C7", dir="o")), Attrs(IO_STANDARD="SB_LVCMOS33")) ``` ## LVDS connector ![[Screenshot 2023-05-16 at 4.19.26 PM.jpg]] LVDS to FPGA pinout: ![[Screenshot 2023-05-16 at 5.21.58 PM.jpg]] [[2023-05-17]] My rewritten connector description: ```python connectors = [ # V G G 12P 12N G 9N 9P G 7N 7P G 5N 5P G 4P 4N G 1N 1P V # G 11N 11P G 10P 10N G 8P 8N G 6P 6N G 3P 3N G 2N 2P G 0P 0N Connector("lvds", 0, "- - - K2 J2 - H3 G3 - F3 F4 - E3 E2 - D2 D3 - C3 C4 -" "- K1 J1 - H1 H2 - G1 G2 - F1 F2 - E1 D1 - C1 C2 - B1 B2"), ] ``` My resource description: ```python Resource("LVDS",0, DiffPairs(p="B1 C4 C2 E1 D2 E2 F1 F4 G1 G3 H1 J1 K2", n = "B2 C3 C1 D1 D3 E3 F2 F3 G2 H3 H2 K1 J2", conn = ["lvds",0]), Attrs(IO_STANDARD="SB_LVDS_INPUT")) ``` Error: ``` NotImplementedError: Platform 'GlasgowPlatformRevC123' does not support differential input/output ``` added `dir = "o"` to DiffPairs definition New error: `NameError: Submodule named 'LVDS_0_0' already exists` Attrs() used in board descriptions in https://github.com/search?q=repo%3Aamaranth-lang%2Famaranth-boards%20lvds&type=code: - `IOSTANDARD = "LVDS"` - `IO_TYPE = "LVDS"` Based on this, changed my code to `Attrs(IO_TYPE="LVDS")` Based on examples in amaranth-boards, changed resource definition to this: ```python Resource("LVDS",0, Subsignal("l0",DiffPairs("B1","B2",dir="o")), Attrs(IO_TYPE="LVDS")) ``` (that's L0 with an l, not 10) Resulting error: `NameError: Submodule named 'LVDS_0__l0_0' already exists` Error is the same whether or not build code contains `lv = platform.request("LVDS")` or `lv = platform.request("LVDS").l0` But if you run `lv = platform.request("LVDS").o`, you get `AttributeError: Record 'LVDS_0' does not have a field 'o'. Did you mean one of: l0?` changed resource name to "LVDS_header" in case there was a conflict with the name LVDS, but got same error added `GLOBAL=True` to Attrs(), got same error Tried calling pins with a more basic resource definition: ```python # glasgow/platform/rev_c123.py Resource("abc", 0, Pins("C1 C2", dir="o")) # lvds_test/__init__.py lv = platform.request("abc") ``` ran with no error, but also no pin level changes on logic analyzer changed to `Resource("abc", 0, Pins("C1 C2", dir="o"),Attrs(IO_TYPE="LVDS"))` error: `ERROR: Module 'SB_IO' referenced in module `pin_abc_0' in cell `abc_0_1' does not have a parameter named 'IO_TYPE'.` Interesting. changed to `Resource("abc", 0, Pins("C1 C2", dir="o"),Attrs(IO_STANDARD="SB_LVDS_INPUT")),` errors: `ERROR: Bel 'X0/Y25/io1' can't be used for LVDS` `ERROR: Bel 'X0/Y25/io1' of type 'SB_IO' is not valid for cell 'pin_abc_0.abc_0_1' of type 'SB_IO'` [[2023-05-18]] After starting to read [[iCE40HX8k]] datasheet, tried `IO_STANDARD="SB_LVDS25"` and `IO_STANDARD="SB_LVDS25E"`. Ran **without errors** but no logic levels changing on the logic analyzer Changed Pins to DiffPairs: `Resource("abc", 0, DiffPairs("C1 C2", dir="o"),Attrs(IO_STANDARD="SB_LVDS25E")),` Connected logic analyzer directly to pin Z0_N - FPGA pin B2. used TTL connector ground. `Resource("abc", 0, Pins("B2", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS33")),` Adding B2 pin to the LED resource to see what happens `Resource("led", 0, Pins("G9 B2", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS33")),` No change on the logic analyzer - but did verify that if we put the logic analyzer on the LED we can see logic levels changing there. Trying a different Glasgow.... just in case. Got a 'device not found' error for a bit but once I unplugged it for long enough that I got the "accept device" popup again and clicked "accept" it worked. Tested on the other side of the resistor directly connected to pin G2 (LED), can see logic levels changing Changed `connectors` description back to the original... Deleted `connectors` section entirely, got error: `TypeError: Can't instantiate abstract class GlasgowPlatformRevC123 with abstract methods connectors`. Commented out everything inside connectors, leaving only `connectors = []` - ran with no errors. Reversed order of pins in LED resource ("B2 G9 B1") - no change. Commented out the blinky test code at the end of `rev_c123.py` - no change Added G8 (LED 1) to LED 0 resource - both LEDs blinked simultaneously. Amaranth iCE40 platform definition: https://github.com/amaranth-lang/amaranth/blob/main/amaranth/vendor/lattice_ice40.py Note from under `should_skip_port_component`: ``` # On iCE40, a differential input is placed by only instantiating an SB_IO primitive for # the pin with z=0, which is the non-inverting pin. The pinout unfortunately differs # between LP/HX and UP series: # * for LP/HX, z=0 is DPxxB (B is non-inverting, A is inverting) # * for UP, z=0 is IOB_xxA (A is non-inverting, B is inverting) ``` investigated [[amaranth backend]] a bit [[debugging amaranth toolchain]] ### resource description ``` ### LVDS Header (Not used as LVDS, but still using the same pin names) Resource("0P", 0, Pins("B1", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS33")), #Resource("0N", 0, Pins("B2", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS33")), Resource("1P", 0, Pins("C4", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS33")), #Resource("1N", 0, Pins("C3", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS33")), Resource("2P", 0, Pins("C2", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS33")), #Resource("2N", 0, Pins("C1", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS33")), Resource("3P", 0, Pins("E1", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS33")), Resource("4P", 0, Pins("D2", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS33")), Resource("5P", 0, Pins("E2", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS33")), Resource("6P", 0, Pins("F1", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS33")), Resource("7P", 0, Pins("F4", dir="o"), Attrs(IO_STANDARD="SB_LVCMOS33")), ``` ### test program combining blinky lights with LVDS test ```python from amaranth import * from glasgow.platform.rev_c123 import GlasgowPlatformRevC123 class LEDBlinker(Elaboratable): def elaborate(self, platform): m = Module() led = platform.request("led") #lv = platform.request("LVDS") half_freq = int(platform.default_clk_frequency // 2) timer = Signal(range(half_freq + 1)) with m.If(timer == half_freq): m.d.sync += led.eq(~led) #m.d.sync += lv.eq(1) m.d.sync += timer.eq(0) with m.Else(): m.d.sync += timer.eq(timer + 1) return m GlasgowPlatformRevC123().build(LEDBlinker(), do_program=True) ```