Started adding RTL for the Caravel project
diff --git a/verilog/rtl/digital_pll.v b/verilog/rtl/digital_pll.v
new file mode 100644
index 0000000..fe564cb
--- /dev/null
+++ b/verilog/rtl/digital_pll.v
@@ -0,0 +1,97 @@
+// Digital PLL (ring oscillator + controller)
+// Technically this is a frequency locked loop, not a phase locked loop.
+
+`include "digital_pll_controller.v"
+`include "ring_osc2x13.v"
+
+module digital_pll(reset, extclk_sel, osc, clockc, clockp, clockd, div, sel, dco, ext_trim);
+
+ input reset; // Sense positive reset
+ input extclk_sel; // External clock select (acts as 2nd reset)
+ input osc; // Input oscillator to match
+ input [4:0] div; // PLL feedback division ratio
+ input [2:0] sel; // Core clock select
+ input dco; // Run in DCO mode
+ input [25:0] ext_trim; // External trim for DCO mode
+
+ output clockc; // Selected core clock output
+ output [1:0] clockp; // Two 90 degree clock phases
+ output [3:0] clockd; // Divided clock (2, 4, 8, 16)
+
+ wire [25:0] itrim; // Internally generated trim bits
+ wire [25:0] otrim; // Trim bits applied to the ring oscillator
+ wire [3:0] nint; // Internal divided down clocks
+ wire resetb; // Internal positivie sense reset
+ wire creset; // Controller reset
+ wire ireset; // Internal reset (external reset OR extclk_sel)
+
+ assign ireset = reset | extclk_sel;
+
+ // 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)
+ );
+
+ digital_pll_controller pll_control (
+ .reset(creset),
+ .clock(clockp[0]),
+ .osc(osc),
+ .div(div),
+ .trim(otrim)
+ );
+
+ // Select core clock output
+ assign clockc = (sel == 3'b000) ? clockp[0] :
+ (sel == 3'b001) ? clockd[0] :
+ (sel == 3'b010) ? clockd[1] :
+ (sel == 3'b011) ? clockd[2] :
+ clockd[3];
+
+ // Derive negative-sense reset from the input positive-sense reset
+
+ sky130_fd_sc_hd__inv_4 irb (
+ .A(reset),
+ .Y(resetb)
+ );
+
+ // Create divided down clocks. The inverted output only comes
+ // with digital standard cells with inverted resets, so the
+ // reset has to be inverted as well.
+
+ sky130_fd_sc_hd__dfrbp_1 idiv2 (
+ .CLK(clockp[1]),
+ .D(clockd[0]),
+ .Q(nint[0]),
+ .QN(clockd[0]),
+ .RESETB(resetb)
+ );
+
+ sky130_fd_sc_hd__dfrbp_1 idiv4 (
+ .CLK(clockd[0]),
+ .D(clockd[1]),
+ .Q(nint[1]),
+ .QN(clockd[1]),
+ .RESETB(resetb)
+ );
+
+ sky130_fd_sc_hd__dfrbp_1 idiv8 (
+ .CLK(clockd[1]),
+ .D(clockd[2]),
+ .Q(nint[2]),
+ .QN(clockd[2]),
+ .RESETB(resetb)
+ );
+
+ sky130_fd_sc_hd__dfrbp_1 idiv16 (
+ .CLK(clockd[2]),
+ .D(clockd[3]),
+ .Q(nint[3]),
+ .QN(clockd[3]),
+ .RESETB(resetb)
+ );
+endmodule