Add ringosc and tweak build
diff --git a/ip/randsack/rtl/collapsering.v b/ip/randsack/rtl/collapsering.v index 04ce4c9..6c686ad 100644 --- a/ip/randsack/rtl/collapsering.v +++ b/ip/randsack/rtl/collapsering.v
@@ -106,7 +106,7 @@ ); -sky130_fd_sc_hd__clkbuf_4 +sky130_fd_sc_hd__clkbuf_8 #( ) x35 (
diff --git a/ip/randsack/rtl/collapsering_macro.v b/ip/randsack/rtl/collapsering_macro.v index fd17492..1b4c50d 100644 --- a/ip/randsack/rtl/collapsering_macro.v +++ b/ip/randsack/rtl/collapsering_macro.v
@@ -42,6 +42,12 @@ reg [31:0] clk_cnt; reg fake_clk; + wire [31:0] max_cnt = trim_a + trim_b + clkmux; + + always @(max_cnt) begin + $display("collapsering_macro max count = 'h%h", max_cnt); + end + initial begin clk_cnt <= 0; fake_clk <= 1'b0; @@ -57,7 +63,7 @@ always #5 fake_clk <= ~fake_clk; - assign clk_out = fake_clk & start & (clk_cnt < 100); + assign clk_out = fake_clk & start & (clk_cnt < max_cnt); `endif endmodule // module collapsering_macro
diff --git a/ip/randsack/rtl/digitalcore_macro.v b/ip/randsack/rtl/digitalcore_macro.v index 9c41fb7..16e2be4 100644 --- a/ip/randsack/rtl/digitalcore_macro.v +++ b/ip/randsack/rtl/digitalcore_macro.v
@@ -51,7 +51,13 @@ output ring0_start, output [27:0] ring0_trim_a, output [27:0] ring0_trim_b, - output [2:0] ring0_clkmux + output [2:0] ring0_clkmux, + + // ring1 collapsering macro + input ring1_clk, + output ring1_start, + output [25:0] ring1_trim_a, + output [2:0] ring1_clkmux ); // Filter wishbone accesses from Caravel. @@ -67,6 +73,8 @@ parameter UART0_BASE_ADDR = 32'h3082_0000; parameter RING0_ADDR_MASK = 32'hffff_0000; parameter RING0_BASE_ADDR = 32'h3083_0000; + parameter RING1_ADDR_MASK = 32'hffff_0000; + parameter RING1_BASE_ADDR = 32'h3084_0000; // Filter addresses from Caravel since we want to be absolutely sure it is // selecting us before letting it access the arbiter. This is mostly needed @@ -75,7 +83,7 @@ wire wbs_addr_sel; assign wbs_addr_sel = (wbs_adr_i & DTOP_MASK) == DTOP_ADDR; - wb_mux_3 interconnect ( + wb_mux_4 interconnect ( .wbm_adr_i(wbs_adr_i), .wbm_dat_i(wbs_dat_i), .wbm_dat_o(wbs_dat_o), @@ -124,7 +132,20 @@ .wbs2_rty_i(1'b0), .wbs2_cyc_o(ring0_cyc_i), .wbs2_addr(RING0_BASE_ADDR), - .wbs2_addr_msk(RING0_ADDR_MASK) + .wbs2_addr_msk(RING0_ADDR_MASK), + + .wbs3_adr_o(ring1_adr_i), + .wbs3_dat_i(ring1_dat_o), + .wbs3_dat_o(ring1_dat_i), + .wbs3_we_o(ring1_we_i), + .wbs3_sel_o(ring1_sel_i), + .wbs3_stb_o(ring1_stb_i), + .wbs3_ack_i(ring1_ack_o), + .wbs3_err_i(1'b0), + .wbs3_rty_i(1'b0), + .wbs3_cyc_o(ring1_cyc_i), + .wbs3_addr(RING1_BASE_ADDR), + .wbs3_addr_msk(RING1_ADDR_MASK) ); // GPIO signals. @@ -204,6 +225,8 @@ wire ring0_stb_i; wire ring0_ack_o; wire [31:0] ring0_dat_o; + wire ring0_test_en; + wire ring0_test_out; ring_control #( .CLKMUX_BITS(3), @@ -226,17 +249,59 @@ .ring_start(ring0_start), .ring_trim_a(ring0_trim_a), .ring_trim_b(ring0_trim_b), - .ring_clkmux(ring0_clkmux) + .ring_clkmux(ring0_clkmux), + + .test_en(ring0_test_en), + .test_out(ring0_test_out) + ); + + // RING1 signals. + wire [31:0] ring1_adr_i; + wire [31:0] ring1_dat_i; + wire [3:0] ring1_sel_i; + wire ring1_we_i; + wire ring1_cyc_i; + wire ring1_stb_i; + wire ring1_ack_o; + wire [31:0] ring1_dat_o; + wire ring1_test_en; + wire ring1_test_out; + + ring_control #( + .CLKMUX_BITS(3), + .TRIM_BITS(26) + ) ring1 ( + .wb_clk_i(wb_clk_i), + .wb_rst_i(wb_rst_i), + + .wb_stb_i(ring1_stb_i), + .wb_cyc_i(ring1_cyc_i), + .wb_we_i(ring1_we_i), + .wb_sel_i(ring1_sel_i), + .wb_dat_i(ring1_dat_i), + .wb_adr_i(ring1_adr_i), + + .wb_ack_o(ring1_ack_o), + .wb_dat_o(ring1_dat_o), + + .ring_clk(ring1_clk), + .ring_start(ring1_start), + .ring_trim_a(ring1_trim_a), + .ring_trim_b(), + .ring_clkmux(ring1_clkmux), + + .test_en(ring1_test_en), + .test_out(ring1_test_out) ); // Connect up external ports. assign gpio_in = io_in[37:6]; - assign uart_rx = io_in[2]; + assign uart_rx = io_in[35]; - assign io_out[5:0] = {1'b0, uart_tx, 4'b0}; - assign io_out[37:6] = gpio_out; - assign io_oeb[5:0] = {1'b1, ~uart_enabled, 4'b1}; - assign io_oeb[37:6] = gpio_oeb; + assign io_out[5:0] = 6'b0; + assign io_out[37:6] = gpio_out | {uart_tx & uart_enabled, 4'b0, ring0_test_out, 26'b0}; + assign io_oeb[5:0] = 6'b0; + assign io_oeb[37:6] = gpio_oeb & {~uart_enabled, {4{1'b1}}, ~ring0_test_en, {26{1'b1}}}; assign la_data_out = 128'b0;
diff --git a/ip/randsack/rtl/ring_control.v b/ip/randsack/rtl/ring_control.v index 5efe222..cc01661 100644 --- a/ip/randsack/rtl/ring_control.v +++ b/ip/randsack/rtl/ring_control.v
@@ -36,7 +36,10 @@ output reg ring_start, output reg [TRIM_BITS-1:0] ring_trim_a, output reg [TRIM_BITS-1:0] ring_trim_b, - output reg [CLKMUX_BITS-1:0] ring_clkmux + output reg [CLKMUX_BITS-1:0] ring_clkmux, + + output reg test_en, + output test_out ); // Register addresses. localparam COUNT_VALUE_ADDR = 8'h00; @@ -59,6 +62,9 @@ reg counter_resetb; reg [16:0] counter_value; + // Test port mux. + assign test_out = test_en ? ring_clk : 1'b0; + // Ring oscillator counter. // NOTE: This reset is pretty nasty, but the idea is we have full control // over the reset timing so we don't need to synchronize it. @@ -77,9 +83,10 @@ wb_dat_o <= 32'h0; counter_resetb <= 1'b0; ring_start <= 1'b0; - ring_clkmux <= {CLKMUX_BITS{1'b1}}; - ring_trim_a <= {TRIM_BITS{1'b1}}; - ring_trim_b <= {TRIM_BITS{1'b1}}; + ring_clkmux <= {CLKMUX_BITS{1'b0}}; + ring_trim_a <= {TRIM_BITS{1'b0}}; + ring_trim_b <= {TRIM_BITS{1'b0}}; + test_en <= 1'b0; end else begin wb_ack_o <= 1'b0; @@ -89,6 +96,7 @@ if (control_sel) begin counter_resetb <= ~wb_dat_i[0]; ring_start <= wb_dat_i[1]; + test_en <= wb_dat_i[2]; ring_clkmux <= wb_dat_i[CLKMUX_BITS-1+8:8]; end else if (trima_sel) begin ring_trim_a <= wb_dat_i[TRIM_BITS-1:0];
diff --git a/ip/randsack/rtl/ringosc_macro.v b/ip/randsack/rtl/ringosc_macro.v new file mode 100644 index 0000000..6a7011c --- /dev/null +++ b/ip/randsack/rtl/ringosc_macro.v
@@ -0,0 +1,74 @@ +// SPDX-FileCopyrightText: 2021 Harrison Pham +// +// 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 + +module ringosc_macro #( + parameter TRIM_BITS = 26 +) ( +`ifdef USE_POWER_PINS + inout vccd1, + inout vssd1, +`endif + + input start, + input [TRIM_BITS-1:0] trim_a, + input [2:0] clkmux, + + output clk_out +); + + wire [1:0] clockp; + wire clk = clockp[0]; + + ring_osc2x13 ring ( + .reset(~start), + .trim(trim_a), + .clockp(clockp) + ); + + // Clock dividers. + reg s0; + always @(posedge clk or negedge start) begin + if (!start) begin + s0 <= 1'b0; + end else begin + s0 <= ~s0; + end + end + + reg s1; + always @(posedge s0 or negedge start) begin + if (!start) begin + s1 <= 1'b0; + end else begin + s1 <= ~s1; + end + end + + reg s2; + always @(posedge s1 or negedge start) begin + if (!start) begin + s2 <= 1'b0; + end else begin + s2 <= ~s2; + end + end + + assign clk_out = (clkmux == 3'b000) ? clk : + (clkmux == 3'b001) ? s0 : + (clkmux == 3'b010) ? s1 : + (clkmux == 3'b011) ? s2 : + clk; + +endmodule // module ringosc_macro
diff --git a/ip/randsack/sch/collapsering.sch b/ip/randsack/sch/collapsering.sch index 2550fff..982a316 100644 --- a/ip/randsack/sch/collapsering.sch +++ b/ip/randsack/sch/collapsering.sch
@@ -305,7 +305,7 @@ C {devices/title-2.sym} 0 -40 0 0 {name=l26 author="Harrison Pham" rev=1.0} C {devices/lab_wire.sym} 3100 -1140 0 0 {name=l18 sig_type=std_logic lab=outb} C {devices/lab_wire.sym} 3100 -1530 0 0 {name=l9 sig_type=std_logic lab=outa} -C {sky130_stdcells/clkbuf_4.sym} 3160 -800 0 0 {name=x35 VGND=VGND VNB=VNB VPB=VPB VPWR=VPWR prefix=sky130_fd_sc_hd__ } +C {sky130_stdcells/clkbuf_8.sym} 3160 -800 0 0 {name=x35 VGND=VGND VNB=VNB VPB=VPB VPWR=VPWR prefix=sky130_fd_sc_hd__ } C {devices/opin.sym} 3230 -800 0 0 {name=p1 lab=CLKBUFOUT} C {devices/ipin.sym} 110 -1690 0 0 {name=p2 lab=START} C {devices/lab_pin.sym} 400 -1660 0 0 {name=l1 sig_type=std_logic lab=TRIMA[0]}
diff --git a/ip/third_party/caravel/ring_osc2x13.v b/ip/third_party/caravel/ring_osc2x13.v new file mode 100644 index 0000000..f20110e --- /dev/null +++ b/ip/third_party/caravel/ring_osc2x13.v
@@ -0,0 +1,250 @@ +// 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
diff --git a/openlane/collapsering_macro/config.tcl b/openlane/collapsering_macro/config.tcl index f73eedc..76760b1 100755 --- a/openlane/collapsering_macro/config.tcl +++ b/openlane/collapsering_macro/config.tcl
@@ -26,11 +26,12 @@ # Disable optimizations and CTS to preserve our hand picked stdcells. set ::env(SYNTH_BUFFERING) 0 +set ::env(SYNTH_SIZING) 0 set ::env(SYNTH_SHARE_RESOURCES) 0 +set ::env(CLOCK_TREE_SYNTH) 0 set ::env(PL_RESIZER_DESIGN_OPTIMIZATIONS) 0 set ::env(PL_RESIZER_TIMING_OPTIMIZATIONS) 0 set ::env(PL_OPENPHYSYN_OPTIMIZATIONS) 0 -set ::env(CLOCK_TREE_SYNTH) 0 set ::env(GLB_RESIZER_TIMING_OPTIMIZATIONS) 0 set ::env(DESIGN_IS_CORE) 0 @@ -44,12 +45,13 @@ set ::env(CLOCK_PERIOD) "10" set ::env(FP_SIZING) absolute +# 85 85 is optimal but wont fit into PDN set ::env(DIE_AREA) "0 0 50 150" set ::env(FP_PIN_ORDER_CFG) $script_dir/pin_order.cfg set ::env(PL_BASIC_PLACEMENT) 1 -set ::env(PL_TARGET_DENSITY) 0.5 +set ::env(PL_TARGET_DENSITY) 0.75 # Maximum layer used for routing is metal 4. # This is because this macro will be inserted in a top level (user_project_wrapper)
diff --git a/openlane/collapsering_macro/pin_order.cfg b/openlane/collapsering_macro/pin_order.cfg index 46201b2..1a9c694 100644 --- a/openlane/collapsering_macro/pin_order.cfg +++ b/openlane/collapsering_macro/pin_order.cfg
@@ -9,6 +9,6 @@ #E trim_a.* +trim_b.* #W -trim_b.*
diff --git a/openlane/digitalcore_macro/base.sdc b/openlane/digitalcore_macro/base.sdc index 5efe131..c1a7a33 100644 --- a/openlane/digitalcore_macro/base.sdc +++ b/openlane/digitalcore_macro/base.sdc
@@ -15,12 +15,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -set ::env(WB_CLOCK_PERIOD) "10" +set ::env(WB_CLOCK_PERIOD) "15" set ::env(WB_CLOCK_PORT) "wb_clk_i" -set ::env(RING0_CLOCK_PERIOD) "10" +set ::env(RING0_CLOCK_PERIOD) "15" set ::env(RING0_CLOCK_PORT) "ring0_clk" +set ::env(RING1_CLOCK_PERIOD) "15" +set ::env(RING1_CLOCK_PORT) "ring1_clk" + if {[info exists ::env(WB_CLOCK_PORT)] && $::env(WB_CLOCK_PORT) != ""} { create_clock [get_ports $::env(WB_CLOCK_PORT)] -name $::env(WB_CLOCK_PORT) -period $::env(CLOCK_PERIOD) } else { @@ -55,3 +58,4 @@ # Extra clocks for macros. # NOTE: These don't need any input/output delays since this design just uses it for clock counting. create_clock [get_ports $::env(RING0_CLOCK_PORT)] -name $::env(RING0_CLOCK_PORT) -period $::env(RING0_CLOCK_PERIOD) +create_clock [get_ports $::env(RING1_CLOCK_PORT)] -name $::env(RING1_CLOCK_PORT) -period $::env(RING1_CLOCK_PERIOD)
diff --git a/openlane/digitalcore_macro/config.tcl b/openlane/digitalcore_macro/config.tcl index 76c41aa..984323c 100755 --- a/openlane/digitalcore_macro/config.tcl +++ b/openlane/digitalcore_macro/config.tcl
@@ -22,7 +22,7 @@ $script_dir/../../ip/randsack/rtl/digitalcore_macro.v \ $script_dir/../../ip/third_party/picorv32_wb/gpio32_wb.v \ $script_dir/../../ip/third_party/picorv32_wb/simpleuart_div16_wb.v \ - $script_dir/../../ip/third_party/verilog-wishbone/rtl/wb_mux_3.v \ + $script_dir/../../ip/third_party/verilog-wishbone/rtl/wb_mux_4.v \ $script_dir/../../ip/randsack/rtl/ring_control.v" set ::env(DESIGN_IS_CORE) 0 @@ -31,8 +31,8 @@ set ::env(BASE_SDC_FILE) "$script_dir/base.sdc" # NOTE: Make sure to add all clocks manually to base.sdc! -set ::env(CLOCK_PORT) "wb_clk_i ring0_clk" -set ::env(CLOCK_PERIOD) "10" +set ::env(CLOCK_PORT) "wb_clk_i ring0_clk ring1_clk" +set ::env(CLOCK_PERIOD) "15" set ::env(FP_SIZING) absolute set ::env(DIE_AREA) "0 0 500 500"
diff --git a/openlane/ringosc_macro/config.tcl b/openlane/ringosc_macro/config.tcl new file mode 100755 index 0000000..60d4a8f --- /dev/null +++ b/openlane/ringosc_macro/config.tcl
@@ -0,0 +1,70 @@ +# 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 + +set script_dir [file dirname [file normalize [info script]]] + +set ::env(DESIGN_NAME) ringosc_macro + +set ::env(VERILOG_FILES) "\ + $script_dir/../../ip/randsack/rtl/ringosc_macro.v \ + $script_dir/../../ip/third_party/caravel/ring_osc2x13.v" + +# Preserve manually instantiated stdcells. +set ::env(SYNTH_READ_BLACKBOX_LIB) 1 + +# Disable optimizations and CTS to preserve our hand picked stdcells. +set ::env(SYNTH_BUFFERING) 0 +set ::env(SYNTH_SIZING) 0 +set ::env(SYNTH_SHARE_RESOURCES) 0 +set ::env(CLOCK_TREE_SYNTH) 0 +set ::env(PL_RESIZER_DESIGN_OPTIMIZATIONS) 0 +set ::env(PL_RESIZER_TIMING_OPTIMIZATIONS) 0 +set ::env(PL_OPENPHYSYN_OPTIMIZATIONS) 0 +set ::env(GLB_RESIZER_TIMING_OPTIMIZATIONS) 0 + +set ::env(DESIGN_IS_CORE) 0 + +# TODO(hdpham): Properly disable STA. +set ::env(CLOCK_PORT) "clk_out" +# set ::env(CLOCK_NET) "ring.clk_ff0" +set ::env(CLOCK_PERIOD) "10" + +set ::env(FP_SIZING) absolute +# 70 70 is optimal but won't fit in PDN. +set ::env(DIE_AREA) "0 0 50 150" + +set ::env(FP_PIN_ORDER_CFG) $script_dir/pin_order.cfg + +set ::env(PL_BASIC_PLACEMENT) 1 +set ::env(PL_TARGET_DENSITY) 0.75 + +# Maximum layer used for routing is metal 4. +# This is because this macro will be inserted in a top level (user_project_wrapper) +# where the PDN is planned on metal 5. So, to avoid having shorts between routes +# in this macro and the top level metal 5 stripes, we have to restrict routes to metal4. +# TODO(hdpham): Figure out why blocking li1 doesn't work. +#set ::env(GLB_RT_MINLAYER) 2 +set ::env(GLB_RT_MAXLAYER) 5 + +# Really force the router to not use li1/met5. +#set ::env(GLB_RT_OBS) "li1 0 0 50 200, met5 0 0 50 200" + +# You can draw more power domains if you need to +set ::env(VDD_NETS) [list {vccd1}] +set ::env(GND_NETS) [list {vssd1}] + +set ::env(DIODE_INSERTION_STRATEGY) 4 +# If you're going to use multiple power domains, then disable cvc run. +set ::env(RUN_CVC) 1
diff --git a/openlane/ringosc_macro/pin_order.cfg b/openlane/ringosc_macro/pin_order.cfg new file mode 100644 index 0000000..dbbb80f --- /dev/null +++ b/openlane/ringosc_macro/pin_order.cfg
@@ -0,0 +1,13 @@ +#BUS_SORT + +#S +clkmux.* +clk_out +start + +#N + +#E +trim_a.* + +#W
diff --git a/openlane/user_project_wrapper/config.tcl b/openlane/user_project_wrapper/config.tcl index 80814ac..7cef48f 100755 --- a/openlane/user_project_wrapper/config.tcl +++ b/openlane/user_project_wrapper/config.tcl
@@ -53,17 +53,20 @@ $::env(CARAVEL_ROOT)/verilog/rtl/defines.v \ $script_dir/../../verilog/rtl/user_proj_example.v \ $script_dir/../../ip/randsack/rtl/digitalcore_macro.v \ - $script_dir/../../ip/randsack/rtl/collapsering_macro.v" + $script_dir/../../ip/randsack/rtl/collapsering_macro.v \ + $script_dir/../../ip/randsack/rtl/ringosc_macro.v" set ::env(EXTRA_LEFS) "\ $script_dir/../../lef/user_proj_example.lef \ $script_dir/../../lef/digitalcore_macro.lef \ - $script_dir/../../lef/collapsering_macro.lef" + $script_dir/../../lef/collapsering_macro.lef \ + $script_dir/../../lef/ringosc_macro.lef" set ::env(EXTRA_GDS_FILES) "\ $script_dir/../../gds/user_proj_example.gds \ $script_dir/../../gds/digitalcore_macro.gds \ - $script_dir/../../gds/collapsering_macro.gds" + $script_dir/../../gds/collapsering_macro.gds \ + $script_dir/../../gds/ringosc_macro.gds" set ::env(GLB_RT_MAXLAYER) 5
diff --git a/openlane/user_project_wrapper/macro.cfg b/openlane/user_project_wrapper/macro.cfg index 732f5ab..e02b4fd 100644 --- a/openlane/user_project_wrapper/macro.cfg +++ b/openlane/user_project_wrapper/macro.cfg
@@ -1,2 +1,3 @@ digitalcore 1000 500 N -collapsering0 700 620 N +ring0 800 620 N +ring1 800 800 N
diff --git a/verilog/dv/randsack_netlists.v b/verilog/dv/randsack_netlists.v index 2eb9750..68f604b 100644 --- a/verilog/dv/randsack_netlists.v +++ b/verilog/dv/randsack_netlists.v
@@ -25,8 +25,9 @@ `include "user_project_wrapper.v" `include "digitalcore_macro.v" `include "collapsering_macro.v" + `include "ringosc_macro.v" `include "ring_control.v" `include "picorv32_wb/gpio32_wb.v" `include "picorv32_wb/simpleuart_div16_wb.v" - `include "verilog-wishbone/rtl/wb_mux_3.v" + `include "verilog-wishbone/rtl/wb_mux_4.v" `endif
diff --git a/verilog/dv/randsack_regrw_directed/randsack_regrw_directed.c b/verilog/dv/randsack_regrw_directed/randsack_regrw_directed.c index 2218b98..ff29a94 100644 --- a/verilog/dv/randsack_regrw_directed/randsack_regrw_directed.c +++ b/verilog/dv/randsack_regrw_directed/randsack_regrw_directed.c
@@ -35,6 +35,7 @@ #define RANDSACK_RING_CONTROL_ADDR 0x04 #define RANDSACK_RING_TRIMA_ADDR 0x08 #define RANDSACK_RING_TRIMB_ADDR 0x0c +#define RANDSACK_RING_CLKMUX_OFFSET 8 #define RANDSACK_RING_CONTROL_RESET_MASK (1 << 0) #define RANDSACK_RING_CONTROL_START_MASK (1 << 1) @@ -80,18 +81,24 @@ REG(RANDSACK_GPIO0_BASE + RANDSACK_GPIO_DATA) = 0x55550000; // Reset ring osc. + REG(RANDSACK_RING0_BASE + RANDSACK_RING_TRIMA_ADDR) = 50; + REG(RANDSACK_RING0_BASE + RANDSACK_RING_TRIMB_ADDR) = 60; REG(RANDSACK_RING0_BASE + RANDSACK_RING_CONTROL_ADDR) = RANDSACK_RING_CONTROL_RESET_MASK; REG(RANDSACK_RING0_BASE + RANDSACK_RING_CONTROL_ADDR) = 0; // Start ring osc. - REG(RANDSACK_RING0_BASE + RANDSACK_RING_CONTROL_ADDR) = RANDSACK_RING_CONTROL_START_MASK; + REG(RANDSACK_RING0_BASE + RANDSACK_RING_CONTROL_ADDR) = RANDSACK_RING_CONTROL_START_MASK + (4 << RANDSACK_RING_CLKMUX_OFFSET); REG(RANDSACK_GPIO0_BASE + RANDSACK_GPIO_DATA) = 0xaaaa0000; // Wait for valid value. - while (REG(RANDSACK_RING0_BASE + RANDSACK_RING_COUNT_ADDR) < 100) { + while (REG(RANDSACK_RING0_BASE + RANDSACK_RING_COUNT_ADDR) < 114) { REG(RANDSACK_GPIO0_BASE + RANDSACK_GPIO_DATA) = 0xdead0000; } - REG(RANDSACK_GPIO0_BASE + RANDSACK_GPIO_DATA) = 0xfeed0000; + // Check to make sure the counter stopped. Our CPU is really slow so this + // is a safe check. + if (REG(RANDSACK_RING0_BASE + RANDSACK_RING_COUNT_ADDR) == 114) { + REG(RANDSACK_GPIO0_BASE + RANDSACK_GPIO_DATA) = 0xfeed0000; + } }