rtl: Use specific cells for scanchain - Add RAM IP block for RF/CSR storage
diff --git a/openlane/tiny_user_project/config.json b/openlane/tiny_user_project/config.json deleted file mode 100644 index 94a3ced..0000000 --- a/openlane/tiny_user_project/config.json +++ /dev/null
@@ -1,54 +0,0 @@ -{ - "DESIGN_NAME": "tiny_user_project", - "DESIGN_IS_CORE": 0, - "VERILOG_FILES": [ - "dir::../../verilog/rtl/top.v", - "dir::../../verilog/rtl/scanchain.v", - "dir::../../verilog/blocks/serv/rtl/serv_top.v", - "dir::../../verilog/blocks/serv/rtl/serv_synth_wrapper.v", - "dir::../../verilog/blocks/serv/rtl/serv_mem_if.v", - "dir::../../verilog/blocks/serv/rtl/serv_rf_if.v", - "dir::../../verilog/blocks/serv/rtl/serv_rf_top.v", - "dir::../../verilog/blocks/serv/rtl/serv_rf_ram.v", - "dir::../../verilog/blocks/serv/rtl/serv_rf_ram_if.v", - "dir::../../verilog/blocks/serv/rtl/serv_alu.v", - "dir::../../verilog/blocks/serv/rtl/serv_ctrl.v", - "dir::../../verilog/blocks/serv/rtl/serv_bufreg2.v", - "dir::../../verilog/blocks/serv/rtl/serv_bufreg.v", - "dir::../../verilog/blocks/serv/rtl/serv_immdec.v", - "dir::../../verilog/blocks/serv/rtl/serv_decode.v", - "dir::../../verilog/blocks/serv/rtl/serv_compdec.v", - "dir::../../verilog/blocks/serv/rtl/serv_aligner.v", - "dir::../../verilog/blocks/serv/rtl/serv_state.v", - "dir::../../verilog/blocks/serv/rtl/serv_csr.v", - "dir::../../verilog/blocks/serv/servant/servant_arbiter.v", - "dir::../../verilog/blocks/serv/servant/servant_mux.v", - "dir::../../verilog/blocks/serv/servant/servant_gpio.v", - "dir::../../verilog/rtl/defines.v", - "dir::../../verilog/rtl/tiny_user_project.v" - ], - "CLOCK_PERIOD": 24, - "CLOCK_PORT": "", - "CLOCK_NET": "", - "FP_SIZING": "absolute", - "DIE_AREA": "0 0 690 800", - "PL_BASIC_PLACEMENT": 0, - "PL_TARGET_DENSITY": 0.55, - "SYNTH_USE_PG_PINS_DEFINES": "USE_POWER_PINS", - "VDD_NETS": [ - "vdd" - ], - "GND_NETS": [ - "vss" - ], - "DIODE_INSERTION_STRATEGY": 4, - "RUN_CVC": 1, - "RUN_KLAYOUT_XOR": 0, - "RUN_KLAYOUT_DRC": 0, - "SYNTH_READ_BLACKBOX_LIB": 0, - "pdk::gf180mcuC": { - "STD_CELL_LIBRARY": "gf180mcu_fd_sc_mcu7t5v0", - "RT_MAX_LAYER": "Metal4", - "SYNTH_MAX_FANOUT": 4 - } -} \ No newline at end of file
diff --git a/openlane/tiny_user_project/config.tcl b/openlane/tiny_user_project/config.tcl new file mode 100644 index 0000000..f09173b --- /dev/null +++ b/openlane/tiny_user_project/config.tcl
@@ -0,0 +1,116 @@ +# 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) tiny_user_project +set ::env(DESIGN_IS_CORE) 0 + +set ::env(PDK) "gf180mcuC" +set ::env(STD_CELL_LIBRARY) "gf180mcu_fd_sc_mcu7t5v0" + +set ::env(RUN_KLAYOUT) 0 +set ::env(CLOCK_TREE_SYNTH) 0 +set ::env(CLOCK_PORT) {io_in[8]} +#set ::env(CLOCK_NET) "" +set ::env(CLOCK_PERIOD) "45" + +set ::env(FP_IO_HLENGTH) 2 +set ::env(FP_IO_VLENGTH) 2 + +## Floorplan +set ::env(FP_SIZING) absolute +set ::env(DIE_AREA) "0 0 700 500" + + +## Placement +set ::env(PL_BASIC_PLACEMENT) 0 +set ::env(PL_TARGET_DENSITY) 0.55 + +set ::env(PL_RESIZER_DESIGN_OPTIMIZATIONS) 1 +set ::env(PL_RESIZER_TIMING_OPTIMIZATIONS) 1 + +## Diode Insertion +set ::env(DIODE_INSERTION_STRATEGY) 4 + +# connect to first digital rails +set ::env(VDD_NETS) [list {VDD}] +set ::env(GND_NETS) [list {VSS}] + + +# save some time +set ::env(RUN_KLAYOUT_XOR) 0 +set ::env(RUN_KLAYOUT_DRC) 0 + +# don't put clock buffers on the outputs +set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 + +## Internal Macros +set ::env(MACRO_PLACEMENT_CFG) $script_dir/macro.cfg + +set ::env(DESIGN_DIR) $script_dir/../../verilog + + #$::env(DESIGN_DIR)/blocks/serv/rtl/serv_rf_ram.v \ + +set ::env(VERILOG_FILES) "\ + $::env(DESIGN_DIR)/rtl/defines.v \ + $::env(DESIGN_DIR)/rtl/top.v \ + $::env(DESIGN_DIR)/rtl/serv_rf_ram_gf180.v \ + $::env(DESIGN_DIR)/rtl/scanchain_gf180.v \ + $::env(DESIGN_DIR)/rtl/tiny_user_project.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_top.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_synth_wrapper.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_mem_if.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_rf_if.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_rf_top.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_rf_ram_if.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_alu.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_ctrl.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_bufreg2.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_bufreg.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_immdec.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_decode.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_compdec.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_aligner.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_state.v \ + $::env(DESIGN_DIR)/blocks/serv/rtl/serv_csr.v \ + $::env(DESIGN_DIR)/blocks/serv/servant/servant_arbiter.v \ + $::env(DESIGN_DIR)/blocks/serv/servant/servant_mux.v \ + $::env(DESIGN_DIR)/blocks/serv/servant/servant_gpio.v" + +set ::env(VERILOG_FILES_BLACKBOX) "\ + $::env(DESIGN_DIR)/rtl/gf180mcu_fd_sc_mcu7t5v0_bb.v \ + $::env(PDK_ROOT)/$::env(PDK)/libs.ref/gf180mcu_fd_ip_sram/verilog/gf180mcu_fd_ip_sram__sram256x8m8wm1.v" + +set ::env(EXTRA_LEFS) "\ + $::env(PDK_ROOT)/$::env(PDK)/libs.ref/gf180mcu_fd_ip_sram/lef/gf180mcu_fd_ip_sram__sram256x8m8wm1.lef" +set ::env(EXTRA_GDS_FILES) "\ + $::env(PDK_ROOT)/$::env(PDK)/libs.ref/gf180mcu_fd_ip_sram/gds/gf180mcu_fd_ip_sram__sram256x8m8wm1.gds" +set ::env(EXTRA_LIBS) "\ + $::env(PDK_ROOT)/$::env(PDK)/libs.ref/gf180mcu_fd_ip_sram/liberty/gf180mcu_fd_ip_sram__sram256x8m8wm1__tt_025C_1v80.lib" + +set ::env(FP_PDN_MACRO_HOOKS) "\ + u_cpu.rf_ram.RAM0 VDD VSS VDD VSS + " + +#set ::env(PDN_CFG) $script_dir/pdn.tcl +set ::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS) 1 + +## LVS +set ::env(MAGIC_DRC_USE_GDS) 0 +set ::env(RUN_MAGIC_DRC) 0 +set ::env(QUIT_ON_MAGIC_DRC) 0 + +set ::env(QUIT_ON_LVS_ERROR) 0 \ No newline at end of file
diff --git a/openlane/tiny_user_project/macro.cfg b/openlane/tiny_user_project/macro.cfg new file mode 100644 index 0000000..ac06333 --- /dev/null +++ b/openlane/tiny_user_project/macro.cfg
@@ -0,0 +1 @@ +mod.u_cpu.rf_ram.RAM0 50 50 FS
diff --git a/openlane/tiny_user_project/pdn.tcl b/openlane/tiny_user_project/pdn.tcl new file mode 100644 index 0000000..8902373 --- /dev/null +++ b/openlane/tiny_user_project/pdn.tcl
@@ -0,0 +1,165 @@ +# Power nets + +if { ! [info exists ::env(VDD_NET)] } { + set ::env(VDD_NET) $::env(VDD_PIN) +} + +if { ! [info exists ::env(GND_NET)] } { + set ::env(GND_NET) $::env(GND_PIN) +} + +if { [info exists ::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS)] } { + if { $::env(FP_PDN_ENABLE_GLOBAL_CONNECTIONS) == 1 } { + foreach power_pin $::env(STD_CELL_POWER_PINS) { + add_global_connection \ + -net $::env(VDD_NET) \ + -inst_pattern .* \ + -pin_pattern $power_pin \ + -power + } + foreach ground_pin $::env(STD_CELL_GROUND_PINS) { + add_global_connection \ + -net $::env(GND_NET) \ + -inst_pattern .* \ + -pin_pattern $ground_pin \ + -ground + } + } +} + +if { $::env(FP_PDN_ENABLE_MACROS_GRID) == 1 && + [info exists ::env(FP_PDN_MACRO_HOOKS)]} { + set pdn_hooks [split $::env(FP_PDN_MACRO_HOOKS) ","] + foreach pdn_hook $pdn_hooks { + set instance_name [lindex $pdn_hook 0] + set power_net [lindex $pdn_hook 1] + set ground_net [lindex $pdn_hook 2] + # This assumes the power pin and the power net have the same name. + # The macro hooks only give an instance name and not power pin names. + + add_global_connection \ + -net $power_net \ + -inst_pattern $instance_name \ + -pin_pattern $power_net \ + -power + + add_global_connection \ + -net $ground_net \ + -inst_pattern $instance_name \ + -pin_pattern $ground_net \ + -ground + } +} + +set secondary [] + +foreach net $::env(VDD_NETS) { + if { $net != $::env(VDD_NET)} { + lappend secondary $net + + set db_net [[ord::get_db_block] findNet $net] + if {$db_net == "NULL"} { + set net [odb::dbNet_create [ord::get_db_block] $net] + $net setSpecial + $net setSigType "POWER" + } + } +} + +foreach net $::env(GND_NETS) { + if { $net != $::env(GND_NET)} { + lappend secondary $net + + set db_net [[ord::get_db_block] findNet $net] + if {$db_net == "NULL"} { + set net [odb::dbNet_create [ord::get_db_block] $net] + $net setSpecial + $net setSigType "GROUND" + } + } +} + +set_voltage_domain -name CORE -power $::env(VDD_NET) -ground $::env(GND_NET) \ + -secondary_power $secondary + +# Assesses whether the design is the core of the chip or not based on the +# value of $::env(DESIGN_IS_CORE) and uses the appropriate stdcell section +if { $::env(DESIGN_IS_CORE) == 1 } { + # Used if the design is the core of the chip + define_pdn_grid \ + -name stdcell_grid \ + -starts_with POWER \ + -voltage_domain CORE \ + -pins "$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)" + + add_pdn_stripe \ + -grid stdcell_grid \ + -layer $::env(FP_PDN_LOWER_LAYER) \ + -width $::env(FP_PDN_VWIDTH) \ + -pitch $::env(FP_PDN_VPITCH) \ + -offset $::env(FP_PDN_VOFFSET) \ + -starts_with POWER -extend_to_core_ring + + add_pdn_stripe \ + -grid stdcell_grid \ + -layer $::env(FP_PDN_UPPER_LAYER) \ + -width $::env(FP_PDN_HWIDTH) \ + -pitch $::env(FP_PDN_HPITCH) \ + -offset $::env(FP_PDN_HOFFSET) \ + -starts_with POWER -extend_to_core_ring + + add_pdn_connect \ + -grid stdcell_grid \ + -layers "$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)" +} else { + # Used if the design is a macro in the core + define_pdn_grid \ + -name stdcell_grid \ + -starts_with POWER \ + -voltage_domain CORE \ + -pins $::env(FP_PDN_LOWER_LAYER) + + add_pdn_stripe \ + -grid stdcell_grid \ + -layer $::env(FP_PDN_LOWER_LAYER) \ + -width $::env(FP_PDN_VWIDTH) \ + -pitch $::env(FP_PDN_VPITCH) \ + -offset $::env(FP_PDN_VOFFSET) \ + -starts_with POWER +} + +# Adds the standard cell rails if enabled. +if { $::env(FP_PDN_ENABLE_RAILS) == 1 } { + add_pdn_stripe \ + -grid stdcell_grid \ + -layer $::env(FP_PDN_RAILS_LAYER) \ + -width $::env(FP_PDN_RAIL_WIDTH) \ + -followpins \ + -starts_with POWER + + add_pdn_connect \ + -grid stdcell_grid \ + -layers "$::env(FP_PDN_RAILS_LAYER) $::env(FP_PDN_LOWER_LAYER)" +} + + +# Adds the core ring if enabled. +if { $::env(FP_PDN_CORE_RING) == 1 } { + add_pdn_ring \ + -grid stdcell_grid \ + -layers "$::env(FP_PDN_LOWER_LAYER) $::env(FP_PDN_UPPER_LAYER)" \ + -widths "$::env(FP_PDN_CORE_RING_VWIDTH) $::env(FP_PDN_CORE_RING_HWIDTH)" \ + -spacings "$::env(FP_PDN_CORE_RING_VSPACING) $::env(FP_PDN_CORE_RING_HSPACING)" \ + -core_offset "$::env(FP_PDN_CORE_RING_VOFFSET) $::env(FP_PDN_CORE_RING_HOFFSET)" +} + +define_pdn_grid \ + -macro \ + -default \ + -name macro \ + -starts_with POWER \ + -halo "$::env(FP_PDN_HORIZONTAL_HALO) $::env(FP_PDN_VERTICAL_HALO)" + +add_pdn_connect \ + -grid macro \ + -layers "Metal3 Metal4"
diff --git a/verilog/includes/includes.gl+sdf.caravel_user_project b/verilog/includes/includes.gl+sdf.caravel_user_project index d68969d..79e7112 100644 --- a/verilog/includes/includes.gl+sdf.caravel_user_project +++ b/verilog/includes/includes.gl+sdf.caravel_user_project
@@ -1,3 +1,6 @@ // Caravel user project includes $USER_PROJECT_VERILOG/gl/user_project_wrapper.v $USER_PROJECT_VERILOG/gl/user_module.v + +$(PDK_ROOT)/$(PDK)/libs.ref/gf180mcu_fd_sc_mcu7t5v0/verilog/gf180mcu_fd_sc_mcu7t5v0.v +$(PDK_ROOT)/$(PDK)/libs.ref/gf180mcu_fd_ip_sram/verilog/gf180mcu_fd_ip_sram__sram512x8m8wm1.v
diff --git a/verilog/includes/includes.gl.caravel_user_project b/verilog/includes/includes.gl.caravel_user_project index 0bbcd8d..3235e89 100644 --- a/verilog/includes/includes.gl.caravel_user_project +++ b/verilog/includes/includes.gl.caravel_user_project
@@ -1,3 +1,9 @@ # Caravel user project includes -v $(USER_PROJECT_VERILOG)/gl/user_project_wrapper.v -v $(USER_PROJECT_VERILOG)/gl/user_module.v + +# STD CELLS - they need to be below the defines.v files + -v $(PDK_ROOT)/$(PDK)/libs.ref/gf180mcu_fd_sc_mcu7t5v0/verilog/gf180mcu_fd_sc_mcu7t5v0.v + +## STD CELLS - they need to be below the defines.v files + -v $(PDK_ROOT)/$(PDK)/libs.ref/gf180mcu_fd_ip_sram/verilog/gf180mcu_fd_ip_sram__sram512x8m8wm1.v
diff --git a/verilog/includes/includes.rtl.caravel_user_project b/verilog/includes/includes.rtl.caravel_user_project index 898b5cb..cc97d00 100644 --- a/verilog/includes/includes.rtl.caravel_user_project +++ b/verilog/includes/includes.rtl.caravel_user_project
@@ -2,4 +2,10 @@ -v $(USER_PROJECT_VERILOG)/rtl/user_project_wrapper.v -v $(USER_PROJECT_VERILOG)/rtl/user_module.v - \ No newline at end of file + +# STD CELLS - they need to be below the defines.v files + -v $(PDK_ROOT)/$(PDK)/libs.ref/gf180mcu_fd_sc_mcu7t5v0/verilog/gf180mcu_fd_sc_mcu7t5v0.v + +## STD CELLS - they need to be below the defines.v files + -v $(PDK_ROOT)/$(PDK)/libs.ref/gf180mcu_fd_ip_sram/verilog/gf180mcu_fd_ip_sram__sram512x8m8wm1.v +
diff --git a/verilog/rtl/gf180mcu_fd_sc_mcu7t5v0_bb.v b/verilog/rtl/gf180mcu_fd_sc_mcu7t5v0_bb.v new file mode 100644 index 0000000..2a0fbda --- /dev/null +++ b/verilog/rtl/gf180mcu_fd_sc_mcu7t5v0_bb.v
@@ -0,0 +1,47 @@ + +// Copyright 2022 GlobalFoundries PDK Authors +// +// 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. + + +module gf180mcu_fd_sc_mcu7t5v0__sdffq_1( SE, SI, D, CLK, Q, VDD, VSS ); +input CLK, D, SE, SI; +inout VDD, VSS; +output Q; +reg notifier; +endmodule + +module gf180mcu_fd_sc_mcu7t5v0__buf_1( I, Z, VDD, VSS ); +input I; +inout VDD, VSS; +output Z; +endmodule + +module gf180mcu_fd_sc_mcu7t5v0__buf_2( I, Z, VDD, VSS ); +input I; +inout VDD, VSS; +output Z; +endmodule + +module gf180mcu_fd_sc_mcu7t5v0__buf_4( I, Z, VDD, VSS ); +input I; +inout VDD, VSS; +output Z; +endmodule + +module gf180mcu_fd_sc_mcu7t5v0__dffnq_1( CLKN, D, Q, VDD, VSS ); +input CLKN, D; +inout VDD, VSS; +output Q; +reg notifier; +endmodule
diff --git a/verilog/rtl/serv_rf_ram_gf180.v b/verilog/rtl/serv_rf_ram_gf180.v new file mode 100644 index 0000000..653eaa2 --- /dev/null +++ b/verilog/rtl/serv_rf_ram_gf180.v
@@ -0,0 +1,51 @@ +module serv_rf_ram + #(parameter width=0, + parameter csr_regs=4, + parameter depth=32*(32+csr_regs)/width) + (input wire i_clk, + input wire [$clog2(depth)-1:0] i_waddr, + input wire [width-1:0] i_wdata, + input wire i_wen, + input wire [$clog2(depth)-1:0] i_raddr, + output wire [width-1:0] o_rdata); + +// reg [width-1:0] memory [0:depth-1]; + + wire [width-1:0] data ; + reg [width-1:0] rdata ; + + +gf180mcu_fd_ip_sram__sram256x8m8wm1 RAM0 ( + .CLK(i_clk), + .CEN(1'b0), // Active LOW chip enable + .GWEN(~i_wen), // Active LOW Write enable + .WEN({8{~i_wen}}), // Active LOW + .A(i_wen ? i_waddr : i_raddr), + .D(i_wdata), + .Q(data), + .VDD(1'b1), + .VSS(1'b0) +); + + /* Reads from reg x0 needs to return 0 + Check that the part of the read address corresponding to the register + is zero and gate the output + width LSB of reg index $clog2(width) + 2 4 1 + 4 3 2 + 8 2 3 + 16 1 4 + 32 0 5 + */ + reg regzero; + + always @(posedge i_clk) + regzero <= !(|i_raddr[$clog2(depth)-1:5-$clog2(width)]); + + always @(posedge i_clk) + if(~i_wen) + rdata <= data; + + assign o_rdata = (i_wen ? rdata : data) & ~{width{regzero}}; + +endmodule
diff --git a/verilog/rtl/top.v b/verilog/rtl/top.v index 0095ec5..b3d84fd 100644 --- a/verilog/rtl/top.v +++ b/verilog/rtl/top.v
@@ -69,7 +69,7 @@ .PRE_REGISTER(1), .RESET_STRATEGY("MINI"), .WITH_CSR(1), - .RF_WIDTH(2)) + .RF_WIDTH(8)) u_cpu ( .clk (serv_clk),