|  | #!/usr/bin/env python3 | 
|  | """ | 
|  | The generator | 
|  | """ | 
|  | import argparse | 
|  |  | 
|  | # ============================================================================= | 
|  |  | 
|  | PINOUT = { | 
|  | "basys3-full": | 
|  | { | 
|  | "clock": "W5", | 
|  | "led": | 
|  | [ | 
|  | "U16", | 
|  | "E19", | 
|  | "U19", | 
|  | "V19", | 
|  | "W18", | 
|  | "U15", | 
|  | "U14", | 
|  | "V14", | 
|  | "V13", | 
|  | "V3", | 
|  | "W3", | 
|  | "U3", | 
|  | "P3", | 
|  | "N3", | 
|  | "P1", | 
|  | "L1", | 
|  | ], | 
|  | "single-ended": | 
|  | [ | 
|  | # Basys3 JB 1-4, 7-10 | 
|  | "A14", | 
|  | "A16", | 
|  | "B15", | 
|  | "B16", | 
|  | "A15", | 
|  | "A17", | 
|  | "C15", | 
|  | "C16", | 
|  | # Basys3 JC 1-4, 7-10 | 
|  | "K17", | 
|  | "M18", | 
|  | "N17", | 
|  | "P18", | 
|  | "L17", | 
|  | "M19", | 
|  | "P17", | 
|  | "R18" | 
|  | ], | 
|  | "differential": | 
|  | [ | 
|  | # Basys3 JB | 
|  | ("A14", "A15"), | 
|  | ("A16", "A17"), | 
|  | ("C15", "B15"), | 
|  | ("B16", "C16"), | 
|  | # Basys3 JC | 
|  | ("M19", "M18"), | 
|  | ("K17", "L17"), | 
|  | ("N17", "P17"), | 
|  | ("P18", "R18"), | 
|  | ], | 
|  | "iobanks": [16, 14], | 
|  | }, | 
|  | "arty-full": | 
|  | { | 
|  | "clock": | 
|  | "E3", | 
|  | "led": | 
|  | [ | 
|  | "G6",  # R0 | 
|  | "G3",  # R1 | 
|  | "J3",  # R2 | 
|  | "K1",  # R3 | 
|  | "F6",  # G0 | 
|  | "J4",  # G1 | 
|  | "J2",  # G2 | 
|  | "H6",  # G3 | 
|  | "E1",  # B0 | 
|  | "G4",  # B1 | 
|  | "H4",  # B2 | 
|  | "K2",  # B3 | 
|  | "H5",  # LED4 | 
|  | "J5",  # LED5 | 
|  | "T9",  # LED6 | 
|  | "T10",  # LED7 | 
|  | ], | 
|  | "single-ended": | 
|  | [ | 
|  | # Pmod JB | 
|  | (15, "E15"), | 
|  | (15, "E16"), | 
|  | (15, "D15"), | 
|  | (15, "C15"), | 
|  | (15, "J17"), | 
|  | (15, "J18"), | 
|  | (15, "K15"), | 
|  | (15, "J15"), | 
|  | # Pmod JC | 
|  | (14, "U12"), | 
|  | (14, "V12"), | 
|  | (14, "V10"), | 
|  | (14, "V11"), | 
|  | (14, "U14"), | 
|  | (14, "V14"), | 
|  | (14, "T13"), | 
|  | (14, "U13"), | 
|  | ], | 
|  | "differential": | 
|  | [ | 
|  | # Pmod JB | 
|  | (15, "E15", "E16"), | 
|  | (15, "D15", "C15"), | 
|  | (15, "J17", "J18"), | 
|  | (15, "K15", "J15"), | 
|  | # Pmod JC | 
|  | (15, "U12", "V12"), | 
|  | (15, "V10", "V11"), | 
|  | (15, "U14", "V14"), | 
|  | (15, "T13", "U13"), | 
|  | ] | 
|  | }, | 
|  |  | 
|  | # Pinout for "bottom" routing graph of 50t, only for Basys3. These pins may | 
|  | # not correspond to actual LEDs so the design may not be suitable for testing | 
|  | # on hardware but it will pass all the checks on CI. | 
|  | "basys3-bottom": | 
|  | { | 
|  | "clock": "W5",  # Bank 34 | 
|  | "led": | 
|  | [ | 
|  | "V3",  # LED9 | 
|  | "W3",  # LED10 | 
|  | "U3",  # LED11 | 
|  | "W7",  # CA | 
|  | "W6",  # CB | 
|  | "U8",  # CC | 
|  | "V8",  # CD | 
|  | "U5",  # CE | 
|  | "V5",  # CF | 
|  | "U7",  # CG | 
|  | ], | 
|  | "single-ended": | 
|  | [ | 
|  | # Basys3 JC 1-4, 7-10 | 
|  | "K17", | 
|  | "M18", | 
|  | "N17", | 
|  | "P18", | 
|  | "L17", | 
|  | "M19", | 
|  | "P17", | 
|  | "R18", | 
|  | "U15",  # LEDs | 
|  | "U16", | 
|  | "V13", | 
|  | "V14", | 
|  | ], | 
|  | "differential": | 
|  | [ | 
|  | # Basys3 JC | 
|  | ("M18", "M19"), | 
|  | ("L17", "K17"), | 
|  | ("P17", "N17"), | 
|  | ("R18", "P18"), | 
|  | ], | 
|  | "iobanks": [14], | 
|  | }, | 
|  | } | 
|  |  | 
|  |  | 
|  | def unquote(s): | 
|  | if isinstance(s, str): | 
|  | return s.replace("\"", "") | 
|  | return s | 
|  |  | 
|  |  | 
|  | # ============================================================================= | 
|  |  | 
|  |  | 
|  | def generate_output(board, iostandard, drives, slews): | 
|  | """ | 
|  | Generates a design which outputs 100Hz square wave to a number of pins | 
|  | in which each one has different DRIVE+SLEW setting. The IOSTANDARD is | 
|  | common for all of them. | 
|  | """ | 
|  |  | 
|  | num_ports = len(drives) * len(slews) | 
|  | iosettings = {} | 
|  |  | 
|  | # Header | 
|  | verilog = """ | 
|  | module top( | 
|  | input  wire clk, | 
|  | output wire [{}:0] out | 
|  | ); | 
|  | """.format(num_ports - 1) | 
|  |  | 
|  | pcf = """ | 
|  | set_io clk {} | 
|  | """.format(PINOUT[board]["clock"]) | 
|  |  | 
|  | # 100Hz square wave generator | 
|  | verilog += """ | 
|  | wire        clk_bufg; | 
|  | reg  [31:0] cnt_ps; | 
|  | reg         tick; | 
|  |  | 
|  | BUFG bufg (.I(clk), .O(clk_bufg)); | 
|  |  | 
|  | initial cnt_ps <= 0; | 
|  | initial tick   <= 0; | 
|  |  | 
|  | always @(posedge clk_bufg) | 
|  | if (cnt_ps >= (100000000 / (2*100)) - 1) begin | 
|  | cnt_ps <= 0; | 
|  | tick   <= !tick; | 
|  | end else begin | 
|  | cnt_ps <= cnt_ps + 1; | 
|  | tick   <= tick; | 
|  | end | 
|  | """ | 
|  |  | 
|  | # Output buffers | 
|  | index = 0 | 
|  | for slew in slews: | 
|  | for drive in drives: | 
|  |  | 
|  | params = {"IOSTANDARD": "\"{}\"".format(iostandard)} | 
|  |  | 
|  | if drive is not None: | 
|  | params["DRIVE"] = int(drive) | 
|  |  | 
|  | if slew is not None: | 
|  | params["SLEW"] = "\"{}\"".format(slew) | 
|  |  | 
|  | pin = PINOUT[board]["single-ended"][index][1] | 
|  |  | 
|  | verilog += """ | 
|  | OBUF # ({params}) obuf_{index} ( | 
|  | .I(tick), | 
|  | .O(out[{index}]) | 
|  | ); | 
|  | """.format( | 
|  | params=",".join( | 
|  | [".{}({})".format(k, v) for k, v in params.items()] | 
|  | ), | 
|  | index=index | 
|  | ) | 
|  |  | 
|  | if num_ports > 1: | 
|  | pcf += "set_io out[{}] {}\n".format(index, pin) | 
|  | else: | 
|  | pcf += "set_io out {}\n".format(pin) | 
|  |  | 
|  | iosettings[pin] = {k: unquote(v) for k, v in params.items()} | 
|  | index += 1 | 
|  |  | 
|  | # Footer | 
|  | verilog += """ | 
|  | endmodule | 
|  | """ | 
|  |  | 
|  | return verilog, pcf, "", iosettings | 
|  |  | 
|  |  | 
|  | def generate_input(board, iostandard, in_terms, vref): | 
|  | """ | 
|  | Generates a design with singnals from external pins go through IBUFs and | 
|  | registers to LEDs. Each IBUF has differen IN_TERM setting. | 
|  | """ | 
|  |  | 
|  | num_ports = len(in_terms) | 
|  | iosettings = {} | 
|  | used_iobanks = set() | 
|  |  | 
|  | # Header | 
|  | verilog = """ | 
|  | module top( | 
|  | input  wire clk, | 
|  | input  wire [{N}:0] inp, | 
|  | output reg  [{N}:0] led | 
|  | ); | 
|  |  | 
|  | initial led <= 0; | 
|  | """.format(N=num_ports - 1) | 
|  |  | 
|  | pcf = """ | 
|  | set_io clk {} | 
|  | """.format(PINOUT[board]["clock"]) | 
|  |  | 
|  | # BUFG | 
|  | verilog += """ | 
|  | wire  clk_bufg; | 
|  |  | 
|  | BUFG bufg (.I(clk), .O(clk_bufg)); | 
|  | """ | 
|  |  | 
|  | verilog += """ | 
|  | wire inp_b[{}:0]; | 
|  | """.format(len(in_terms) - 1) | 
|  |  | 
|  | # Input buffers + registers | 
|  | index = 0 | 
|  | for in_term in in_terms: | 
|  |  | 
|  | params = { | 
|  | "IOSTANDARD": "\"{}\"".format(iostandard), | 
|  | } | 
|  |  | 
|  | if in_term is not None: | 
|  | params["IN_TERM"] = "\"{}\"".format(in_term) | 
|  |  | 
|  | iobank, pin = PINOUT[board]["single-ended"][index] | 
|  | used_iobanks.add(iobank) | 
|  |  | 
|  | verilog += """ | 
|  | IBUF # ({params}) ibuf_{index} ( | 
|  | .I(inp[{index}]), | 
|  | .O(inp_b[{index}]) | 
|  | ); | 
|  |  | 
|  | always @(posedge clk_bufg) | 
|  | led[{index}] <= inp_b[{index}]; | 
|  | """.format( | 
|  | params=",".join( | 
|  | [".{}({})".format(k, v) for k, v in params.items()] | 
|  | ), | 
|  | index=index | 
|  | ) | 
|  |  | 
|  | if num_ports > 1: | 
|  | pcf += "set_io inp[{}] {}\n".format(index, pin) | 
|  | pcf += "set_io led[{}] {}\n".format( | 
|  | index, PINOUT[board]["led"][index] | 
|  | ) | 
|  | else: | 
|  | pcf += "set_io inp {}\n".format(pin) | 
|  | pcf += "set_io led {}\n".format(PINOUT[board]["led"][index]) | 
|  |  | 
|  | iosettings[pin] = {k: unquote(v) for k, v in params.items()} | 
|  | index += 1 | 
|  |  | 
|  | # Footer | 
|  | verilog += """ | 
|  | endmodule | 
|  | """ | 
|  |  | 
|  | # VREF | 
|  | tcl = "" | 
|  | if vref is not None: | 
|  | for iobank in used_iobanks: | 
|  | tcl += "set_property INTERNAL_VREF {} [get_iobanks {}]\n".format( | 
|  | vref, iobank | 
|  | ) | 
|  |  | 
|  | return verilog, pcf, tcl, iosettings | 
|  |  | 
|  |  | 
|  | def generate_inout(board, iostandard, drives, slews, vref): | 
|  | """ | 
|  | Generates a design with INOUT buffers. Buffers cycle through states: | 
|  | L,Z,H,Z with 100Hz frequency. During the Z state, IO pins are latched | 
|  | and their state is presented on LEDs. | 
|  | """ | 
|  |  | 
|  | num_ports = len(drives) * len(slews) | 
|  | iosettings = {} | 
|  | used_iobanks = set() | 
|  |  | 
|  | # Header | 
|  | verilog = """ | 
|  | module top( | 
|  | input  wire clk, | 
|  | inout  wire [{N}:0] ino, | 
|  | output reg  [{N}:0] led | 
|  | ); | 
|  |  | 
|  | initial led <= 0; | 
|  |  | 
|  | wire [{N}:0] ino_i; | 
|  | reg ino_o; | 
|  | reg ino_t; | 
|  |  | 
|  | """.format(N=num_ports - 1) | 
|  |  | 
|  | pcf = """ | 
|  | set_io clk {} | 
|  | """.format(PINOUT[board]["clock"]) | 
|  |  | 
|  | # Control signal generator, data sampler | 
|  | verilog += """ | 
|  | wire        clk_bufg; | 
|  | reg  [31:0] cnt_ps; | 
|  |  | 
|  | BUFG bufg (.I(clk), .O(clk_bufg)); | 
|  |  | 
|  | initial cnt_ps <= 32'd0; | 
|  | initial ino_o  <= 1'b0; | 
|  | initial ino_t  <= 1'b1; | 
|  |  | 
|  | always @(posedge clk_bufg) | 
|  | if (cnt_ps >= (100000000 / (2*100)) - 1) begin | 
|  | cnt_ps <= 0; | 
|  | ino_t  <= !ino_t; | 
|  | if (ino_t == 1'b1) | 
|  | ino_o <= !ino_o; | 
|  | end else begin | 
|  | cnt_ps <= cnt_ps + 1; | 
|  | ino_t  <= ino_t; | 
|  | ino_o  <= ino_o; | 
|  | end | 
|  |  | 
|  | always @(posedge clk_bufg) | 
|  | if (ino_t == 1'b1) | 
|  | led <= ino_i; | 
|  | else | 
|  | led <= led; | 
|  | """ | 
|  |  | 
|  | # INOUT buffers | 
|  | index = 0 | 
|  | for slew in slews: | 
|  | for drive in drives: | 
|  |  | 
|  | params = {"IOSTANDARD": "\"{}\"".format(iostandard)} | 
|  |  | 
|  | if drive is not None: | 
|  | params["DRIVE"] = int(drive) | 
|  |  | 
|  | if slew is not None: | 
|  | params["SLEW"] = "\"{}\"".format(slew) | 
|  |  | 
|  | iobank, pin = PINOUT[board]["single-ended"][index] | 
|  | used_iobanks.add(iobank) | 
|  |  | 
|  | verilog += """ | 
|  | IOBUF # ({params}) iobuf_{index} ( | 
|  | .I(ino_o), | 
|  | .O(ino_i[{index}]), | 
|  | .T(ino_t), | 
|  | .IO(ino[{index}]) | 
|  | ); | 
|  | """.format( | 
|  | params=",".join( | 
|  | [".{}({})".format(k, v) for k, v in params.items()] | 
|  | ), | 
|  | index=index | 
|  | ) | 
|  |  | 
|  | if num_ports > 1: | 
|  | pcf += "set_io ino[{}] {}\n".format(index, pin) | 
|  | pcf += "set_io led[{}] {}\n".format( | 
|  | index, PINOUT[board]["led"][index] | 
|  | ) | 
|  | else: | 
|  | pcf += "set_io ino {}\n".format(pin) | 
|  | pcf += "set_io led {}\n".format(PINOUT[board]["led"][index]) | 
|  |  | 
|  | iosettings[pin] = {k: unquote(v) for k, v in params.items()} | 
|  | index += 1 | 
|  |  | 
|  | # Footer | 
|  | verilog += """ | 
|  | endmodule | 
|  | """ | 
|  |  | 
|  | # VREF | 
|  | tcl = "" | 
|  | if vref is not None: | 
|  | for iobank in used_iobanks: | 
|  | tcl += "set_property INTERNAL_VREF {} [get_iobanks {}]\n".format( | 
|  | vref, iobank | 
|  | ) | 
|  |  | 
|  | return verilog, pcf, tcl, iosettings | 
|  |  | 
|  |  | 
|  | # ============================================================================= | 
|  |  | 
|  |  | 
|  | def generate_diff_output(board, iostandard, drives, slews): | 
|  | """ | 
|  | Generates a design which outputs 100Hz square wave to a number of pins | 
|  | in which each one has different DRIVE+SLEW setting. The IOSTANDARD is | 
|  | common for all of them. | 
|  | """ | 
|  |  | 
|  | num_ports = len(drives) * len(slews) | 
|  | iosettings = {} | 
|  |  | 
|  | # Header | 
|  | verilog = """ | 
|  | module top( | 
|  | input  wire clk, | 
|  | output wire [{N}:0] out_p, | 
|  | output wire [{N}:0] out_n | 
|  | ); | 
|  | """.format(N=num_ports - 1) | 
|  |  | 
|  | pcf = """ | 
|  | set_io clk {} | 
|  | """.format(PINOUT[board]["clock"]) | 
|  |  | 
|  | # 100Hz square wave generator | 
|  | verilog += """ | 
|  | wire        clk_bufg; | 
|  | reg  [31:0] cnt_ps; | 
|  | reg         tick; | 
|  |  | 
|  | BUFG bufg (.I(clk), .O(clk_bufg)); | 
|  |  | 
|  | initial cnt_ps <= 0; | 
|  | initial tick   <= 0; | 
|  |  | 
|  | always @(posedge clk_bufg) | 
|  | if (cnt_ps >= (100000000 / (2*100)) - 1) begin | 
|  | cnt_ps <= 0; | 
|  | tick   <= !tick; | 
|  | end else begin | 
|  | cnt_ps <= cnt_ps + 1; | 
|  | tick   <= tick; | 
|  | end | 
|  | """ | 
|  |  | 
|  | # Output buffers | 
|  | index = 0 | 
|  | for slew in slews: | 
|  | for drive in drives: | 
|  |  | 
|  | params = {"IOSTANDARD": "\"{}\"".format(iostandard)} | 
|  |  | 
|  | if drive is not None: | 
|  | params["DRIVE"] = int(drive) | 
|  |  | 
|  | if slew is not None: | 
|  | params["SLEW"] = "\"{}\"".format(slew) | 
|  |  | 
|  | iobank, *pins = PINOUT[board]["differential"][index] | 
|  |  | 
|  | verilog += """ | 
|  | OBUFDS # ({params}) obuf_{index} ( | 
|  | .I(tick), | 
|  | .O(out_p[{index}]), | 
|  | .OB(out_n[{index}]) | 
|  | ); | 
|  | """.format( | 
|  | params=",".join( | 
|  | [".{}({})".format(k, v) for k, v in params.items()] | 
|  | ), | 
|  | index=index | 
|  | ) | 
|  |  | 
|  | if num_ports > 1: | 
|  | pcf += "set_io out_p[{}] {}\n".format(index, pins[0]) | 
|  | pcf += "set_io out_n[{}] {}\n".format(index, pins[1]) | 
|  | else: | 
|  | pcf += "set_io out_p {}\n".format(pins[0]) | 
|  | pcf += "set_io out_n {}\n".format(pins[1]) | 
|  |  | 
|  | iosettings[pins[0]] = {k: unquote(v) for k, v in params.items()} | 
|  | iosettings[pins[1]] = {k: unquote(v) for k, v in params.items()} | 
|  | index += 1 | 
|  |  | 
|  | # Footer | 
|  | verilog += """ | 
|  | endmodule | 
|  | """ | 
|  |  | 
|  | return verilog, pcf, "", iosettings | 
|  |  | 
|  |  | 
|  | def generate_diff_input(board, iostandard, in_terms, vref): | 
|  | """ | 
|  | Generates a design with singnals from external pins go through IBUFs and | 
|  | registers to LEDs. Each IBUF has differen IN_TERM setting. | 
|  | """ | 
|  |  | 
|  | num_ports = len(in_terms) | 
|  | iosettings = {} | 
|  | used_iobanks = set() | 
|  |  | 
|  | # Header | 
|  | verilog = """ | 
|  | module top( | 
|  | input  wire clk, | 
|  | input  wire [{N}:0] inp_p, | 
|  | input  wire [{N}:0] inp_n, | 
|  | output reg  [{N}:0] led | 
|  | ); | 
|  |  | 
|  | initial led <= 0; | 
|  | """.format(N=num_ports - 1) | 
|  |  | 
|  | pcf = """ | 
|  | set_io clk {} | 
|  | """.format(PINOUT[board]["clock"]) | 
|  |  | 
|  | # BUFG | 
|  | verilog += """ | 
|  | wire  clk_bufg; | 
|  |  | 
|  | BUFG bufg (.I(clk), .O(clk_bufg)); | 
|  | """ | 
|  |  | 
|  | verilog += """ | 
|  | wire inp_b[{}:0]; | 
|  | """.format(len(in_terms) - 1) | 
|  |  | 
|  | # Input buffers + registers | 
|  | index = 0 | 
|  | for in_term in in_terms: | 
|  |  | 
|  | params = { | 
|  | "IOSTANDARD": "\"{}\"".format(iostandard), | 
|  | } | 
|  |  | 
|  | if in_term is not None: | 
|  | params["IN_TERM"] = "\"{}\"".format(in_term) | 
|  |  | 
|  | iobank, *pins = PINOUT[board]["differential"][index] | 
|  | used_iobanks.add(iobank) | 
|  |  | 
|  | verilog += """ | 
|  | IBUFDS # ({params}) ibuf_{index} ( | 
|  | .I(inp_p[{index}]), | 
|  | .IB(inp_n[{index}]), | 
|  | .O(inp_b[{index}]) | 
|  | ); | 
|  |  | 
|  | always @(posedge clk_bufg) | 
|  | led[{index}] <= inp_b[{index}]; | 
|  | """.format( | 
|  | params=",".join( | 
|  | [".{}({})".format(k, v) for k, v in params.items()] | 
|  | ), | 
|  | index=index | 
|  | ) | 
|  |  | 
|  | if num_ports > 1: | 
|  | pcf += "set_io inp_p[{}] {}\n".format(index, pins[0]) | 
|  | pcf += "set_io inp_n[{}] {}\n".format(index, pins[1]) | 
|  | pcf += "set_io led[{}] {}\n".format( | 
|  | index, PINOUT[board]["led"][index] | 
|  | ) | 
|  | else: | 
|  | pcf += "set_io inp_p {}\n".format(pins[0]) | 
|  | pcf += "set_io inp_n {}\n".format(pins[1]) | 
|  | pcf += "set_io led {}\n".format(PINOUT[board]["led"][index]) | 
|  |  | 
|  | iosettings[pins[0]] = {k: unquote(v) for k, v in params.items()} | 
|  | iosettings[pins[1]] = {k: unquote(v) for k, v in params.items()} | 
|  | index += 1 | 
|  |  | 
|  | # Footer | 
|  | verilog += """ | 
|  | endmodule | 
|  | """ | 
|  |  | 
|  | # VREF | 
|  | tcl = "" | 
|  | if vref is not None: | 
|  | for iobank in used_iobanks: | 
|  | tcl += "set_property INTERNAL_VREF {} [get_iobanks {}]\n".format( | 
|  | vref, iobank | 
|  | ) | 
|  |  | 
|  | return verilog, pcf, tcl, iosettings | 
|  |  | 
|  |  | 
|  | def generate_diff_inout(board, iostandard, drives, slews, vref): | 
|  | """ | 
|  | Generates a design with INOUT buffers. Buffers cycle through states: | 
|  | L,Z,H,Z with 100Hz frequency. During the Z state, IO pins are latched | 
|  | and their state is presented on LEDs. | 
|  | """ | 
|  |  | 
|  | num_ports = len(drives) * len(slews) | 
|  | iosettings = {} | 
|  | used_iobanks = set() | 
|  |  | 
|  | # Header | 
|  | verilog = """ | 
|  | module top( | 
|  | input  wire clk, | 
|  | inout  wire [{N}:0] ino_p, | 
|  | inout  wire [{N}:0] ino_n, | 
|  | output reg  [{N}:0] led | 
|  | ); | 
|  |  | 
|  | initial led <= 0; | 
|  |  | 
|  | wire [{N}:0] ino_i; | 
|  | reg ino_o; | 
|  | reg ino_t; | 
|  |  | 
|  | """.format(N=num_ports - 1) | 
|  |  | 
|  | pcf = """ | 
|  | set_io clk {} | 
|  | """.format(PINOUT[board]["clock"]) | 
|  |  | 
|  | # Control signal generator, data sampler | 
|  | verilog += """ | 
|  | wire        clk_bufg; | 
|  | reg  [31:0] cnt_ps; | 
|  |  | 
|  | BUFG bufg (.I(clk), .O(clk_bufg)); | 
|  |  | 
|  | initial cnt_ps <= 32'd0; | 
|  | initial ino_o  <= 1'b0; | 
|  | initial ino_t  <= 1'b1; | 
|  |  | 
|  | always @(posedge clk_bufg) | 
|  | if (cnt_ps >= (100000000 / (2*100)) - 1) begin | 
|  | cnt_ps <= 0; | 
|  | ino_t  <= !ino_t; | 
|  | if (ino_t == 1'b1) | 
|  | ino_o <= !ino_o; | 
|  | end else begin | 
|  | cnt_ps <= cnt_ps + 1; | 
|  | ino_t  <= ino_t; | 
|  | ino_o  <= ino_o; | 
|  | end | 
|  |  | 
|  | always @(posedge clk_bufg) | 
|  | if (ino_t == 1'b1) | 
|  | led <= ino_i; | 
|  | else | 
|  | led <= led; | 
|  | """ | 
|  |  | 
|  | # INOUT buffers | 
|  | index = 0 | 
|  | for slew in slews: | 
|  | for drive in drives: | 
|  |  | 
|  | params = {"IOSTANDARD": "\"{}\"".format(iostandard)} | 
|  |  | 
|  | if drive is not None: | 
|  | params["DRIVE"] = int(drive) | 
|  |  | 
|  | if slew is not None: | 
|  | params["SLEW"] = "\"{}\"".format(slew) | 
|  |  | 
|  | iobank, *pins = PINOUT[board]["differential"][index] | 
|  | used_iobanks.add(iobank) | 
|  |  | 
|  | verilog += """ | 
|  | IOBUFDS # ({params}) iobuf_{index} ( | 
|  | .I(ino_o), | 
|  | .O(ino_i[{index}]), | 
|  | .T(ino_t), | 
|  | .IO(ino_p[{index}]), | 
|  | .IOB(ino_n[{index}]) | 
|  | ); | 
|  | """.format( | 
|  | params=",".join( | 
|  | [".{}({})".format(k, v) for k, v in params.items()] | 
|  | ), | 
|  | index=index | 
|  | ) | 
|  |  | 
|  | if num_ports > 1: | 
|  | pcf += "set_io ino_p[{}] {}\n".format(index, pins[0]) | 
|  | pcf += "set_io ino_n[{}] {}\n".format(index, pins[1]) | 
|  | pcf += "set_io led[{}] {}\n".format( | 
|  | index, PINOUT[board]["led"][index] | 
|  | ) | 
|  | else: | 
|  | pcf += "set_io ino_p {}\n".format(pins[0]) | 
|  | pcf += "set_io ino_n {}\n".format(pins[1]) | 
|  | pcf += "set_io led {}\n".format(PINOUT[board]["led"][index]) | 
|  |  | 
|  | iosettings[pins[0]] = {k: unquote(v) for k, v in params.items()} | 
|  | iosettings[pins[1]] = {k: unquote(v) for k, v in params.items()} | 
|  | index += 1 | 
|  |  | 
|  | # Footer | 
|  | verilog += """ | 
|  | endmodule | 
|  | """ | 
|  |  | 
|  | tcl = "" | 
|  | if vref is not None: | 
|  | for iobank in PINOUT[board]["iobanks"]: | 
|  | tcl += "set_property INTERNAL_VREF {} [get_iobanks {}]\n".format( | 
|  | vref, iobank | 
|  | ) | 
|  |  | 
|  | return verilog, pcf, tcl, iosettings | 
|  |  | 
|  |  | 
|  | # ============================================================================= | 
|  |  | 
|  |  | 
|  | def main(): | 
|  |  | 
|  | # Parse arguments | 
|  | parser = argparse.ArgumentParser() | 
|  | parser.add_argument("--board", required=True, help="Board") | 
|  | parser.add_argument("--mode", required=True, help="Generation mode") | 
|  | parser.add_argument("--iostandard", required=True, help="IOSTANDARD") | 
|  | parser.add_argument( | 
|  | "--drive", required=False, nargs="+", default=[None], help="DRIVE(s)" | 
|  | ) | 
|  | parser.add_argument( | 
|  | "--slew", required=False, nargs="+", default=[None], help="SLEW(s)" | 
|  | ) | 
|  | parser.add_argument("--vref", required=False, default=None, help="VREF") | 
|  | parser.add_argument( | 
|  | "--in_term", | 
|  | required=False, | 
|  | nargs="+", | 
|  | default=[None], | 
|  | help="IN_TERM(s)" | 
|  | ) | 
|  | parser.add_argument("-o", required=True, help="Design name") | 
|  |  | 
|  | args = parser.parse_args() | 
|  |  | 
|  | # Generate design for output IO settings | 
|  | if args.mode == "output": | 
|  | verilog, pcf, tcl, iosettings = generate_output( | 
|  | args.board, args.iostandard, args.drive, args.slew | 
|  | ) | 
|  | elif args.mode == "input": | 
|  | verilog, pcf, tcl, iosettings = generate_input( | 
|  | args.board, args.iostandard, args.in_term, args.vref | 
|  | ) | 
|  | elif args.mode == "inout": | 
|  | verilog, pcf, tcl, iosettings = generate_inout( | 
|  | args.board, args.iostandard, args.drive, args.slew, args.vref | 
|  | ) | 
|  | elif args.mode == "diff_output": | 
|  | verilog, pcf, tcl, iosettings = generate_diff_output( | 
|  | args.board, args.iostandard, args.drive, args.slew | 
|  | ) | 
|  | elif args.mode == "diff_input": | 
|  | verilog, pcf, tcl, iosettings = generate_diff_input( | 
|  | args.board, args.iostandard, args.in_term, args.vref | 
|  | ) | 
|  | elif args.mode == "diff_inout": | 
|  | verilog, pcf, tcl, iosettings = generate_diff_inout( | 
|  | args.board, args.iostandard, args.drive, args.slew, args.vref | 
|  | ) | 
|  | else: | 
|  | raise RuntimeError("Unknown generation mode '{}'".format(args.mode)) | 
|  |  | 
|  | # Write verilog | 
|  | with open(args.o + ".v", "w") as fp: | 
|  | fp.write(verilog) | 
|  |  | 
|  | # Write PCF | 
|  | with open(args.o + ".pcf", "w") as fp: | 
|  | fp.write(pcf) | 
|  |  | 
|  | # Write XDC | 
|  | with open(args.o + ".xdc", "w") as fp: | 
|  | fp.write(tcl) | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | main() |