// 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 // Tunable ring oscillator---synthesizable (physical) version. // // NOTE: This netlist cannot be simulated correctly due to lack // of accurate timing in the digital cell verilog models. module delay_stage(in, trim, out); input in; input [1:0] trim; output out; wire d0, d1, d2, ts; sky130_fd_sc_hd__clkbuf_2 delaybuf0 ( .A(in), .X(ts) ); sky130_fd_sc_hd__clkbuf_1 delaybuf1 ( .A(ts), .X(d0) ); sky130_fd_sc_hd__einvp_2 delayen1 ( .A(d0), .TE(trim[1]), .Z(d1) ); sky130_fd_sc_hd__einvn_4 delayenb1 ( .A(ts), .TE_B(trim[1]), .Z(d1) ); sky130_fd_sc_hd__clkinv_1 delayint0 ( .A(d1), .Y(d2) ); sky130_fd_sc_hd__einvp_2 delayen0 ( .A(d2), .TE(trim[0]), .Z(out) ); sky130_fd_sc_hd__einvn_8 delayenb0 ( .A(ts), .TE_B(trim[0]), .Z(out) ); endmodule module start_stage(in, trim, reset, out); input in; input [1:0] trim; input reset; output out; wire d0, d1, d2, ctrl0, one; sky130_fd_sc_hd__clkbuf_1 delaybuf0 ( .A(in), .X(d0) ); sky130_fd_sc_hd__einvp_2 delayen1 ( .A(d0), .TE(trim[1]), .Z(d1) ); sky130_fd_sc_hd__einvn_4 delayenb1 ( .A(in), .TE_B(trim[1]), .Z(d1) ); sky130_fd_sc_hd__clkinv_1 delayint0 ( .A(d1), .Y(d2) ); sky130_fd_sc_hd__einvp_2 delayen0 ( .A(d2), .TE(trim[0]), .Z(out) ); sky130_fd_sc_hd__einvn_8 delayenb0 ( .A(in), .TE_B(ctrl0), .Z(out) ); sky130_fd_sc_hd__einvp_1 reseten0 ( .A(one), .TE(reset), .Z(out) ); sky130_fd_sc_hd__or2_2 ctrlen0 ( .A(reset), .B(trim[0]), .X(ctrl0) ); sky130_fd_sc_hd__conb_1 const1 ( .HI(one), .LO() ); endmodule // Ring oscillator with 13 stages, each with two trim bits delay // (see above). Trim is not binary: For trim[1:0], lower bit // trim[0] is primary trim and must be applied first; upper // bit trim[1] is secondary trim and should only be applied // after the primary trim is applied, or it has no effect. // // Total effective number of inverter stages in this oscillator // ranges from 13 at trim 0 to 65 at trim 24. The intention is // to cover a range greater than 2x so that the midrange can be // reached over all PVT conditions. // // Frequency of this ring oscillator under SPICE simulations at // nominal PVT is maximum 214 MHz (trim 0), minimum 90 MHz (trim 24). module ring_osc2x13(reset, trim, clockp); input reset; input [25:0] trim; output[1:0] clockp; `ifdef FUNCTIONAL // i.e., behavioral model below reg [1:0] clockp; reg hiclock; integer i; real delay; wire [5:0] bcount; assign bcount = trim[0] + trim[1] + trim[2] + trim[3] + trim[4] + trim[5] + trim[6] + trim[7] + trim[8] + trim[9] + trim[10] + trim[11] + trim[12] + trim[13] + trim[14] + trim[15] + trim[16] + trim[17] + trim[18] + trim[19] + trim[20] + trim[21] + trim[22] + trim[23] + trim[24] + trim[25]; initial begin hiclock <= 1'b0; delay = 3.0; end // Fastest operation is 214 MHz = 4.67ns // Delay per trim is 0.02385 // Run "hiclock" at 2x this rate, then use positive and negative // edges to derive the 0 and 90 degree phase clocks. always #delay begin hiclock <= (hiclock === 1'b0); end always @(trim) begin // Implement trim as a variable delay, one delay per trim bit delay = 1.168 + 0.012 * $itor(bcount); end always @(posedge hiclock or posedge reset) begin if (reset == 1'b1) begin clockp[0] <= 1'b0; end else begin clockp[0] <= (clockp[0] === 1'b0); end end always @(negedge hiclock or posedge reset) begin if (reset == 1'b1) begin clockp[1] <= 1'b0; end else begin clockp[1] <= (clockp[1] === 1'b0); end end `else // !FUNCTIONAL; i.e., gate level netlist below wire [1:0] clockp; wire [12:0] d; wire [1:0] c; // Main oscillator loop stages genvar i; generate for (i = 0; i < 12; i = i + 1) begin : dstage delay_stage id ( .in(d[i]), .trim({trim[i+13], trim[i]}), .out(d[i+1]) ); end endgenerate // Reset/startup stage start_stage iss ( .in(d[12]), .trim({trim[25], trim[12]}), .reset(reset), .out(d[0]) ); // Buffered outputs a 0 and 90 degrees phase (approximately) sky130_fd_sc_hd__clkinv_2 ibufp00 ( .A(d[0]), .Y(c[0]) ); sky130_fd_sc_hd__clkinv_8 ibufp01 ( .A(c[0]), .Y(clockp[0]) ); sky130_fd_sc_hd__clkinv_2 ibufp10 ( .A(d[6]), .Y(c[1]) ); sky130_fd_sc_hd__clkinv_8 ibufp11 ( .A(c[1]), .Y(clockp[1]) ); `endif // !FUNCTIONAL endmodule `default_nettype wire