caravel/verilog/rtl/digital_pll.v

99 lines
2.6 KiB
Verilog

// SPDX-FileCopyrightText: 2020 Efabless Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0
`default_nettype none
// Digital PLL (ring oscillator + controller)
// Technically this is a frequency locked loop, not a phase locked loop.
`ifndef SIM
`include "digital_pll_controller.v"
`include "ring_osc2x13.v"
`endif
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;
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
`default_nettype wire