├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── bug_report.md └── workflows │ └── wokwi.yaml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── info.yaml ├── src ├── base.sdc └── cells.v └── template ├── config.tcl └── scan_wrapper.v /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | custom: ['https://zerotoasiccourse.com'] 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: mattvenn 7 | 8 | --- 9 | 10 | **Link to your wokwi project** 11 | 12 | Please put a link to your wokwi project here. 13 | -------------------------------------------------------------------------------- /.github/workflows/wokwi.yaml: -------------------------------------------------------------------------------- 1 | name: wokwi 2 | # either manually started, or on a schedule 3 | on: [ push, workflow_dispatch ] 4 | permissions: 5 | contents: write 6 | pages: write 7 | id-token: write 8 | jobs: 9 | gds: 10 | env: 11 | OPENLANE_TAG: 2022.02.23_02.50.41 12 | OPENLANE_IMAGE_NAME: efabless/openlane:$(OPENLANE_TAG) 13 | OPENLANE_ROOT: /home/runner/openlane 14 | PDK_ROOT: /home/runner/pdk 15 | PDK: sky130A 16 | 17 | # ubuntu 18 | runs-on: ubuntu-latest 19 | steps: 20 | # need the repo checked out 21 | - name: checkout repo 22 | uses: actions/checkout@v2 23 | 24 | # build PDK and fetch OpenLane 25 | - name: pdk & caravel 26 | run: | 27 | cd $HOME 28 | git clone https://github.com/efabless/caravel_user_project.git -b mpw-6c 29 | cd caravel_user_project 30 | make setup 31 | 32 | # fetch the Verilog from Wokwi API 33 | - name: fetch Verilog 34 | run: make fetch 35 | 36 | # run the 'harden' rule in the Makefile to use OpenLane to build the GDS 37 | - name: make GDS 38 | run: make harden 39 | 40 | # for debugging, show all the files 41 | - name: show files 42 | run: find runs/wokwi/results 43 | 44 | - name: setup python 45 | uses: actions/setup-python@v4 46 | with: 47 | python-version: '3.10' 48 | 49 | - name: add summary 50 | run: | 51 | python << EOF >> $GITHUB_STEP_SUMMARY 52 | import csv 53 | with open('runs/wokwi/reports/final_summary_report.csv') as f: 54 | report = list(csv.DictReader(f))[0] 55 | keys = ['OpenDP_Util', 'cell_count', 'wire_length', 'AND', 'DFF', 'NAND', 'NOR', 'OR', 'XOR', 'XNOR', 'MUX'] 56 | print(f'| { "|".join(keys) } |') 57 | print(f'| { "|".join(["-----"] * len(keys)) } |') 58 | print(f'| { "|".join(report[k] for k in keys) } |') 59 | EOF 60 | 61 | - name: populate src cache 62 | uses: actions/cache@v2 63 | with: 64 | path: src 65 | key: ${{ runner.os }}-src-${{ github.run_id }} 66 | 67 | - name: populate runs cache 68 | uses: actions/cache@v2 69 | with: 70 | path: runs 71 | key: ${{ runner.os }}-runs-${{ github.run_id }} 72 | 73 | svg: 74 | needs: gds 75 | runs-on: ubuntu-latest 76 | steps: 77 | - name: checkout repo 78 | uses: actions/checkout@v2 79 | 80 | - name: setup python 81 | uses: actions/setup-python@v4 82 | with: 83 | python-version: '3.10' 84 | 85 | - name: restore runs cache 86 | uses: actions/cache@v2 87 | with: 88 | path: runs 89 | key: ${{ runner.os }}-runs-${{ github.run_id }} 90 | 91 | - name: create svg 92 | run: | 93 | python -m pip install gdstk 94 | python << EOF 95 | import gdstk 96 | import pathlib 97 | 98 | gds = sorted(pathlib.Path('runs').glob('wokwi/results/final/gds/*.gds')) 99 | library = gdstk.read_gds(gds[-1]) 100 | top_cells = library.top_level() 101 | top_cells[0].write_svg('gds_render.svg') 102 | EOF 103 | 104 | - name: populate svg cache 105 | uses: actions/cache@v2 106 | with: 107 | path: 'gds_render.svg' 108 | key: ${{ runner.os }}-svg-${{ github.run_id }} 109 | 110 | viewer: 111 | needs: gds 112 | runs-on: ubuntu-latest 113 | steps: 114 | - name: checkout GDS2glTF repo 115 | uses: actions/checkout@v2 116 | with: 117 | repository: mbalestrini/GDS2glTF 118 | 119 | - name: checkout tinytapeout_gds_viewer repo 120 | uses: actions/checkout@v2 121 | with: 122 | repository: mbalestrini/tinytapeout_gds_viewer 123 | path: viewer 124 | 125 | - name: setup python 126 | uses: actions/setup-python@v4 127 | with: 128 | python-version: '3.10' 129 | 130 | - name: restore runs cache 131 | uses: actions/cache@v2 132 | with: 133 | path: runs 134 | key: ${{ runner.os }}-runs-${{ github.run_id }} 135 | 136 | - name: gds2gltf 137 | run: | 138 | python -m pip install -r requirements.txt 139 | cp runs/wokwi/results/final/gds/*.gds tinytapeout.gds 140 | python3 gds2gltf.py tinytapeout.gds 141 | cp tinytapeout.gds.gltf viewer/ 142 | 143 | - name: populate viewer cache 144 | uses: actions/cache@v2 145 | with: 146 | path: viewer 147 | key: ${{ runner.os }}-viewer-${{ github.run_id }} 148 | 149 | artifact: 150 | needs: 151 | - gds 152 | runs-on: ubuntu-latest 153 | steps: 154 | - name: restore src cache 155 | uses: actions/cache@v2 156 | with: 157 | path: src 158 | key: ${{ runner.os }}-src-${{ github.run_id }} 159 | 160 | - name: restore runs cache 161 | uses: actions/cache@v2 162 | with: 163 | path: runs 164 | key: ${{ runner.os }}-runs-${{ github.run_id }} 165 | 166 | - name: upload artifact 167 | uses: actions/upload-artifact@v2 168 | with: 169 | # path depends on the tag and the module name 170 | name: GDS 171 | path: | 172 | src/* 173 | runs/wokwi/results/final/* 174 | runs/wokwi/reports/final_summary_report.csv 175 | 176 | pages: 177 | needs: 178 | - svg 179 | - viewer 180 | environment: 181 | name: github-pages 182 | url: ${{ steps.deployment.outputs.page_url }} 183 | outputs: 184 | page_url: ${{ steps.deployment.outputs.page_url }} 185 | runs-on: ubuntu-latest 186 | steps: 187 | - name: restore svg cache 188 | uses: actions/cache@v2 189 | with: 190 | path: 'gds_render.svg' 191 | key: ${{ runner.os }}-svg-${{ github.run_id }} 192 | - name: restore viewer cache 193 | uses: actions/cache@v2 194 | with: 195 | path: viewer 196 | key: ${{ runner.os }}-viewer-${{ github.run_id }} 197 | - name: Setup Pages 198 | uses: actions/configure-pages@v2 199 | - name: Upload artifact 200 | uses: actions/upload-pages-artifact@v1 201 | with: 202 | path: '.' 203 | - name: Deploy to GitHub Pages 204 | id: deployment 205 | uses: actions/deploy-pages@v1 206 | 207 | preview: 208 | needs: pages 209 | runs-on: ubuntu-latest 210 | steps: 211 | - name: add gds preview 212 | run: | 213 | PAGE_URL=${{ needs.pages.outputs.page_url }} 214 | PAGE_URL=$(echo "$PAGE_URL" | sed -e 's/\/$//') 215 | cat << EOF >> $GITHUB_STEP_SUMMARY 216 | # layout 217 | ![svg]($PAGE_URL/gds_render.svg) 218 | # viewer 219 | [open preview]($PAGE_URL/viewer/tinytapeout.html) 220 | EOF 221 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | src/config.tcl 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | WOKWI_PROJECT_ID=334445762078310996 2 | # logic puzzle and muxes 3 | # 4 inverters 334348818476696146 4 | # the clock divider 334335179919196756 5 | fetch: 6 | curl https://wokwi.com/api/projects/$(WOKWI_PROJECT_ID)/verilog > src/user_module_$(WOKWI_PROJECT_ID).v 7 | sed -e 's/USER_MODULE_ID/$(WOKWI_PROJECT_ID)/g' template/scan_wrapper.v > src/scan_wrapper_$(WOKWI_PROJECT_ID).v 8 | sed -e 's/USER_MODULE_ID/$(WOKWI_PROJECT_ID)/g' template/config.tcl > src/config.tcl 9 | echo $(WOKWI_PROJECT_ID) > src/ID 10 | 11 | # needs PDK_ROOT and OPENLANE_ROOT, OPENLANE_IMAGE_NAME set from your environment 12 | harden: 13 | docker run --rm \ 14 | -v $(OPENLANE_ROOT):/openlane \ 15 | -v $(PDK_ROOT):$(PDK_ROOT) \ 16 | -v $(CURDIR):/work \ 17 | -e PDK_ROOT=$(PDK_ROOT) \ 18 | -u $(shell id -u $(USER)):$(shell id -g $(USER)) \ 19 | $(OPENLANE_IMAGE_NAME) \ 20 | /bin/bash -c "./flow.tcl -overwrite -design /work/src -run_path /work/runs -tag wokwi" 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](../../workflows/wokwi/badge.svg) 2 | 3 | Go to https://tinytapeout.com for instructions! 4 | 5 | # Out of date! 6 | 7 | We have a new submission repo now: https://github.com/TinyTapeout/tt02-submission-template 8 | 9 | # How to change the Wokwi project 10 | 11 | Edit the [Makefile](Makefile) and change the WOKWI_PROJECT_ID to match your project. 12 | 13 | # What is this about? 14 | 15 | This repo is a template you can make a copy of for your own [ASIC](https://www.zerotoasiccourse.com/terminology/asic/) design using [Wokwi](https://wokwi.com/). 16 | 17 | When you edit the Makefile to choose a different ID, the [GitHub Action](.github/workflows/wokwi.yaml) will fetch the digital netlist of your design from Wokwi. 18 | 19 | The design gets wrapped in some extra logic that builds a 'scan chain'. This is a way to put lots of designs onto one chip and still have access to them all. You can see [all of the technical details here](https://github.com/mattvenn/scan_wrapper). 20 | 21 | After that, the action uses the open source ASIC tool called [OpenLane](https://www.zerotoasiccourse.com/terminology/openlane/) to build the files needed to fabricate an ASIC. 22 | 23 | # What files get made? 24 | 25 | When the action is complete, you can [click here](https://github.com/mattvenn/wokwi-verilog-gds-test/actions) to see the latest build of your design. You need to download the zip file and take a look at the contents: 26 | 27 | * gds_render.svg - picture of your ASIC design 28 | * gds.html - zoomable picture of your ASIC design 29 | * runs/wokwi/reports/final_summary_report.csv - CSV file with lots of details about the design 30 | * runs/wokwi/reports/synthesis/1-synthesis.stat.rpt.strategy4 - list of the [standard cells](https://www.zerotoasiccourse.com/terminology/standardcell/) used by your design 31 | * runs/wokwi/results/final/gds/user_module.gds - the final [GDS](https://www.zerotoasiccourse.com/terminology/gds2/) file needed to make your design 32 | 33 | # What next? 34 | 35 | * Update the [info.yaml](info.yaml) file. The info will be collected and used to make a datachip for the whole chip. 36 | * Share your GDS on twitter, tag it #tinytapeout and [link me](https://twitter.com/matthewvenn)! 37 | * [Submit it to be made](https://docs.google.com/forms/d/e/1FAIpQLSc3ZF0AHKD3LoZRSmKX5byl-0AzrSK8ADeh0DtkZQX0bbr16w/viewform?usp=sf_link) 38 | * [Join the community](https://discord.gg/rPK2nSjxy8) 39 | -------------------------------------------------------------------------------- /info.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # TinyTapeout project information 3 | # 4 | # As everyone will have access to all designs, try to make it easy for someone new to your design to know what 5 | # it does and how to operate it. 6 | # 7 | # This will be automatically collected and used to make a datasheet for the chip. 8 | project: 9 | author: "" # Your name 10 | title: "" # Project title 11 | description: "" # Short description of what your project does 12 | how_it_works: "" # Longer description of how the project works 13 | how_to_test: "" # Instructions on how someone could test your project, include things like what buttons do what and how to set the clock if needed 14 | external_hw: "" # Describe any external hardware needed 15 | doc_link: "" # URL to longer form documentation, eg the README.md in your repository 16 | clock_hz: 0 # Clock frequency in Hz (if required) 17 | language: "wokwi" # other examples include Verilog, Amaranth, VHDL, etc 18 | wokwi_id: 0 # the wokwi ID 19 | picture: "" # relative path to a picture in your repository 20 | inputs: # a description of what the inputs do 21 | - clock 22 | - reset 23 | - none 24 | - none 25 | - none 26 | - none 27 | - none 28 | - none 29 | outputs: 30 | - segment a # a description of what the outputs do 31 | - segment b 32 | - segment c 33 | - segment d 34 | - segment e 35 | - segment f 36 | - segment g 37 | - none 38 | 39 | -------------------------------------------------------------------------------- /src/base.sdc: -------------------------------------------------------------------------------- 1 | # Create a clock for the scan chain @ 200 MHz 2 | create_clock -name clk_scan_in -period 5 [get_ports {clk_in}] 3 | create_generated_clock -name clk_scan_out -source clk_in -combinational [get_ports {clk_out}] 4 | 5 | # Scan chain input 0.5 ns setup time, 0.5 ns hold time 6 | set_input_delay -min 0.5 -clock [get_clocks clk_scan_in] [get_ports {data_in}] 7 | set_input_delay -max 0.5 -clock [get_clocks clk_scan_in] [get_ports {data_in}] 8 | 9 | # Scan chain output 1.5 ns setup time, 1.5 ns hold time 10 | set_output_delay -min -1.5 -clock [get_clocks clk_scan_out] [get_ports {data_out}] 11 | set_output_delay -max 1.5 -clock [get_clocks clk_scan_out] [get_ports {data_out}] 12 | 13 | # Misc 14 | set_max_fanout $::env(SYNTH_MAX_FANOUT) [current_design] 15 | 16 | if { ![info exists ::env(SYNTH_CLK_DRIVING_CELL)] } { 17 | set ::env(SYNTH_CLK_DRIVING_CELL) $::env(SYNTH_DRIVING_CELL) 18 | } 19 | 20 | if { ![info exists ::env(SYNTH_CLK_DRIVING_CELL_PIN)] } { 21 | set ::env(SYNTH_CLK_DRIVING_CELL_PIN) $::env(SYNTH_DRIVING_CELL_PIN) 22 | } 23 | 24 | set_driving_cell -lib_cell $::env(SYNTH_DRIVING_CELL) -pin $::env(SYNTH_DRIVING_CELL_PIN) [get_ports {data_in scan_select_in latch_enable_in}] 25 | set_driving_cell -lib_cell $::env(SYNTH_CLK_DRIVING_CELL) -pin $::env(SYNTH_CLK_DRIVING_CELL_PIN) [get_ports {clk_in}] 26 | 27 | set cap_load [expr $::env(SYNTH_CAP_LOAD) / 1000.0] 28 | puts "\[INFO\]: Setting load to: $cap_load" 29 | set_load $cap_load [all_outputs] 30 | 31 | puts "\[INFO\]: Setting clock uncertainity to: $::env(SYNTH_CLOCK_UNCERTAINITY)" 32 | set_clock_uncertainty $::env(SYNTH_CLOCK_UNCERTAINITY) [get_clocks {clk_sys clk_scan_in clk_scan_out}] 33 | 34 | puts "\[INFO\]: Setting clock transition to: $::env(SYNTH_CLOCK_TRANSITION)" 35 | set_clock_transition $::env(SYNTH_CLOCK_TRANSITION) [get_clocks {clk_sys clk_scan_in clk_scan_out}] 36 | 37 | puts "\[INFO\]: Setting timing derate to: [expr {$::env(SYNTH_TIMING_DERATE) * 100}] %" 38 | set_timing_derate -early [expr {1-$::env(SYNTH_TIMING_DERATE)}] 39 | set_timing_derate -late [expr {1+$::env(SYNTH_TIMING_DERATE)}] 40 | -------------------------------------------------------------------------------- /src/cells.v: -------------------------------------------------------------------------------- 1 | `define default_netname none 2 | 3 | module buffer_cell ( 4 | input wire in, 5 | output wire out 6 | ); 7 | assign out = in; 8 | endmodule 9 | 10 | module and_cell ( 11 | input wire a, 12 | input wire b, 13 | output wire out 14 | ); 15 | 16 | assign out = a & b; 17 | endmodule 18 | 19 | module or_cell ( 20 | input wire a, 21 | input wire b, 22 | output wire out 23 | ); 24 | 25 | assign out = a | b; 26 | endmodule 27 | 28 | module xor_cell ( 29 | input wire a, 30 | input wire b, 31 | output wire out 32 | ); 33 | 34 | assign out = a ^ b; 35 | endmodule 36 | 37 | module nand_cell ( 38 | input wire a, 39 | input wire b, 40 | output wire out 41 | ); 42 | 43 | assign out = !(a&b); 44 | endmodule 45 | 46 | module not_cell ( 47 | input wire in, 48 | output wire out 49 | ); 50 | 51 | assign out = !in; 52 | endmodule 53 | 54 | module mux_cell ( 55 | input wire a, 56 | input wire b, 57 | input wire sel, 58 | output wire out 59 | ); 60 | 61 | assign out = sel ? b : a; 62 | endmodule 63 | 64 | module dff_cell ( 65 | input wire clk, 66 | input wire d, 67 | output reg q, 68 | output wire notq 69 | ); 70 | 71 | assign notq = !q; 72 | always @(posedge clk) 73 | q <= d; 74 | 75 | endmodule 76 | 77 | module dffsr_cell ( 78 | input wire clk, 79 | input wire d, 80 | input wire s, 81 | input wire r, 82 | output reg q, 83 | output wire notq 84 | ); 85 | 86 | assign notq = !q; 87 | 88 | always @(posedge clk or posedge s or posedge r) begin 89 | if (r) 90 | q <= '0; 91 | else if (s) 92 | q <= '1; 93 | else 94 | q <= d; 95 | end 96 | endmodule 97 | -------------------------------------------------------------------------------- /template/config.tcl: -------------------------------------------------------------------------------- 1 | # User config 2 | set script_dir [file dirname [file normalize [info script]]] 3 | 4 | # has to match the module name from wokwi 5 | set ::env(DESIGN_NAME) scan_wrapper_USER_MODULE_ID 6 | 7 | # save some time 8 | set ::env(RUN_KLAYOUT_XOR) 0 9 | set ::env(RUN_KLAYOUT_DRC) 0 10 | 11 | # don't put clock buffers on the outputs 12 | set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 0 13 | 14 | # allow use of specific sky130 cells 15 | set ::env(SYNTH_READ_BLACKBOX_LIB) 1 16 | 17 | # read all verilog files 18 | set ::env(VERILOG_FILES) [glob $::env(DESIGN_DIR)/*.v] 19 | 20 | # absolute die size 21 | set ::env(FP_SIZING) absolute 22 | set ::env(DIE_AREA) "0 0 105 105" 23 | set ::env(FP_CORE_UTIL) 45 24 | set ::env(PL_BASIC_PLACEMENT) {1} 25 | 26 | # use alternative efabless decap cells to solve LI density issue 27 | set ::env(DECAP_CELL) "\ 28 | sky130_fd_sc_hd__decap_3 \ 29 | sky130_fd_sc_hd__decap_4 \ 30 | sky130_fd_sc_hd__decap_6 \ 31 | sky130_fd_sc_hd__decap_8 \ 32 | sky130_ef_sc_hd__decap_12" 33 | 34 | # clock 35 | set ::env(CLOCK_PERIOD) "10" 36 | set ::env(CLOCK_PORT) "" 37 | 38 | set ::env(BASE_SDC_FILE) $::env(DESIGN_DIR)/base.sdc 39 | 40 | set ::env(SYNTH_CLOCK_UNCERTAINITY) 0.20 41 | set ::env(SYNTH_CLOCK_TRANSITION) 0.15 42 | 43 | # don't use power rings or met5 44 | set ::env(DESIGN_IS_CORE) 0 45 | set ::env(RT_MAX_LAYER) {met4} 46 | 47 | # connect to first digital rails 48 | set ::env(VDD_NETS) [list {vccd1}] 49 | set ::env(GND_NETS) [list {vssd1}] 50 | -------------------------------------------------------------------------------- /template/scan_wrapper.v: -------------------------------------------------------------------------------- 1 | `default_nettype none 2 | /* 3 | `ifdef COCOTB 4 | `define UNIT_DELAY #1 5 | `define FUNCTIONAL 6 | `define USE_POWER_PINS 7 | `include "libs.ref/sky130_fd_sc_hd/verilog/primitives.v" 8 | `include "libs.ref/sky130_fd_sc_hd/verilog/sky130_fd_sc_hd.v" 9 | `endif 10 | */ 11 | 12 | module scan_wrapper_USER_MODULE_ID ( 13 | input wire clk_in, 14 | input wire data_in, 15 | input wire scan_select_in, 16 | input wire latch_enable_in, 17 | output wire clk_out, 18 | output wire data_out, 19 | output wire scan_select_out, 20 | output wire latch_enable_out 21 | ); 22 | 23 | // input buffers 24 | // Looking at results from multiple projects the bufferring is a bit 25 | // inconsistent. So instead, we ensure at least clk buf 26 | wire clk; 27 | 28 | sky130_fd_sc_hd__clkbuf_2 input_buf_clk ( 29 | .A (clk_in), 30 | .X (clk), 31 | .VPWR (1'b1), 32 | .VGND (1'b0) 33 | ); 34 | 35 | // output buffers 36 | // Same as for input, to try and be more consistent, we make our own 37 | wire data_out_i; 38 | 39 | sky130_fd_sc_hd__buf_4 output_buffers[3:0] ( 40 | .A ({clk, data_out_i, scan_select_in, latch_enable_in }), 41 | .X ({clk_out, data_out, scan_select_out, latch_enable_out }), 42 | .VPWR (1'b1), 43 | .VGND (1'b0) 44 | ); 45 | 46 | /* 47 | `ifdef COCOTB 48 | initial begin 49 | $dumpfile ("scan_wrapper.vcd"); 50 | $dumpvars (0, scan_wrapper_lesson_1); 51 | #1; 52 | end 53 | `endif 54 | */ 55 | 56 | parameter NUM_IOS = 8; 57 | 58 | // wires needed 59 | wire [NUM_IOS-1:0] scan_data_out; // output of the each scan chain flop 60 | wire [NUM_IOS-1:0] scan_data_in; // input of each scan chain flop 61 | wire [NUM_IOS-1:0] module_data_in; // the data that enters the user module 62 | wire [NUM_IOS-1:0] module_data_out; // the data from the user module 63 | 64 | // scan chain - link all the flops, with data coming from data_in 65 | assign scan_data_in = {scan_data_out[NUM_IOS-2:0], data_in}; 66 | 67 | // end of the chain is a negedge FF to increase hold margin between blocks 68 | sky130_fd_sc_hd__dfrtn_1 out_flop ( 69 | .RESET_B (1'b1), 70 | .CLK_N (clk), 71 | .D (scan_data_out[NUM_IOS-1]), 72 | .Q (data_out_i), 73 | .VPWR (1'b1), 74 | .VGND (1'b0) 75 | ); 76 | 77 | // scan flops have a mux on their inputs to choose either data from the user module or the previous flop's output 78 | // https://antmicro-skywater-pdk-docs.readthedocs.io/en/test-submodules-in-rtd/contents/libraries/sky130_fd_sc_ls/cells/sdfxtp/README.html 79 | `ifndef FORMAL 80 | `ifndef FORMAL_COMPAT 81 | sky130_fd_sc_hd__sdfxtp_1 scan_flop [NUM_IOS-1:0] ( 82 | .CLK (clk), 83 | .D (scan_data_in), 84 | .SCD (module_data_out), 85 | .SCE (scan_select_in), 86 | .Q (scan_data_out), 87 | .VPWR (1'b1), 88 | .VGND (1'b0) 89 | ); 90 | 91 | // latch is used to latch the input data of the user module while the scan chain is used to capture the user module's outputs 92 | // https://antmicro-skywater-pdk-docs.readthedocs.io/en/test-submodules-in-rtd/contents/libraries/sky130_fd_sc_hd/cells/dlxtp/README.html 93 | sky130_fd_sc_hd__dlxtp_1 latch [NUM_IOS-1:0] ( 94 | .D (scan_data_out), 95 | .GATE (latch_enable_in), 96 | .Q (module_data_in), 97 | .VPWR (1'b1), 98 | .VGND (1'b0) 99 | ); 100 | `endif 101 | `endif 102 | 103 | // instantiate the wokwi module 104 | user_module_USER_MODULE_ID user_module( 105 | .io_in (module_data_in), 106 | .io_out (module_data_out) 107 | ); 108 | 109 | endmodule 110 | --------------------------------------------------------------------------------