module digital_pll(
`ifdef USE_POWER_PINS
    VPWR,
    VGND,
`endif
    resetb, enable, osc, clockp, div, dco, ext_trim);

`ifdef USE_POWER_PINS
    input VPWR;
    input VGND;
`endif

    input	 resetb;	// Sense negative reset
    input	 enable;	// Enable PLL
    input	 osc;		// Input oscillator to match
    input [4:0]	 div;		// PLL feedback division ratio
    input 	 dco;		// Run in DCO mode
    input [25:0] ext_trim;	// External trim for DCO mode

    output [1:0] clockp;	// Two 90 degree clock phases

    wire [1:0]   clockp_buffer_in;	// Input wires to clockp buffers
    wire [25:0]  itrim;		// Internally generated trim bits
    wire [25:0]  otrim;		// Trim bits applied to the ring oscillator
    wire	 creset;	// Controller reset
    wire	 ireset;	// Internal reset (external reset OR disable)

    assign ireset = ~resetb | ~enable;

    // In DCO mode: Hold controller in reset and apply external trim value

    assign itrim = (dco == 1'b0) ? otrim : ext_trim;
    assign creset = (dco == 1'b0) ? ireset : 1'b1;

    (* keep *)
    ring_osc2x13 ringosc (
        .reset(ireset),
        .trim(itrim),
        .clockp(clockp_buffer_in)
    );

    digital_pll_controller pll_control (
        .reset(creset),
        .clock(clockp_buffer_in[0]),
        .osc(osc),
        .div(div),
        .trim(otrim)
    );

    (* keep *)
    sky130_fd_sc_hd__clkbuf_16 clockp_buffer_0 (
`ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
`endif
        .A(clockp_buffer_in[0]),
        .X(clockp[0])
    );

    (* keep *)
    sky130_fd_sc_hd__clkbuf_16 clockp_buffer_1 (
`ifdef USE_POWER_PINS
        .VPWR(VPWR),
        .VGND(VGND),
        .VPB(VPWR),
        .VNB(VGND),
`endif
        .A(clockp_buffer_in[1]),
        .X(clockp[1])
    );

endmodule