| // Digital PLL (ring oscillator + controller) |
| // Technically this is a frequency locked loop, not a phase locked loop. |
| |
| `include "cells.v" |
| `include "digital_pll_controller.v" |
| `include "ring_osc2x13.v" |
| |
| module digital_pll(reset, osc, clockp, clockd, div); |
| |
| input reset; // Sense positive reset |
| input osc; // Input oscillator to match |
| input [4:0] div; // PLL feedback division ratio |
| |
| output [1:0] clockp; // Two 90 degree clock phases |
| output [3:0] clockd; // Divided clock (2, 4, 8, 16) |
| |
| wire [25:0] trim; // Internally generated trim bits |
| wire [3:0] nint; // Internal divided down clocks |
| wire resetb; // Internal positivie sense reset |
| |
| ring_osc2x13 ringosc ( |
| .reset(reset), |
| .trim(trim), |
| .clockp(clockp) |
| ); |
| |
| digital_pll_controller pll_control ( |
| .reset(reset), |
| .clock(clockp[0]), |
| .osc(osc), |
| .div(div), |
| .trim(trim) |
| ); |
| |
| // Derive negative-sense reset from the input positive-sense reset |
| |
| scs8hd_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. |
| |
| scs8hd_dfrbp_1 idiv2 ( |
| .CLK(clockp[1]), |
| .D(clockd[0]), |
| .Q(nint[0]), |
| .QN(clockd[0]), |
| .RESETB(resetb) |
| ); |
| |
| scs8hd_dfrbp_1 idiv4 ( |
| .CLK(clockd[0]), |
| .D(clockd[1]), |
| .Q(nint[1]), |
| .QN(clockd[1]), |
| .RESETB(resetb) |
| ); |
| |
| scs8hd_dfrbp_1 idiv8 ( |
| .CLK(clockd[1]), |
| .D(clockd[2]), |
| .Q(nint[2]), |
| .QN(clockd[2]), |
| .RESETB(resetb) |
| ); |
| |
| scs8hd_dfrbp_1 idiv16 ( |
| .CLK(clockd[2]), |
| .D(clockd[3]), |
| .Q(nint[3]), |
| .QN(clockd[3]), |
| .RESETB(resetb) |
| ); |
| endmodule |