#!/usr/bin/env python3 import argparse import re from pathlib import Path def width_bits(width): if not width: return 1 match = re.fullmatch(r"\[(\d+):(\d+)\]", width.strip()) if not match: raise ValueError(f"unsupported width: {width}") left = int(match.group(1)) right = int(match.group(2)) return abs(left - right) + 1 def parse_ports(verilog_path): text = Path(verilog_path).read_text() module_name = Path(verilog_path).stem start = text.index(f"module {module_name}(") end = text.index(");", start) header = re.sub(r"//.*", "", text[start:end]) pieces = re.split(r"\b(input|output)\b", header)[1:] ports = [] for direction, body in zip(pieces[0::2], pieces[1::2]): body = body.replace("\n", " ") body = re.split(r"\b(input|output)\b", body)[0] default_width = "" width_match = re.match(r"\s*(\[[^\]]+\])\s*(.*)", body) if width_match: default_width = width_match.group(1) rest = width_match.group(2) else: rest = body for item in rest.split(","): item = item.strip() if not item: continue item_match = re.match(r"(\[[^\]]+\])\s*(\w+)$", item) if item_match: width = item_match.group(1) name = item_match.group(2) else: width = default_width name = item.split()[-1] if re.fullmatch(r"\w+", name): ports.append((direction, width, name)) return ports def const_for(width): bits = width_bits(width) return "1'b0" if bits == 1 else f"{bits}'d0" def is_clock(name): return name.endswith("_clock") or name in { "debug_clock", "debug_clockeddmi_dmiClock", } def is_reset(name): return name.endswith("_reset") or name in { "debug_reset", "debug_clockeddmi_dmiReset", } def main(): parser = argparse.ArgumentParser() parser.add_argument("--rocket-top", required=True) parser.add_argument("--out", required=True) parser.add_argument( "--rf-input-mode", choices=["pmod", "generated", "ethernet"], default="pmod", help="GPS RF source: pmod uses external PMOD clock/data, generated uses an internal RF clock with zero data, ethernet enables the VCU118 Ethernet RF path.", ) args = parser.parse_args() ports = parse_ports(args.rocket_top) port_by_name = {name: (direction, width) for direction, width, name in ports} def decl(width, name): return f" wire {width + ' ' if width else ''}{name};" def connect(prefix, module_name, addr_width): lines = [ f" {module_name} #(", f" .ADDR_WIDTH({addr_width}),", " .ID_WIDTH(4)", f" ) u_{prefix}_slave (", " .clk(fabric_clk),", " .reset(fabric_reset),", f" .aw_ready({prefix}_axi4_0_aw_ready),", f" .aw_valid({prefix}_axi4_0_aw_valid),", f" .aw_bits_id({prefix}_axi4_0_aw_bits_id),", f" .aw_bits_addr({prefix}_axi4_0_aw_bits_addr),", f" .aw_bits_len({prefix}_axi4_0_aw_bits_len),", f" .aw_bits_size({prefix}_axi4_0_aw_bits_size),", f" .aw_bits_burst({prefix}_axi4_0_aw_bits_burst),", f" .w_ready({prefix}_axi4_0_w_ready),", f" .w_valid({prefix}_axi4_0_w_valid),", f" .w_bits_data({prefix}_axi4_0_w_bits_data),", f" .w_bits_strb({prefix}_axi4_0_w_bits_strb),", f" .w_bits_last({prefix}_axi4_0_w_bits_last),", f" .b_ready({prefix}_axi4_0_b_ready),", f" .b_valid({prefix}_axi4_0_b_valid),", f" .b_bits_id({prefix}_axi4_0_b_bits_id),", f" .b_bits_resp({prefix}_axi4_0_b_bits_resp),", f" .ar_ready({prefix}_axi4_0_ar_ready),", f" .ar_valid({prefix}_axi4_0_ar_valid),", f" .ar_bits_id({prefix}_axi4_0_ar_bits_id),", f" .ar_bits_addr({prefix}_axi4_0_ar_bits_addr),", f" .ar_bits_len({prefix}_axi4_0_ar_bits_len),", f" .ar_bits_size({prefix}_axi4_0_ar_bits_size),", f" .ar_bits_burst({prefix}_axi4_0_ar_bits_burst),", f" .r_ready({prefix}_axi4_0_r_ready),", f" .r_valid({prefix}_axi4_0_r_valid),", f" .r_bits_id({prefix}_axi4_0_r_bits_id),", f" .r_bits_data({prefix}_axi4_0_r_bits_data),", f" .r_bits_resp({prefix}_axi4_0_r_bits_resp),", f" .r_bits_last({prefix}_axi4_0_r_bits_last)", " );", ] return "\n".join(lines) def has_axi_slave(prefix): required = [ f"{prefix}_axi4_0_aw_ready", f"{prefix}_axi4_0_aw_valid", f"{prefix}_axi4_0_w_ready", f"{prefix}_axi4_0_w_valid", f"{prefix}_axi4_0_b_ready", f"{prefix}_axi4_0_b_valid", f"{prefix}_axi4_0_ar_ready", f"{prefix}_axi4_0_ar_valid", f"{prefix}_axi4_0_r_ready", f"{prefix}_axi4_0_r_valid", ] return all(name in port_by_name for name in required) top_passthrough_ports = { name for name in ["pmod_spi_sck", "pmod_spi_csn", "pmod_irq", "gps_pps"] if name in port_by_name } assigns = [] for direction, width, name in ports: if direction != "input": continue if name in top_passthrough_ports: continue if name == "debug_systemjtag_reset": value = "fabric_reset | bscan_reset" elif name.startswith("debug_clockeddmi_dmi_req") or name == "debug_clockeddmi_dmi_resp_ready": continue elif name in { "debug_clockeddmi_dmiClock", "debug_clockeddmi_dmiReset", }: continue elif is_clock(name): value = "fabric_clk" elif name == "debug_reset": value = "fabric_reset" elif name == "resetctrl_hartIsInReset_0": value = "soc_reset" elif is_reset(name): value = "soc_reset" elif name == "gps_acq_clk": value = "gps_acq_clk_gen" elif name == "gps_trck_clk": value = "gps_trck_clk_gen" elif name == "gps_rf_clk": value = "gps_rf_clk_selected" elif name == "gps_rf_data": value = "gps_rf_data_selected" elif name == "gps_clock_ready": value = "gps_clock_locked & gps_rf_ready" elif name == "gps_afe_clk": value = "gps_rf_clk_selected" elif name == "debug_systemjtag_jtag_TCK": value = "bscan_tck" elif name == "debug_systemjtag_jtag_TMS": value = "bscan_tms" elif name == "debug_systemjtag_jtag_TDI": value = "bscan_tdi" elif name == "debug_systemjtag_mfr_id": value = "11'd0" elif name == "debug_systemjtag_part_number": value = "16'd0" elif name == "debug_systemjtag_version": value = "4'd0" elif name == "debug_clockeddmi_dmi_resp_ready": value = "1'b1" elif name == "debug_dmactiveAck": value = "debug_dmactive" elif name.startswith("debug_clockeddmi_dmi_req"): value = const_for(width) elif name.startswith("l2_frontend_bus_axi4_0_"): if name.endswith("_b_ready") or name.endswith("_r_ready"): value = "1'b1" else: value = const_for(width) elif name == "interrupts": value = "2'b00" elif name == "uart_rxd": value = "rs232_uart_rxd" elif name == "spi_dq_i": continue elif name == "pmod_spi_dq_i": continue elif name.startswith("mem_axi4_0_") or name.startswith("mmio_axi4_0_"): continue else: value = const_for(width) assigns.append(f" assign {name} = {value};") port_map = ",\n".join(f" .{name}({name})" for _, _, name in ports) led_debug = [] for candidate in ["debug_ndreset", "debug_dmactive", "debug_clockeddmi_dmi_req_ready"]: if candidate in port_by_name: led_debug.append(candidate) while len(led_debug) < 3: led_debug.append("1'b0") has_system_jtag = all(name in port_by_name for name in [ "debug_systemjtag_jtag_TCK", "debug_systemjtag_jtag_TMS", "debug_systemjtag_jtag_TDI", "debug_systemjtag_jtag_TDO_data", ]) has_clocked_dmi = all(name in port_by_name for name in [ "debug_clockeddmi_dmi_req_ready", "debug_clockeddmi_dmi_req_valid", "debug_clockeddmi_dmi_req_bits_addr", "debug_clockeddmi_dmi_req_bits_data", "debug_clockeddmi_dmi_req_bits_op", "debug_clockeddmi_dmi_resp_ready", "debug_clockeddmi_dmi_resp_valid", "debug_clockeddmi_dmi_resp_bits_data", "debug_clockeddmi_dmi_resp_bits_resp", "debug_clockeddmi_dmiClock", "debug_clockeddmi_dmiReset", ]) bscan_block = "" if has_clocked_dmi: bscan_block = """\ wire bscan_capture; wire bscan_drck; wire bscan_reset; wire bscan_runtest; wire bscan_sel; wire bscan_shift; wire bscan_tck; wire bscan_tdi; wire bscan_tms; wire bscan_tdo; wire bscan_update; BSCANE2 #( .DISABLE_JTAG("FALSE"), .JTAG_CHAIN(4) ) u_rocket_bscan ( .CAPTURE(bscan_capture), .DRCK(bscan_drck), .RESET(bscan_reset), .RUNTEST(bscan_runtest), .SEL(bscan_sel), .SHIFT(bscan_shift), .TCK(bscan_tck), .TDI(bscan_tdi), .TMS(bscan_tms), .UPDATE(bscan_update), .TDO(bscan_tdo) ); rocket_bscan_dmi_tunnel u_rocket_bscan_dmi_tunnel ( .tck(bscan_tck), .reset(fabric_reset | bscan_reset), .bscan_capture(bscan_capture), .bscan_sel(bscan_sel), .bscan_shift(bscan_shift), .bscan_tdi(bscan_tdi), .bscan_update(bscan_update), .bscan_tdo(bscan_tdo), .dmi_clock(debug_clockeddmi_dmiClock), .dmi_reset(debug_clockeddmi_dmiReset), .dmi_req_ready(debug_clockeddmi_dmi_req_ready), .dmi_req_valid(debug_clockeddmi_dmi_req_valid), .dmi_req_addr(debug_clockeddmi_dmi_req_bits_addr), .dmi_req_data(debug_clockeddmi_dmi_req_bits_data), .dmi_req_op(debug_clockeddmi_dmi_req_bits_op), .dmi_resp_ready(debug_clockeddmi_dmi_resp_ready), .dmi_resp_valid(debug_clockeddmi_dmi_resp_valid), .dmi_resp_data(debug_clockeddmi_dmi_resp_bits_data), .dmi_resp_resp(debug_clockeddmi_dmi_resp_bits_resp) ); """ elif has_system_jtag: bscan_block = """\ wire bscan_capture; wire bscan_drck; wire bscan_reset; wire bscan_runtest; wire bscan_sel; wire bscan_shift; wire bscan_tck; wire bscan_tdi; wire bscan_tms; wire bscan_update; BSCANE2 #( .DISABLE_JTAG("FALSE"), .JTAG_CHAIN(1) ) u_rocket_bscan ( .CAPTURE(bscan_capture), .DRCK(bscan_drck), .RESET(bscan_reset), .RUNTEST(bscan_runtest), .SEL(bscan_sel), .SHIFT(bscan_shift), .TCK(bscan_tck), .TDI(bscan_tdi), .TMS(bscan_tms), .UPDATE(bscan_update), .TDO(debug_systemjtag_jtag_TDO_data) ); """ has_spi_flash = all(name in port_by_name for name in [ "spi_sck", "spi_csn", "spi_dq_i", "spi_dq_o", "spi_dq_oe", ]) startup_block = "" if has_spi_flash: startup_block = """\ wire [3:0] cfg_flash_dq_i; wire cfg_flash_eos; assign spi_dq_i = cfg_flash_dq_i; STARTUPE3 #( .PROG_USR("FALSE"), .SIM_CCLK_FREQ(0.0) ) u_cfg_flash_startup ( .CFGCLK(), .CFGMCLK(), .DI(cfg_flash_dq_i), .EOS(cfg_flash_eos), .PREQ(), .DO(spi_dq_o), .DTS(~spi_dq_oe), .FCSBO(spi_csn), .FCSBTS(1'b0), .GSR(1'b0), .GTS(1'b0), .KEYCLEARB(1'b1), .PACK(1'b0), .USRCCLKO(spi_sck), .USRCCLKTS(1'b0), .USRDONEO(1'b1), .USRDONETS(1'b1) ); """ has_pmod_spi = all(name in port_by_name for name in [ "pmod_spi_sck", "pmod_spi_csn", "pmod_spi_dq_i", "pmod_spi_dq_o", "pmod_spi_dq_oe", ]) pmod_spi_top_ports = "" pmod_spi_block = "" if has_pmod_spi: pmod_spi_top_ports = """\ output wire pmod_spi_sck, output wire pmod_spi_csn, inout wire [3:0] pmod_spi_dq, """ pmod_spi_block = """\ assign pmod_spi_dq_i = pmod_spi_dq; assign pmod_spi_dq[0] = pmod_spi_dq_oe[0] ? pmod_spi_dq_o[0] : 1'bz; assign pmod_spi_dq[1] = pmod_spi_dq_oe[1] ? pmod_spi_dq_o[1] : 1'bz; assign pmod_spi_dq[2] = pmod_spi_dq_oe[2] ? pmod_spi_dq_o[2] : 1'bz; assign pmod_spi_dq[3] = pmod_spi_dq_oe[3] ? pmod_spi_dq_o[3] : 1'bz; """ pmod_irq_top_ports = "" if "pmod_irq" in port_by_name: pmod_irq_top_ports = """\ input wire pmod_irq, """ pps_top_ports = "" if port_by_name.get("gps_pps") == ("output", ""): pps_top_ports = """\ output wire gps_pps, """ rf_top_ports = "" eth_top_ports = "" rf_extra_wires = "" if args.rf_input_mode == "pmod": rf_top_ports = """\ // External RF PMOD input. VCU118 PMOD connector side is 3.3 V through a level shifter. input wire rf_clk_pmod, input wire [3:0] rf_data_pmod, """ rf_clock_block = """\ wire rf_clk_pmod_ibuf; // PMOD mode removes the Ethernet RF path and clocks GPS RF from the external sampler. IBUF u_rf_clk_pmod_ibuf ( .I(rf_clk_pmod), .O(rf_clk_pmod_ibuf) ); BUFG u_rf_clk_pmod_buf ( .I(rf_clk_pmod_ibuf), .O(gps_rf_clk_selected) ); assign gps_rf_data_selected = rf_data_pmod; assign gps_rf_ready = 1'b1; """ eth_block = "" led_prefix = "rf_data_pmod" else: rf_extra_wires = """\ wire gps_rf_clk_gen; wire gps_rf_clkfb; wire gps_rf_clkfb_buf; wire pll_gps_rf_exact_clk; wire gps_rf_pll_locked; """ rf_clock_block = """\ // Internal RF clock used by generated and Ethernet RF modes. MMCME4_ADV #( .BANDWIDTH("OPTIMIZED"), .CLKFBOUT_MULT_F(42.625), .CLKFBOUT_PHASE(0.000), .CLKIN1_PERIOD(3.333), .CLKOUT0_DIVIDE_F(78.125), .CLKOUT0_PHASE(0.000), .CLKOUT0_DUTY_CYCLE(0.500), .DIVCLK_DIVIDE(10), .STARTUP_WAIT("FALSE") ) u_gps_rf_mmcm ( .CLKIN1(sysclk_300), .CLKIN2(1'b0), .CLKINSEL(1'b1), .CLKFBIN(gps_rf_clkfb_buf), .CLKFBOUT(gps_rf_clkfb), .CLKFBOUTB(), .CLKOUT0(pll_gps_rf_exact_clk), .CLKOUT0B(), .CLKOUT1(), .CLKOUT1B(), .CLKOUT2(), .CLKOUT2B(), .CLKOUT3(), .CLKOUT3B(), .CLKOUT4(), .CLKOUT5(), .CLKOUT6(), .DADDR(7'd0), .DCLK(1'b0), .DEN(1'b0), .DI(16'd0), .DWE(1'b0), .DO(), .DRDY(), .LOCKED(gps_rf_pll_locked), .PSCLK(1'b0), .PSEN(1'b0), .PSINCDEC(1'b0), .PSDONE(), .PWRDWN(1'b0), .RST(cpu_reset), .CDDCDONE(), .CDDCREQ(1'b0) ); BUFG u_gps_rf_feedback_buf ( .I(gps_rf_clkfb), .O(gps_rf_clkfb_buf) ); BUFG u_gps_rf_clk_buf ( .I(pll_gps_rf_exact_clk), .O(gps_rf_clk_gen) ); assign gps_rf_clk_selected = gps_rf_clk_gen; assign gps_rf_ready = gps_rf_pll_locked; """ if args.rf_input_mode == "ethernet": eth_top_ports = """\ input wire phy_sgmii_rx_p, input wire phy_sgmii_rx_n, output wire phy_sgmii_tx_p, output wire phy_sgmii_tx_n, input wire phy_sgmii_clk_p, input wire phy_sgmii_clk_n, output wire phy_reset_n, input wire phy_int_n, inout wire phy_mdio, output wire phy_mdc, """ eth_block = """\ wire [3:0] ethernet_rf_data; wire [7:0] ethernet_rf_status; // Ethernet RF mode keeps the VCU118 PCS/PMA path for the host RF streamer. eth_rf_vcu118 u_ethernet_rf ( .mgmt_clk(fabric_clk), .mgmt_rst(fabric_reset), .rf_clk(gps_rf_clk_gen), .rf_rst(fabric_reset), .phy_sgmii_rx_p(phy_sgmii_rx_p), .phy_sgmii_rx_n(phy_sgmii_rx_n), .phy_sgmii_tx_p(phy_sgmii_tx_p), .phy_sgmii_tx_n(phy_sgmii_tx_n), .phy_sgmii_clk_p(phy_sgmii_clk_p), .phy_sgmii_clk_n(phy_sgmii_clk_n), .phy_reset_n(phy_reset_n), .phy_int_n(phy_int_n), .phy_mdio(phy_mdio), .phy_mdc(phy_mdc), .gps_rf_data(ethernet_rf_data), .status(ethernet_rf_status) ); assign gps_rf_data_selected = ethernet_rf_data; """ led_prefix = "ethernet_rf_status[7:4]" else: eth_block = """\ assign gps_rf_data_selected = 4'd0; """ led_prefix = "{heartbeat[25], heartbeat[24], 2'b00}" content = f"""`timescale 1ns/1ps module vcu118_rocket_top ( input wire sysclk1_300_p, input wire sysclk1_300_n, input wire cpu_reset, input wire rs232_uart_rxd, output wire rs232_uart_txd, {rf_top_ports}{eth_top_ports}{pmod_spi_top_ports}{pmod_irq_top_ports}{pps_top_ports}\ output wire [7:0] led ); wire sysclk_300; wire fabric_clk; wire gps_acq_clk_gen; wire gps_trck_clk_gen; wire gps_rf_clk_selected; wire [3:0] gps_rf_data_selected; wire gps_rf_ready; wire fabric_clkfb; wire fabric_clkfb_buf; wire gps_ref_clkfb; wire gps_ref_clkfb_buf; wire gps_ref_clk_gen; wire pll_gps_ref_clk; wire gps_ref_pll_locked; wire gps_clkfb; wire gps_clkfb_buf; wire pll_fabric_clk; wire pll_gps_acq_clk; wire pll_gps_trck_clk; wire fabric_pll_locked; wire gps_domain_pll_locked; wire gps_clock_locked = gps_ref_pll_locked & gps_domain_pll_locked; {rf_extra_wires} IBUFDS #( .DIFF_TERM("FALSE"), .IBUF_LOW_PWR("FALSE") ) u_sysclk_ibufds ( .I(sysclk1_300_p), .IB(sysclk1_300_n), .O(sysclk_300) ); MMCME4_ADV #( .BANDWIDTH("OPTIMIZED"), .CLKFBOUT_MULT_F(5.000), .CLKFBOUT_PHASE(0.000), .CLKIN1_PERIOD(3.333), .CLKOUT0_DIVIDE_F(91.625), .CLKOUT0_PHASE(0.000), .CLKOUT0_DUTY_CYCLE(0.500), .CLKOUT1_DIVIDE(15), .CLKOUT1_PHASE(0.000), .CLKOUT1_DUTY_CYCLE(0.500), .CLKOUT2_DIVIDE(12), .CLKOUT2_PHASE(0.000), .CLKOUT2_DUTY_CYCLE(0.500), .CLKOUT3_DIVIDE(15), .CLKOUT3_PHASE(0.000), .CLKOUT3_DUTY_CYCLE(0.500), .DIVCLK_DIVIDE(1), .STARTUP_WAIT("FALSE") ) u_clock_mmcm ( .CLKIN1(sysclk_300), .CLKIN2(1'b0), .CLKINSEL(1'b1), .CLKFBIN(fabric_clkfb_buf), .CLKFBOUT(fabric_clkfb), .CLKFBOUTB(), .CLKOUT0(), .CLKOUT0B(), .CLKOUT1(), .CLKOUT1B(), .CLKOUT2(), .CLKOUT2B(), .CLKOUT3(pll_fabric_clk), .CLKOUT3B(), .CLKOUT4(), .CLKOUT5(), .CLKOUT6(), .DADDR(7'd0), .DCLK(1'b0), .DEN(1'b0), .DI(16'd0), .DWE(1'b0), .DO(), .DRDY(), .LOCKED(fabric_pll_locked), .PSCLK(1'b0), .PSEN(1'b0), .PSINCDEC(1'b0), .PSDONE(), .PWRDWN(1'b0), .RST(cpu_reset), .CDDCDONE(), .CDDCREQ(1'b0) ); BUFG u_pll_feedback_buf ( .I(fabric_clkfb), .O(fabric_clkfb_buf) ); BUFG u_fabric_clk_buf ( .I(pll_fabric_clk), .O(fabric_clk) ); {rf_clock_block} // GPS processing clocks are synthesized from the RF sample clock, not the // board crystal. Two MMCM stages keep 100/125 MHz within 0.01 ppm of nominal // for the 16.367981 MHz sampler while leaving the Rocket fabric independent. MMCME4_ADV #( .BANDWIDTH("OPTIMIZED"), .CLKFBOUT_MULT_F(58.125), .CLKFBOUT_PHASE(0.000), .CLKIN1_PERIOD(61.095), .CLKOUT0_DIVIDE_F(17.125), .CLKOUT0_PHASE(0.000), .CLKOUT0_DUTY_CYCLE(0.500), .DIVCLK_DIVIDE(1), .STARTUP_WAIT("FALSE") ) u_gps_ref_mmcm ( .CLKIN1(gps_rf_clk_selected), .CLKIN2(1'b0), .CLKINSEL(1'b1), .CLKFBIN(gps_ref_clkfb_buf), .CLKFBOUT(gps_ref_clkfb), .CLKFBOUTB(), .CLKOUT0(pll_gps_ref_clk), .CLKOUT0B(), .CLKOUT1(), .CLKOUT1B(), .CLKOUT2(), .CLKOUT2B(), .CLKOUT3(), .CLKOUT3B(), .CLKOUT4(), .CLKOUT5(), .CLKOUT6(), .DADDR(7'd0), .DCLK(1'b0), .DEN(1'b0), .DI(16'd0), .DWE(1'b0), .DO(), .DRDY(), .LOCKED(gps_ref_pll_locked), .PSCLK(1'b0), .PSEN(1'b0), .PSINCDEC(1'b0), .PSDONE(), .PWRDWN(1'b0), .RST(cpu_reset), .CDDCDONE(), .CDDCREQ(1'b0) ); BUFG u_gps_ref_feedback_buf ( .I(gps_ref_clkfb), .O(gps_ref_clkfb_buf) ); BUFG u_gps_ref_clk_buf ( .I(pll_gps_ref_clk), .O(gps_ref_clk_gen) ); MMCME4_ADV #( .BANDWIDTH("OPTIMIZED"), .CLKFBOUT_MULT_F(18.000), .CLKFBOUT_PHASE(0.000), .CLKIN1_PERIOD(18.000), .CLKOUT0_DIVIDE_F(10.000), .CLKOUT0_PHASE(0.000), .CLKOUT0_DUTY_CYCLE(0.500), .CLKOUT1_DIVIDE(8), .CLKOUT1_PHASE(0.000), .CLKOUT1_DUTY_CYCLE(0.500), .DIVCLK_DIVIDE(1), .STARTUP_WAIT("FALSE") ) u_gps_domain_mmcm ( .CLKIN1(gps_ref_clk_gen), .CLKIN2(1'b0), .CLKINSEL(1'b1), .CLKFBIN(gps_clkfb_buf), .CLKFBOUT(gps_clkfb), .CLKFBOUTB(), .CLKOUT0(pll_gps_acq_clk), .CLKOUT0B(), .CLKOUT1(pll_gps_trck_clk), .CLKOUT1B(), .CLKOUT2(), .CLKOUT2B(), .CLKOUT3(), .CLKOUT3B(), .CLKOUT4(), .CLKOUT5(), .CLKOUT6(), .DADDR(7'd0), .DCLK(1'b0), .DEN(1'b0), .DI(16'd0), .DWE(1'b0), .DO(), .DRDY(), .LOCKED(gps_domain_pll_locked), .PSCLK(1'b0), .PSEN(1'b0), .PSINCDEC(1'b0), .PSDONE(), .PWRDWN(1'b0), .RST(cpu_reset | ~gps_ref_pll_locked), .CDDCDONE(), .CDDCREQ(1'b0) ); BUFG u_gps_domain_feedback_buf ( .I(gps_clkfb), .O(gps_clkfb_buf) ); BUFG u_gps_acq_clk_buf ( .I(pll_gps_acq_clk), .O(gps_acq_clk_gen) ); BUFG u_gps_trck_clk_buf ( .I(pll_gps_trck_clk), .O(gps_trck_clk_gen) ); // The Rocket/fabric clock and RAM cache must survive loss of the external RF // clock. gps_clock_ready independently resets only the GPS DSP domains. wire pll_ready_async = fabric_pll_locked & ~cpu_reset; (* async_reg = "true" *) reg [2:0] pll_ready_sync = 3'b000; reg [15:0] reset_shift = 16'hFFFF; always @(posedge fabric_clk) begin pll_ready_sync <= {{pll_ready_sync[1:0], pll_ready_async}}; if (!pll_ready_sync[2]) begin reset_shift <= 16'hFFFF; end else begin reset_shift <= {{reset_shift[14:0], 1'b0}}; end end wire fabric_reset = reset_shift[15]; reg [31:0] heartbeat; always @(posedge fabric_clk) begin if (fabric_reset) begin heartbeat <= 32'd0; end else begin heartbeat <= heartbeat + 32'd1; end end {chr(10).join(decl(width, name) for _, width, name in ports if name not in top_passthrough_ports)} wire soc_reset = {"fabric_reset | debug_ndreset" if "debug_ndreset" in port_by_name else "fabric_reset"}; {bscan_block} {startup_block} {pmod_spi_block} {eth_block} {chr(10).join(assigns)} assign led = {{ {led_prefix}, fabric_reset, {led_debug[2]}, {led_debug[1]}, {led_debug[0]} }}; assign rs232_uart_txd = {"uart_txd" if "uart_txd" in port_by_name else "1'b1"}; {connect("mem", "axi4_ram_64", 32) if has_axi_slave("mem") else ""} {connect("mmio", "axi4_slave_tieoff_64", 31) if has_axi_slave("mmio") else ""} (* dont_touch = "true", keep_hierarchy = "yes" *) {Path(args.rocket_top).stem} u_rocket ( {port_map} ); endmodule """ Path(args.out).parent.mkdir(parents=True, exist_ok=True) Path(args.out).write_text(content) if __name__ == "__main__": main()