├── .gitignore ├── Bender.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── scripts ├── compile_vsim.sh ├── run_vsim.sh ├── run_xsim.sh └── vivado │ └── run_xsim.tcl ├── src ├── deprecated │ ├── cluster_clk_cells.sv │ ├── cluster_pwr_cells.sv │ ├── generic_memory.sv │ ├── generic_rom.sv │ ├── pad_functional.sv │ ├── pulp_buffer.sv │ ├── pulp_clk_cells.sv │ ├── pulp_clock_gating_async.sv │ └── pulp_pwr_cells.sv ├── fpga │ ├── pad_functional_xilinx.sv │ ├── tc_clk_xilinx.sv │ └── tc_sram_xilinx.sv ├── rtl │ ├── tc_clk.sv │ ├── tc_sram.sv │ └── tc_sram_impl.sv └── tc_pwr.sv ├── src_files.yml └── test └── tb_tc_sram.sv /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | !.git* 3 | build 4 | scripts/vivado/add_sources.tcl 5 | /Bender.lock 6 | /Bender.local 7 | -------------------------------------------------------------------------------- /Bender.yml: -------------------------------------------------------------------------------- 1 | package: 2 | name: tech_cells_generic 3 | description: "Technology-agnostic building blocks." 4 | 5 | dependencies: 6 | common_verification: { git: "https://github.com/pulp-platform/common_verification.git", version: 0.2.0 } 7 | 8 | sources: 9 | - target: all(any(all(not(asic), not(fpga)), tech_cells_generic_include_tc_sram), not(tech_cells_generic_exclude_tc_sram)) 10 | files: 11 | # Level 0 12 | - src/rtl/tc_sram.sv 13 | - src/rtl/tc_sram_impl.sv 14 | 15 | - target: all(any(all(not(asic), not(fpga)), tech_cells_generic_include_tc_clk), not(tech_cells_generic_exclude_tc_clk)) 16 | files: 17 | # Level 0 18 | - src/rtl/tc_clk.sv 19 | 20 | - target: all(any(fpga, tech_cells_generic_include_xilinx_xpm), not(tech_cells_generic_exclude_xilinx_xpm)) 21 | files: 22 | - src/fpga/pad_functional_xilinx.sv 23 | - src/fpga/tc_clk_xilinx.sv 24 | - src/fpga/tc_sram_xilinx.sv 25 | - src/rtl/tc_sram_impl.sv 26 | 27 | - target: all(any(not(synthesis), tech_cells_generic_include_deprecated), not(tech_cells_generic_exclude_deprecated)) 28 | files: 29 | - src/deprecated/cluster_pwr_cells.sv 30 | - src/deprecated/generic_memory.sv 31 | - src/deprecated/generic_rom.sv 32 | - src/deprecated/pad_functional.sv 33 | - src/deprecated/pulp_buffer.sv 34 | - src/deprecated/pulp_pwr_cells.sv 35 | 36 | - target: all(any(not(synthesis), tech_cells_generic_include_pwr_cells), not(tech_cells_generic_exclude_pwr_cells)) 37 | files: 38 | - src/tc_pwr.sv 39 | 40 | - target: all(any(test, tech_cells_generic_include_tb_cells), not(tech_cells_generic_exclude_tb_cells)) 41 | files: 42 | - test/tb_tc_sram.sv 43 | - src/deprecated/pulp_clock_gating_async.sv 44 | 45 | # These simply wrap tc_* cells and are fine to use in any case 46 | - src/deprecated/cluster_clk_cells.sv 47 | - src/deprecated/pulp_clk_cells.sv 48 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.2.13 - 2023-09-19 8 | ### Fixed 9 | - `tc_sram_xilinx`: Fix be assignment 10 | 11 | ## 0.2.12 - 2023-08-12 12 | ### Changed 13 | - `tc_sram_xilinx`: Support ByteWidth != 8 14 | 15 | ## 0.2.11 - 2022-12-12 16 | ### Added 17 | - `tc_clk_or2`: A new generic tech cell for balanced clock OR-gates. 18 | - `tc_clk_mux2`: Added warning about misusing `tc_clk_mux2` cells. 19 | 20 | ## 0.2.10 - 2022-11-20 21 | ### Added 22 | - `tc_sram_impl`: Wrapper for `tc_sram` with implementation-specific keys and IO 23 | 24 | ### Changed 25 | - `tc_sram`: Improve simulation performance 26 | 27 | ### Fixed 28 | - `tc_clk_xilinx`: Add `IS_FUNCTIONAL` parameter to match `tc_clk_gating` interface 29 | 30 | ## 0.2.9 - 2022-03-17 31 | ### Changed 32 | - Added optional `IS_FUNCTIONAL` flag to `tc_clk_gating` cell to optionally mark them as *not required for functionality*. 33 | 34 | ## 0.2.8 35 | *Skipped* 36 | 37 | ## 0.2.7 38 | *Skipped* 39 | 40 | ## 0.2.6 - 2021-10-04 41 | ### Added 42 | - Add `pad_functional_xilinx` 43 | 44 | ### Fixed 45 | - Bender targets 46 | 47 | ### Removed 48 | - Deprecated xilinx `clk_cell`s replaced by wrappers 49 | 50 | ## 0.2.5 51 | *Skipped* 52 | 53 | ## 0.2.4 - 2021-02-04 54 | - Add `deprecated/pulp_clk_cells_xilinx.sv` to `Bender.yml` 55 | 56 | ## 0.2.3 - 2021-01-28 57 | ### Fixed 58 | - `tc_sram_xilinx`: Remove unsupported `string` type from `SimInit` parameter. 59 | - `IPApproX:` Add `tc_sram` to `src_files.yml` for proper compilation with IPApproX 60 | 61 | ## 0.2.2 - 2020-11-11 62 | ### Fixed 63 | - `Bender:` Add deprecated `pulp_clock_gating_async` for compatibility to `udma_core`. 64 | 65 | ## 0.2.1 - 2020-06-23 66 | ### Added 67 | - `Bender:` Add `rtl/tc_sram` to target `rtl`, to prevent overwriting of target specific implementations. 68 | 69 | ### Fixed 70 | - `tc_sram`: Drop string literal from parameter `SimInit` definition as synopsys throws an elaboration error. 71 | - `tc_clk:tc_clk_delay`: Add Verilator and synthesis guards. 72 | 73 | ## 0.2.0 - 2020-03-18 74 | ### Added 75 | - Add `tc_sram` and `tc_sram_xilinx`, with testbench for verifying technology specific implementations. 76 | 77 | ## 0.1.6 - 2019-11-18 78 | ### Added 79 | - Add Readme 80 | - Add Contribution Guide 81 | 82 | ### Changed 83 | - Move modules of similar topic to a single file. This makes it easier to add new modules. 84 | - Move separation between `cluster` and `pulp` to `deprecated` folder. There should be a single solution to a tech-cell. 85 | 86 | ## 0.1.1 - 2018-09-12 87 | ### Changed 88 | - Polish release 89 | - Keep Changelog 90 | - Move to sources subfolder 91 | 92 | ## 0.1.0 - 2018-09-12 93 | ### Added 94 | - Initial commit. 95 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | See [our style and contribution guidelines](https://github.com/pulp-platform/style-guidelines). -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | SOLDERPAD HARDWARE LICENSE version 0.51 2 | 3 | This license is based closely on the Apache License Version 2.0, but is not 4 | approved or endorsed by the Apache Foundation. A copy of the non-modified 5 | Apache License 2.0 can be found at http://www.apache.org/licenses/LICENSE-2.0. 6 | 7 | As this license is not currently OSI or FSF approved, the Licensor permits any 8 | Work licensed under this License, at the option of the Licensee, to be treated 9 | as licensed under the Apache License Version 2.0 (which is so approved). 10 | 11 | This License is licensed under the terms of this License and in particular 12 | clause 7 below (Disclaimer of Warranties) applies in relation to its use. 13 | 14 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 15 | 16 | 1. Definitions. 17 | 18 | "License" shall mean the terms and conditions for use, reproduction, and 19 | distribution as defined by Sections 1 through 9 of this document. 20 | 21 | "Licensor" shall mean the Rights owner or entity authorized by the Rights owner 22 | that is granting the License. 23 | 24 | "Legal Entity" shall mean the union of the acting entity and all other entities 25 | that control, are controlled by, or are under common control with that entity. 26 | For the purposes of this definition, "control" means (i) the power, direct or 27 | indirect, to cause the direction or management of such entity, whether by 28 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 29 | outstanding shares, or (iii) beneficial ownership of such entity. 30 | 31 | "You" (or "Your") shall mean an individual or Legal Entity exercising 32 | permissions granted by this License. 33 | 34 | "Rights" means copyright and any similar right including design right (whether 35 | registered or unregistered), semiconductor topography (mask) rights and 36 | database rights (but excluding Patents and Trademarks). 37 | 38 | "Source" form shall mean the preferred form for making modifications, including 39 | but not limited to source code, net lists, board layouts, CAD files, 40 | documentation source, and configuration files. 41 | 42 | "Object" form shall mean any form resulting from mechanical transformation or 43 | translation of a Source form, including but not limited to compiled object 44 | code, generated documentation, the instantiation of a hardware design and 45 | conversions to other media types, including intermediate forms such as 46 | bytecodes, FPGA bitstreams, artwork and semiconductor topographies (mask 47 | works). 48 | 49 | "Work" shall mean the work of authorship, whether in Source form or other 50 | Object form, made available under the License, as indicated by a Rights notice 51 | that is included in or attached to the work (an example is provided in the 52 | Appendix below). 53 | 54 | "Derivative Works" shall mean any work, whether in Source or Object form, that 55 | is based on (or derived from) the Work and for which the editorial revisions, 56 | annotations, elaborations, or other modifications represent, as a whole, an 57 | original work of authorship. For the purposes of this License, Derivative Works 58 | shall not include works that remain separable from, or merely link (or bind by 59 | name) or physically connect to or interoperate with the interfaces of, the Work 60 | and Derivative Works thereof. 61 | 62 | "Contribution" shall mean any design or work of authorship, including the 63 | original version of the Work and any modifications or additions to that Work or 64 | Derivative Works thereof, that is intentionally submitted to Licensor for 65 | inclusion in the Work by the Rights owner or by an individual or Legal Entity 66 | authorized to submit on behalf of the Rights owner. For the purposes of this 67 | definition, "submitted" means any form of electronic, verbal, or written 68 | communication sent to the Licensor or its representatives, including but not 69 | limited to communication on electronic mailing lists, source code control 70 | systems, and issue tracking systems that are managed by, or on behalf of, the 71 | Licensor for the purpose of discussing and improving the Work, but excluding 72 | communication that is conspicuously marked or otherwise designated in writing 73 | by the Rights owner as "Not a Contribution." 74 | 75 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 76 | of whom a Contribution has been received by Licensor and subsequently 77 | incorporated within the Work. 78 | 79 | 2. Grant of License. Subject to the terms and conditions of this License, each 80 | Contributor hereby grants to You a perpetual, worldwide, non-exclusive, 81 | no-charge, royalty-free, irrevocable license under the Rights to reproduce, 82 | prepare Derivative Works of, publicly display, publicly perform, sublicense, 83 | and distribute the Work and such Derivative Works in Source or Object form and 84 | do anything in relation to the Work as if the Rights did not exist. 85 | 86 | 3. Grant of Patent License. Subject to the terms and conditions of this 87 | License, each Contributor hereby grants to You a perpetual, worldwide, 88 | non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this 89 | section) patent license to make, have made, use, offer to sell, sell, import, 90 | and otherwise transfer the Work, where such license applies only to those 91 | patent claims licensable by such Contributor that are necessarily infringed by 92 | their Contribution(s) alone or by combination of their Contribution(s) with the 93 | Work to which such Contribution(s) was submitted. If You institute patent 94 | litigation against any entity (including a cross-claim or counterclaim in a 95 | lawsuit) alleging that the Work or a Contribution incorporated within the Work 96 | constitutes direct or contributory patent infringement, then any patent 97 | licenses granted to You under this License for that Work shall terminate as of 98 | the date such litigation is filed. 99 | 100 | 4. Redistribution. You may reproduce and distribute copies of the Work or 101 | Derivative Works thereof in any medium, with or without modifications, and in 102 | Source or Object form, provided that You meet the following conditions: 103 | 104 | You must give any other recipients of the Work or Derivative Works a copy 105 | of this License; and 106 | 107 | You must cause any modified files to carry prominent notices stating that 108 | You changed the files; and 109 | 110 | You must retain, in the Source form of any Derivative Works that You 111 | distribute, all copyright, patent, trademark, and attribution notices from 112 | the Source form of the Work, excluding those notices that do not pertain to 113 | any part of the Derivative Works; and 114 | 115 | If the Work includes a "NOTICE" text file as part of its distribution, then 116 | any Derivative Works that You distribute must include a readable copy of 117 | the attribution notices contained within such NOTICE file, excluding those 118 | notices that do not pertain to any part of the Derivative Works, in at 119 | least one of the following places: within a NOTICE text file distributed as 120 | part of the Derivative Works; within the Source form or documentation, if 121 | provided along with the Derivative Works; or, within a display generated by 122 | the Derivative Works, if and wherever such third-party notices normally 123 | appear. The contents of the NOTICE file are for informational purposes only 124 | and do not modify the License. You may add Your own attribution notices 125 | within Derivative Works that You distribute, alongside or as an addendum to 126 | the NOTICE text from the Work, provided that such additional attribution 127 | notices cannot be construed as modifying the License. You may add Your own 128 | copyright statement to Your modifications and may provide additional or 129 | different license terms and conditions for use, reproduction, or 130 | distribution of Your modifications, or for any such Derivative Works as a 131 | whole, provided Your use, reproduction, and distribution of the Work 132 | otherwise complies with the conditions stated in this License. 133 | 134 | 5. Submission of Contributions. Unless You explicitly state otherwise, any 135 | Contribution intentionally submitted for inclusion in the Work by You to the 136 | Licensor shall be under the terms and conditions of this License, without any 137 | additional terms or conditions. Notwithstanding the above, nothing herein shall 138 | supersede or modify the terms of any separate license agreement you may have 139 | executed with Licensor regarding such Contributions. 140 | 141 | 6. Trademarks. This License does not grant permission to use the trade names, 142 | trademarks, service marks, or product names of the Licensor, except as required 143 | for reasonable and customary use in describing the origin of the Work and 144 | reproducing the content of the NOTICE file. 145 | 146 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in 147 | writing, Licensor provides the Work (and each Contributor provides its 148 | Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 149 | KIND, either express or implied, including, without limitation, any warranties 150 | or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any risks 153 | associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, whether in 156 | tort (including negligence), contract, or otherwise, unless required by 157 | applicable law (such as deliberate and grossly negligent acts) or agreed to in 158 | writing, shall any Contributor be liable to You for damages, including any 159 | direct, indirect, special, incidental, or consequential damages of any 160 | character arising as a result of this License or out of the use or inability to 161 | use the Work (including but not limited to damages for loss of goodwill, work 162 | stoppage, computer failure or malfunction, or any and all other commercial 163 | damages or losses), even if such Contributor has been advised of the 164 | possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or 167 | Derivative Works thereof, You may choose to offer, and charge a fee for, 168 | acceptance of support, warranty, indemnity, or other liability obligations 169 | and/or rights consistent with this License. However, in accepting such 170 | obligations, You may act only on Your own behalf and on Your sole 171 | responsibility, not on behalf of any other Contributor, and only if You agree 172 | to indemnify, defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason of your 174 | accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Generic Technology Cells (API to Cell Library) 2 | 3 | Maintainer: Nils Wistoff 4 | 5 | This repository contains technology related cells like SRAMs, clock-gating cells, power management cells. The description here are: 6 | 7 | - **Behavioral**: Meant for RTL simulation only. 8 | - **FPGA**: Meant for FPGA implementation. Currently we only support Xilinx FPGAs. But we are happy to accept patches for Altera or other devices. 9 | 10 | It is the purpose of your technology specific file to include the cells with correct drive strength. We do not make the assumption in the front-end anymore. 11 | 12 | > As this layer needs to be re-implemented for every new technology keep it thin! 13 | 14 | ## Cell Contents 15 | 16 | If you want to get started in your own technology (either an unsupported FPGA or an ASIC technology) please provide implementations for the cells in this repository. 17 | 18 | ### Clock Cells 19 | 20 | Clock cells usually are care-fully designed cells which do not exhibit any glitches. Therefore they need to be manually instantiated in ASIC designs. All clock cells can be found in `tc_clk.sv`. 21 | 22 | | Name | Description | Status | Xilinx | 23 | |-------------------|------------------------------|--------|--------------------| 24 | | `tc_clk_and2` | Clock and gate | active | :white_check_mark: | 25 | | `tc_clk_buffer` | Clock buffer | active | :white_check_mark: | 26 | | `tc_clk_gating` | Integrated clock gating cell | active | :white_check_mark: | 27 | | `tc_clk_inverter` | Clock inverter | active | :white_check_mark: | 28 | | `tc_clk_mux2` | Clock Mux with two inputs | active | :white_check_mark: | 29 | | `tc_clk_xor2` | Clock Xor | active | :white_check_mark: | 30 | | `tc_clk_or2` | Clock Or | active | :white_check_mark: | 31 | | `tc_clk_delay` | Programmable clock-delay | active | | 32 | 33 | ### Memory 34 | 35 | | Name | Description | Status | Xilinx | 36 | |-----------|----------------------------------------------------------|--------|--------------------| 37 | | `tc_sram` | Configurable SRAM | active | :white_check_mark: | 38 | 39 | ### Power Cells 40 | 41 | Power cells are mostly used for advanced power gating features and not used in any of our open-source IPs. However, feel-free to re-use them. All clock cells can be found in `tc_pwr.sv`. 42 | 43 | | Name | Description | Status | 44 | |-------------------------------------|--------------------------------------|--------| 45 | | `tc_pwr_level_shifter_in` | Level Shifter | active | 46 | | `tc_pwr_level_shifter_in_clamp_lo` | Level Shifter w/ clamp to `1'b0` | active | 47 | | `tc_pwr_level_shifter_in_clamp_hi` | Level Shifter w/ clamp to `1'b1` | active | 48 | | `tc_pwr_level_shifter_out` | Level Shifter | active | 49 | | `tc_pwr_level_shifter_out_clamp_lo` | Level Shifter w/ clamp to `1'b0` | active | 50 | | `tc_pwr_level_shifter_out_clamp_hi` | Level Shifter w/ clamp to `1'b1` | active | 51 | | `tc_pwr_power_gating` | Power Gate with ctrl and status pins | active | 52 | | `tc_pwr_isolation_lo` | Isolation Cell w/ isolate to `1'b0` | active | 53 | | `tc_pwr_isolation_hi` | Isolation Cell w/ isolate to `1'b1` | active | 54 | -------------------------------------------------------------------------------- /scripts/compile_vsim.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2014-2020 ETH Zurich, University of Bologna 3 | # 4 | # Copyright and related rights are licensed under the Solderpad Hardware 5 | # License, Version 0.51 (the "License"); you may not use this file except in 6 | # compliance with the License. You may obtain a copy of the License at 7 | # http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 8 | # or agreed to in writing, software, hardware and materials distributed under 9 | # this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 10 | # CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | # specific language governing permissions and limitations under the License. 12 | # 13 | # Fabian Schuiki 14 | # Andreas Kurth 15 | 16 | set -e 17 | 18 | bender script vsim -t test -t rtl --vlog-arg="-svinputport=compat" --vlog-arg="-override_timescale 1ns/1ps" > compile.tcl 19 | echo 'return 0' >> compile.tcl 20 | vsim -c -do 'exit -code [source compile.tcl]' 21 | -------------------------------------------------------------------------------- /scripts/run_vsim.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2014-2018 ETH Zurich, University of Bologna 3 | # 4 | # Copyright and related rights are licensed under the Solderpad Hardware 5 | # License, Version 0.51 (the "License"); you may not use this file except in 6 | # compliance with the License. You may obtain a copy of the License at 7 | # http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 8 | # or agreed to in writing, software, hardware and materials distributed under 9 | # this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 10 | # CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | # specific language governing permissions and limitations under the License. 12 | # 13 | # Fabian Schuiki 14 | # Andreas Kurth 15 | 16 | set -e 17 | ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) 18 | 19 | [ ! -z "$VSIM" ] || VSIM=vsim 20 | 21 | call_vsim() { 22 | echo "run -all" | $VSIM "$@" | tee vsim.log 2>&1 23 | grep "Errors: 0," vsim.log 24 | } 25 | 26 | for PORTS in 1 2; do 27 | for LATENCY in 0 1 2; do 28 | for WORDS in 1 420 1024; do 29 | for DWIDTH in 1 42 64; do 30 | for BYTEWIDTH in 1 8 9; do 31 | call_vsim tb_tc_sram -GNumPorts=$PORTS -GLatency=$LATENCY -GNumWords=$WORDS -GDataWidth=$DWIDTH -GByteWidth=$BYTEWIDTH 32 | done 33 | done 34 | done 35 | done 36 | done 37 | 38 | -------------------------------------------------------------------------------- /scripts/run_xsim.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) 2020 ETH Zurich, University of Bologna 3 | # 4 | # Copyright and related rights are licensed under the Solderpad Hardware 5 | # License, Version 0.51 (the "License"); you may not use this file except in 6 | # compliance with the License. You may obtain a copy of the License at 7 | # http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 8 | # or agreed to in writing, software, hardware and materials distributed under 9 | # this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 10 | # CONDITIONS OF ANY KIND, either express or implied. See the License for the 11 | # specific language governing permissions and limitations under the License. 12 | # 13 | # Wolfgang Roenninger 14 | 15 | set -e 16 | ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) 17 | 18 | VIVADO_VER="2018.2" 19 | 20 | bender script vivado-sim -t test > ${ROOT}/scripts/vivado/add_sources.tcl 21 | 22 | vivado-${VIVADO_VER} vivado -mode batch -source ${ROOT}/scripts/vivado/run_xsim.tcl 23 | -------------------------------------------------------------------------------- /scripts/vivado/run_xsim.tcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 ETH Zurich, University of Bologna 2 | # 3 | # Copyright and related rights are licensed under the Solderpad Hardware 4 | # License, Version 0.51 (the "License"); you may not use this file except in 5 | # compliance with the License. You may obtain a copy of the License at 6 | # http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 7 | # or agreed to in writing, software, hardware and materials distributed under 8 | # this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 9 | # CONDITIONS OF ANY KIND, either express or implied. See the License for the 10 | # specific language governing permissions and limitations under the License. 11 | # 12 | # Wolfgang Roenninger 13 | 14 | 15 | #################################################################################################### 16 | # This script runs xsim in vivado 17 | #################################################################################################### 18 | 19 | # set script root to location where this script is located 20 | set SCRIPT_ROOT [file normalize [file dirname [info script]]] 21 | 22 | # check if the enviroment variables are set, if not, set default to genesys2 23 | if {![info exists ::env(XILINX_PART)]} { 24 | puts "Set default XILINX_PART" 25 | set env(XILINX_PART) "xc7k325tffg900-2" 26 | } 27 | if {![info exists ::env(XILINX_BOARD)]} { 28 | puts "Set default XILINX_BOARD" 29 | set env(XILINX_BOARD) "digilentinc.com:genesys2:part0:1.1" 30 | } 31 | 32 | #################################################################################################### 33 | # Create project 34 | #################################################################################################### 35 | 36 | set project tc_generic_sim 37 | 38 | create_project $project . -force -part $::env(XILINX_PART) 39 | set_property board_part $::env(XILINX_BOARD) [current_project] 40 | 41 | # set number of threads 42 | set_param general.maxThreads 8 43 | 44 | #################################################################################################### 45 | # add design sources 46 | #################################################################################################### 47 | 48 | source $SCRIPT_ROOT/add_sources.tcl 49 | set_property top tb_tc_sram [get_filesets sim_1] 50 | set_property top_lib xil_defaultlib [get_filesets sim_1] 51 | 52 | #################################################################################################### 53 | # Simulate tc_sram_xilinx with one port 54 | #################################################################################################### 55 | 56 | set_property generic NumPorts=32'd1 [get_fileset sim_1] 57 | update_ip_catalog 58 | 59 | update_compile_order -fileset sources_1 60 | 61 | launch_simulation 62 | 63 | run -all 64 | 65 | close_sim 66 | 67 | #################################################################################################### 68 | # Simulate tc_sram_xilinx with two ports 69 | #################################################################################################### 70 | 71 | set_property generic NumPorts=32'd2 [get_fileset sim_1] 72 | update_ip_catalog 73 | 74 | update_compile_order -fileset sources_1 75 | 76 | launch_simulation 77 | 78 | run -all 79 | 80 | close_sim 81 | -------------------------------------------------------------------------------- /src/deprecated/cluster_clk_cells.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2019 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | module cluster_clock_and2 ( 12 | input logic clk0_i, 13 | input logic clk1_i, 14 | output logic clk_o 15 | ); 16 | 17 | tc_clk_and2 i_tc_clk_and2 ( 18 | .clk0_i, 19 | .clk1_i, 20 | .clk_o 21 | ); 22 | 23 | endmodule 24 | 25 | module cluster_clock_buffer ( 26 | input logic clk_i, 27 | output logic clk_o 28 | ); 29 | 30 | tc_clk_buffer i_tc_clk_buffer ( 31 | .clk_i, 32 | .clk_o 33 | ); 34 | 35 | endmodule 36 | 37 | // Description: Behavioral model of an integrated clock-gating cell (ICG) 38 | module cluster_clock_gating ( 39 | input logic clk_i, 40 | input logic en_i, 41 | input logic test_en_i, 42 | output logic clk_o 43 | ); 44 | 45 | tc_clk_gating i_tc_clk_gating ( 46 | .clk_i, 47 | .en_i, 48 | .test_en_i, 49 | .clk_o 50 | ); 51 | 52 | endmodule 53 | 54 | module cluster_clock_inverter ( 55 | input logic clk_i, 56 | output logic clk_o 57 | ); 58 | 59 | tc_clk_inverter i_tc_clk_inverter ( 60 | .clk_i, 61 | .clk_o 62 | ); 63 | 64 | endmodule 65 | 66 | module cluster_clock_mux2 ( 67 | input logic clk0_i, 68 | input logic clk1_i, 69 | input logic clk_sel_i, 70 | output logic clk_o 71 | ); 72 | 73 | tc_clk_mux2 i_tc_clk_mux2 ( 74 | .clk0_i, 75 | .clk1_i, 76 | .clk_sel_i, 77 | .clk_o 78 | ); 79 | 80 | endmodule 81 | 82 | module cluster_clock_xor2 ( 83 | input logic clk0_i, 84 | input logic clk1_i, 85 | output logic clk_o 86 | ); 87 | 88 | tc_clk_xor2 i_tc_clk_xor2 ( 89 | .clk0_i, 90 | .clk1_i, 91 | .clk_o 92 | ); 93 | 94 | endmodule 95 | -------------------------------------------------------------------------------- /src/deprecated/cluster_pwr_cells.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | // Description: This file contains power-related cells 12 | // Mainly shifters at the moment. 13 | 14 | module cluster_level_shifter_in ( 15 | input logic in_i, 16 | output logic out_o 17 | ); 18 | 19 | assign out_o = in_i; 20 | 21 | endmodule 22 | 23 | module cluster_level_shifter_in_clamp ( 24 | input logic in_i, 25 | output logic out_o, 26 | input logic clamp_i 27 | ); 28 | 29 | assign out_o = clamp_i ? 1'b0 : in_i; 30 | 31 | endmodule 32 | 33 | module cluster_level_shifter_inout ( 34 | input logic data_i, 35 | output logic data_o 36 | ); 37 | 38 | assign data_o = data_i; 39 | 40 | endmodule 41 | 42 | module cluster_level_shifter_out ( 43 | input logic in_i, 44 | output logic out_o 45 | ); 46 | 47 | assign out_o = in_i; 48 | 49 | endmodule 50 | 51 | module cluster_level_shifter_out_clamp ( 52 | input logic in_i, 53 | output logic out_o, 54 | input logic clamp_i 55 | ); 56 | 57 | assign out_o = clamp_i ? 1'b0 : in_i; 58 | 59 | endmodule 60 | -------------------------------------------------------------------------------- /src/deprecated/generic_memory.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | module generic_memory 12 | #( 13 | parameter ADDR_WIDTH = 12, 14 | parameter DATA_WIDTH = 32, 15 | parameter BE_WIDTH = DATA_WIDTH/8 16 | ) 17 | ( 18 | input logic CLK, 19 | input logic INITN, 20 | 21 | input logic CEN, 22 | input logic [ADDR_WIDTH-1:0] A, 23 | input logic WEN, 24 | input logic [DATA_WIDTH-1:0] D, 25 | input logic [BE_WIDTH-1:0] BEN, 26 | 27 | output logic [DATA_WIDTH-1:0] Q 28 | ); 29 | 30 | localparam NUM_WORDS = 2**ADDR_WIDTH; 31 | 32 | logic [DATA_WIDTH-1:0] MEM [NUM_WORDS-1:0]; 33 | logic [DATA_WIDTH-1:0] M; 34 | genvar i,j; 35 | 36 | generate 37 | for (i=0; i, ETH Zurich 12 | // 13 | // Description: Xilinx implementation using the XPM constructs for `tc_sram` 14 | // Make sure that Vivado can detect the XPM macros by issuing 15 | // the `auto_detect_xpm` or `set_property XPM_LIBRARIES XPM_MEMORY [current_project]` 16 | // command. Currently the Xilinx macros are always initialized to all zero! 17 | // The behaviour, parameters and ports are described in the header of `rtl/tc_sram.sv`. 18 | 19 | module tc_sram #( 20 | parameter int unsigned NumWords = 32'd1024, // Number of Words in data array 21 | parameter int unsigned DataWidth = 32'd128, // Data signal width (in bits) 22 | parameter int unsigned ByteWidth = 32'd8, // Width of a data byte (in bits) 23 | parameter int unsigned NumPorts = 32'd2, // Number of read and write ports 24 | parameter int unsigned Latency = 32'd1, // Latency when the read data is available 25 | parameter SimInit = "zeros", // Simulation initialization, fixed to zero here! 26 | parameter bit PrintSimCfg = 1'b0, // Print configuration 27 | parameter ImplKey = "none", // Reference to specific implementation 28 | // DEPENDENT PARAMETERS, DO NOT OVERWRITE! 29 | parameter int unsigned AddrWidth = (NumWords > 32'd1) ? $clog2(NumWords) : 32'd1, 30 | parameter int unsigned BeWidth = (DataWidth + ByteWidth - 32'd1) / ByteWidth, // ceil_div 31 | parameter type addr_t = logic [AddrWidth-1:0], 32 | parameter type data_t = logic [DataWidth-1:0], 33 | parameter type be_t = logic [BeWidth-1:0] 34 | ) ( 35 | input logic clk_i, // Clock 36 | input logic rst_ni, // Asynchronous reset active low 37 | // input ports 38 | input logic [NumPorts-1:0] req_i, // request 39 | input logic [NumPorts-1:0] we_i, // write enable 40 | input addr_t [NumPorts-1:0] addr_i, // request address 41 | input data_t [NumPorts-1:0] wdata_i, // write data 42 | input be_t [NumPorts-1:0] be_i, // write byte enable 43 | // output ports 44 | output data_t [NumPorts-1:0] rdata_o // read data 45 | ); 46 | 47 | 48 | // XPM only supports a byte width of 8. Hence, map each input byte to a multiple of 8 bit 49 | // Number of 8-bit bytes (memory bytes) per data byte 50 | localparam int unsigned BytesPerByte = (ByteWidth + 7) / 8; 51 | // Number of allocated memory bits per data byte 52 | localparam int unsigned ByteWidthAligned = BytesPerByte * 8; 53 | // Resulting memory width and size 54 | localparam int unsigned DataWidthAligned = ByteWidthAligned * BeWidth; 55 | localparam int unsigned Size = NumWords * DataWidthAligned; 56 | 57 | typedef logic [DataWidthAligned-1:0] data_aligned_t; 58 | typedef logic [BytesPerByte*BeWidth-1:0] be_aligned_t; 59 | 60 | data_aligned_t [NumPorts-1:0] wdata_pad; 61 | data_aligned_t [NumPorts-1:0] rdata_pad; 62 | data_aligned_t [NumPorts-1:0] wdata_al; 63 | data_aligned_t [NumPorts-1:0] rdata_al; 64 | be_aligned_t [NumPorts-1:0] be_al; 65 | be_aligned_t [NumPorts-1:0] we_al; 66 | 67 | for (genvar i = 0; i < NumPorts; i++) begin : gen_align 68 | // Zero-pad data to allow bit select 69 | assign wdata_pad[i] = data_aligned_t'(wdata_i[i]); 70 | assign rdata_o[i] = data_t'(rdata_pad[i]); 71 | for (genvar j = 0; j < BeWidth; j++) begin 72 | // Unpack data 73 | assign wdata_al[i][j*ByteWidthAligned+:ByteWidthAligned] = ByteWidthAligned'(wdata_pad[i][j*ByteWidth+:ByteWidth]); 74 | assign rdata_pad[i][j*ByteWidth+:ByteWidth] = ByteWidth'(rdata_al[i][j*ByteWidthAligned+:ByteWidthAligned]); 75 | // In case ByteWidth > 8, let each be_i drive the corresponding number of memory be 76 | assign be_al[i][j*BytesPerByte+:BytesPerByte] = {BytesPerByte{be_i[i][j]}}; 77 | assign we_al[i][j*BytesPerByte+:BytesPerByte] = {BytesPerByte{be_i[i][j] & we_i[i]}}; 78 | end 79 | end 80 | 81 | if (NumPorts == 32'd1) begin : gen_1_ports 82 | // xpm_memory_spram: Single Port RAM 83 | // XilinxParameterizedMacro, version 2018.1 84 | xpm_memory_spram#( 85 | .ADDR_WIDTH_A ( AddrWidth ), // DECIMAL 86 | .AUTO_SLEEP_TIME ( 0 ), // DECIMAL 87 | .BYTE_WRITE_WIDTH_A ( 8 ), // DECIMAL 88 | .ECC_MODE ( "no_ecc" ), // String 89 | .MEMORY_INIT_FILE ( "none" ), // String 90 | .MEMORY_INIT_PARAM ( "0" ), // String 91 | .MEMORY_OPTIMIZATION ( "true" ), // String 92 | .MEMORY_PRIMITIVE ( "auto" ), // String 93 | .MEMORY_SIZE ( Size ), // DECIMAL in bit! 94 | .MESSAGE_CONTROL ( 0 ), // DECIMAL 95 | .READ_DATA_WIDTH_A ( DataWidthAligned ), // DECIMAL 96 | .READ_LATENCY_A ( Latency ), // DECIMAL 97 | .READ_RESET_VALUE_A ( "0" ), // String 98 | .USE_MEM_INIT ( 1 ), // DECIMAL 99 | .WAKEUP_TIME ( "disable_sleep" ), // String 100 | .WRITE_DATA_WIDTH_A ( DataWidthAligned ), // DECIMAL 101 | .WRITE_MODE_A ( "no_change" ) // String 102 | ) i_xpm_memory_spram ( 103 | .dbiterra ( /*not used*/ ), // 1-bit output: Status signal to indicate double biterror 104 | .douta ( rdata_al[0] ), // READ_DATA_WIDTH_A-bitoutput: Data output for port A 105 | .sbiterra ( /*not used*/ ), // 1-bit output: Status signal to indicate single biterror 106 | .addra ( addr_i[0] ), // ADDR_WIDTH_A-bit input: Address for port A 107 | .clka ( clk_i ), // 1-bit input: Clock signal for port A. 108 | .dina ( wdata_al[0] ), // WRITE_DATA_WIDTH_A-bitinput: Data input for port A 109 | .ena ( req_i[0] ), // 1-bit input: Memory enable signal for port A. 110 | .injectdbiterra ( 1'b0 ), // 1-bit input: Controls double biterror injection 111 | .injectsbiterra ( 1'b0 ), // 1-bit input: Controls single biterror injection 112 | .regcea ( 1'b1 ), // 1-bit input: Clock Enable for the last register 113 | .rsta ( ~rst_ni ), // 1-bit input: Reset signal for the final port A output 114 | .sleep ( 1'b0 ), // 1-bit input: sleep signal to enable the dynamic power save 115 | .wea ( we_al[0] ) 116 | ); 117 | end else if (NumPorts == 32'd2) begin : gen_2_ports 118 | // xpm_memory_tdpram: True Dual Port RAM 119 | // XilinxParameterizedMacro, version 2018.1 120 | xpm_memory_tdpram#( 121 | .ADDR_WIDTH_A ( AddrWidth ), // DECIMAL 122 | .ADDR_WIDTH_B ( AddrWidth ), // DECIMAL 123 | .AUTO_SLEEP_TIME ( 0 ), // DECIMAL 124 | .BYTE_WRITE_WIDTH_A ( 8 ), // DECIMAL 125 | .BYTE_WRITE_WIDTH_B ( 8 ), // DECIMAL 126 | .CLOCKING_MODE ( "common_clock" ), // String 127 | .ECC_MODE ( "no_ecc" ), // String 128 | .MEMORY_INIT_FILE ( "none" ), // String 129 | .MEMORY_INIT_PARAM ( "0" ), // String 130 | .MEMORY_OPTIMIZATION ( "true" ), // String 131 | .MEMORY_PRIMITIVE ( "auto" ), // String 132 | .MEMORY_SIZE ( Size ), // DECIMAL in bits! 133 | .MESSAGE_CONTROL ( 0 ), // DECIMAL 134 | .READ_DATA_WIDTH_A ( DataWidthAligned ), // DECIMAL 135 | .READ_DATA_WIDTH_B ( DataWidthAligned ), // DECIMAL 136 | .READ_LATENCY_A ( Latency ), // DECIMAL 137 | .READ_LATENCY_B ( Latency ), // DECIMAL 138 | .READ_RESET_VALUE_A ( "0" ), // String 139 | .READ_RESET_VALUE_B ( "0" ), // String 140 | .USE_EMBEDDED_CONSTRAINT ( 0 ), // DECIMAL 141 | .USE_MEM_INIT ( 1 ), // DECIMAL 142 | .WAKEUP_TIME ( "disable_sleep" ), // String 143 | .WRITE_DATA_WIDTH_A ( DataWidthAligned ), // DECIMAL 144 | .WRITE_DATA_WIDTH_B ( DataWidthAligned ), // DECIMAL 145 | .WRITE_MODE_A ( "no_change" ), // String 146 | .WRITE_MODE_B ( "no_change" ) // String 147 | ) i_xpm_memory_tdpram ( 148 | .dbiterra ( /*not used*/ ), // 1-bit output: Doubble bit error A 149 | .dbiterrb ( /*not used*/ ), // 1-bit output: Doubble bit error B 150 | .sbiterra ( /*not used*/ ), // 1-bit output: Single bit error A 151 | .sbiterrb ( /*not used*/ ), // 1-bit output: Single bit error B 152 | .addra ( addr_i[0] ), // ADDR_WIDTH_A-bit input: Address for port A 153 | .addrb ( addr_i[1] ), // ADDR_WIDTH_B-bit input: Address for port B 154 | .clka ( clk_i ), // 1-bit input: Clock signal for port A 155 | .clkb ( clk_i ), // 1-bit input: Clock signal for port B 156 | .dina ( wdata_al[0] ), // WRITE_DATA_WIDTH_A-bit input: Data input for port A 157 | .dinb ( wdata_al[1] ), // WRITE_DATA_WIDTH_B-bit input: Data input for port B 158 | .douta ( rdata_al[0] ), // READ_DATA_WIDTH_A-bit output: Data output for port A 159 | .doutb ( rdata_al[1] ), // READ_DATA_WIDTH_B-bit output: Data output for port B 160 | .ena ( req_i[0] ), // 1-bit input: Memory enable signal for port A 161 | .enb ( req_i[1] ), // 1-bit input: Memory enable signal for port B 162 | .injectdbiterra ( 1'b0 ), // 1-bit input: Controls doublebiterror injection on input data 163 | .injectdbiterrb ( 1'b0 ), // 1-bit input: Controls doublebiterror injection on input data 164 | .injectsbiterra ( 1'b0 ), // 1-bit input: Controls singlebiterror injection on input data 165 | .injectsbiterrb ( 1'b0 ), // 1-bit input: Controls singlebiterror injection on input data 166 | .regcea ( 1'b1 ), // 1-bit input: Clock Enable for the last register stage 167 | .regceb ( 1'b1 ), // 1-bit input: Clock Enable for the last register stage 168 | .rsta ( ~rst_ni ), // 1-bit input: Reset signal for the final port A output 169 | .rstb ( ~rst_ni ), // 1-bit input: Reset signal for the final port B output 170 | .sleep ( 1'b0 ), // 1-bit input: sleep signal to enable the dynamic power 171 | .wea ( we_al[0] ), // WRITE_DATA_WIDTH_A-bit input: Write enable vector for port A 172 | .web ( we_al[1] ) // WRITE_DATA_WIDTH_B-bit input: Write enable vector for port B 173 | ); 174 | end else begin : gen_err_ports 175 | $fatal(1, "Not supported port parametrization for NumPorts: %0d", NumPorts); 176 | end 177 | 178 | // Validate parameters. 179 | // pragma translate_off 180 | `ifndef VERILATOR 181 | `ifndef TARGET_SYNTHESIS 182 | initial begin: p_assertions 183 | assert (SimInit == "zeros") else $fatal(1, "The Xilinx `tc_sram` has fixed SimInit: zeros"); 184 | assert ($bits(addr_i) == NumPorts * AddrWidth) else $fatal(1, "AddrWidth problem on `addr_i`"); 185 | assert ($bits(wdata_i) == NumPorts * DataWidth) else $fatal(1, "DataWidth problem on `wdata_i`"); 186 | assert ($bits(be_i) == NumPorts * BeWidth) else $fatal(1, "BeWidth problem on `be_i`" ); 187 | assert ($bits(rdata_o) == NumPorts * DataWidth) else $fatal(1, "DataWidth problem on `rdata_o`"); 188 | assert (NumWords >= 32'd1) else $fatal(1, "NumWords has to be > 0"); 189 | assert (DataWidth >= 32'd1) else $fatal(1, "DataWidth has to be > 0"); 190 | assert (ByteWidth >= 32'd1) else $fatal(1, "ByteWidth has to be > 0"); 191 | assert (NumPorts >= 32'd1) else $fatal(1, "The number of ports must be at least 1!"); 192 | end 193 | initial begin: p_sim_hello 194 | if (PrintSimCfg) begin 195 | $display("#################################################################################"); 196 | $display("tc_sram functional instantiated with the configuration:" ); 197 | $display("Instance: %m" ); 198 | $display("Number of ports (dec): %0d", NumPorts ); 199 | $display("Number of words (dec): %0d", NumWords ); 200 | $display("Address width (dec): %0d", AddrWidth ); 201 | $display("Data width (dec): %0d", DataWidth ); 202 | $display("Byte width (dec): %0d", ByteWidth ); 203 | $display("Byte enable width (dec): %0d", BeWidth ); 204 | $display("Latency Cycles (dec): %0d", Latency ); 205 | $display("Simulation init (str): %0s", SimInit ); 206 | $display("#################################################################################"); 207 | end 208 | end 209 | for (genvar i = 0; i < NumPorts; i++) begin : gen_assertions 210 | assert property ( @(posedge clk_i) disable iff (!rst_ni) 211 | (req_i[i] |-> (addr_i[i] < NumWords))) else 212 | $warning("Request address %0h not mapped, port %0d, expect random write or read behavior!", 213 | addr_i[i], i); 214 | end 215 | 216 | `endif 217 | `endif 218 | // pragma translate_on 219 | 220 | endmodule 221 | -------------------------------------------------------------------------------- /src/rtl/tc_clk.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2019 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | module tc_clk_and2 ( 12 | input logic clk0_i, 13 | input logic clk1_i, 14 | output logic clk_o 15 | ); 16 | 17 | assign clk_o = clk0_i & clk1_i; 18 | 19 | endmodule 20 | 21 | module tc_clk_buffer ( 22 | input logic clk_i, 23 | output logic clk_o 24 | ); 25 | 26 | assign clk_o = clk_i; 27 | 28 | endmodule 29 | 30 | // Description: Behavioral model of an integrated clock-gating cell (ICG) 31 | module tc_clk_gating #( 32 | /// This paramaeter is a hint for tool/technology specific mappings of this 33 | /// tech_cell. It indicates wether this particular clk gate instance is 34 | /// required for functional correctness or just instantiated for power 35 | /// savings. If IS_FUNCTIONAL == 0, technology specific mappings might 36 | /// replace this cell with a feedthrough connection without any gating. 37 | parameter bit IS_FUNCTIONAL = 1'b1 38 | )( 39 | input logic clk_i, 40 | input logic en_i, 41 | input logic test_en_i, 42 | output logic clk_o 43 | ); 44 | 45 | logic clk_en; 46 | 47 | always_latch begin 48 | if (clk_i == 1'b0) clk_en <= en_i | test_en_i; 49 | end 50 | 51 | assign clk_o = clk_i & clk_en; 52 | 53 | endmodule 54 | 55 | module tc_clk_inverter ( 56 | input logic clk_i, 57 | output logic clk_o 58 | ); 59 | 60 | assign clk_o = ~clk_i; 61 | 62 | endmodule 63 | 64 | // Warning: Typical clock mux cells of a technologies std cell library ARE NOT 65 | // GLITCH FREE!! The only difference to a regular multiplexer cell is that they 66 | // feature balanced rise- and fall-times. In other words: SWITCHING FROM ONE 67 | // CLOCK TO THE OTHER CAN INTRODUCE GLITCHES. ALSO, GLITCHES ON THE SELECT LINE 68 | // DIRECTLY TRANSLATE TO GLITCHES ON THE OUTPUT CLOCK!! This cell is only 69 | // intended to be used for quasi-static switching between clocks when one of the 70 | // clocks is anyway inactive or if the downstream logic remains gated or in 71 | // reset state during the transition phase. If you need dynamic switching 72 | // between arbitrary input clocks without introducing glitches, have a look at 73 | // the clk_mux_glitch_free cell in the pulp-platform/common_cells repository. 74 | module tc_clk_mux2 ( 75 | input logic clk0_i, 76 | input logic clk1_i, 77 | input logic clk_sel_i, 78 | output logic clk_o 79 | ); 80 | 81 | assign clk_o = (clk_sel_i) ? clk1_i : clk0_i; 82 | 83 | endmodule 84 | 85 | module tc_clk_xor2 ( 86 | input logic clk0_i, 87 | input logic clk1_i, 88 | output logic clk_o 89 | ); 90 | 91 | assign clk_o = clk0_i ^ clk1_i; 92 | 93 | endmodule 94 | 95 | module tc_clk_or2 ( 96 | input logic clk0_i, 97 | input logic clk1_i, 98 | output logic clk_o 99 | ); 100 | 101 | assign clk_o = clk0_i | clk1_i; 102 | 103 | endmodule 104 | 105 | `ifndef SYNTHESIS 106 | module tc_clk_delay #( 107 | parameter int unsigned Delay = 300ps 108 | ) ( 109 | input logic in_i, 110 | output logic out_o 111 | ); 112 | 113 | // pragma translate_off 114 | `ifndef VERILATOR 115 | assign #(Delay) out_o = in_i; 116 | `endif 117 | // pragma translate_on 118 | 119 | endmodule 120 | `endif 121 | -------------------------------------------------------------------------------- /src/rtl/tc_sram.sv: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | // Author: Wolfgang Roenninger 12 | 13 | // Description: Functional module of a generic SRAM 14 | // 15 | // Parameters: 16 | // - NumWords: Number of words in the macro. Address width can be calculated with: 17 | // `AddrWidth = (NumWords > 32'd1) ? $clog2(NumWords) : 32'd1` 18 | // The module issues a warning if there is a request on an address which is 19 | // not in range. 20 | // - DataWidth: Width of the ports `wdata_i` and `rdata_o`. 21 | // - ByteWidth: Width of a byte, the byte enable signal `be_i` can be calculated with the 22 | // ceiling division `ceil(DataWidth, ByteWidth)`. 23 | // - NumPorts: Number of read and write ports. Each is a full port. Ports with a higher 24 | // index read and write after the ones with lower indices. 25 | // - Latency: Read latency, the read data is available this many cycles after a request. 26 | // - SimInit: Macro simulation initialization. Values are: 27 | // "zeros": Each bit gets initialized with 1'b0. 28 | // "ones": Each bit gets initialized with 1'b1. 29 | // "random": Each bit gets random initialized with 1'b0 or 1'b1. 30 | // "none": Each bit gets initialized with 1'bx. (default) 31 | // - PrintSimCfg: Prints at the beginning of the simulation a `Hello` message with 32 | // the instantiated parameters and signal widths. 33 | // - ImplKey: Key by which an instance can refer to a specific implementation (e.g. macro). 34 | // May be used to look up additional parameters for implementation (e.g. generator, 35 | // line width, muxing) in an external reference, such as a configuration file. 36 | // 37 | // Ports: 38 | // - `clk_i`: Clock 39 | // - `rst_ni`: Asynchronous reset, active low 40 | // - `req_i`: Request, active high 41 | // - `we_i`: Write request, active high 42 | // - `addr_i`: Request address 43 | // - `wdata_i`: Write data, has to be valid on request 44 | // - `be_i`: Byte enable, active high 45 | // - `rdata_o`: Read data, valid `Latency` cycles after a request with `we_i` low. 46 | // 47 | // Behaviour: 48 | // - Address collision: When Ports are making a write access onto the same address, 49 | // the write operation will start at the port with the lowest address 50 | // index, each port will overwrite the changes made by the previous ports 51 | // according how the respective `be_i` signal is set. 52 | // - Read data on write: This implementation will not produce a read data output on the signal 53 | // `rdata_o` when `req_i` and `we_i` are asserted. The output data is stable 54 | // on write requests. 55 | 56 | module tc_sram #( 57 | parameter int unsigned NumWords = 32'd1024, // Number of Words in data array 58 | parameter int unsigned DataWidth = 32'd128, // Data signal width 59 | parameter int unsigned ByteWidth = 32'd8, // Width of a data byte 60 | parameter int unsigned NumPorts = 32'd2, // Number of read and write ports 61 | parameter int unsigned Latency = 32'd1, // Latency when the read data is available 62 | parameter SimInit = "none", // Simulation initialization 63 | parameter bit PrintSimCfg = 1'b0, // Print configuration 64 | parameter ImplKey = "none", // Reference to specific implementation 65 | // DEPENDENT PARAMETERS, DO NOT OVERWRITE! 66 | parameter int unsigned AddrWidth = (NumWords > 32'd1) ? $clog2(NumWords) : 32'd1, 67 | parameter int unsigned BeWidth = (DataWidth + ByteWidth - 32'd1) / ByteWidth, // ceil_div 68 | parameter type addr_t = logic [AddrWidth-1:0], 69 | parameter type data_t = logic [DataWidth-1:0], 70 | parameter type be_t = logic [BeWidth-1:0] 71 | ) ( 72 | input logic clk_i, // Clock 73 | input logic rst_ni, // Asynchronous reset active low 74 | // input ports 75 | input logic [NumPorts-1:0] req_i, // request 76 | input logic [NumPorts-1:0] we_i, // write enable 77 | input addr_t [NumPorts-1:0] addr_i, // request address 78 | input data_t [NumPorts-1:0] wdata_i, // write data 79 | input be_t [NumPorts-1:0] be_i, // write byte enable 80 | // output ports 81 | output data_t [NumPorts-1:0] rdata_o // read data 82 | ); 83 | 84 | // memory array 85 | data_t sram [NumWords-1:0]; 86 | // hold the read address when no read access is made 87 | addr_t [NumPorts-1:0] r_addr_q; 88 | 89 | // SRAM simulation initialization 90 | data_t init_val[NumWords-1:0]; 91 | initial begin : proc_sram_init 92 | for (int unsigned i = 0; i < NumWords; i++) begin 93 | case (SimInit) 94 | "zeros": init_val[i] = {DataWidth{1'b0}}; 95 | "ones": init_val[i] = {DataWidth{1'b1}}; 96 | "random": init_val[i] = {DataWidth{$urandom()}}; 97 | default: init_val[i] = {DataWidth{1'bx}}; 98 | endcase 99 | end 100 | end 101 | 102 | // set the read output if requested 103 | // The read data at the highest array index is set combinational. 104 | // It gets then delayed for a number of cycles until it gets available at the output at 105 | // array index 0. 106 | 107 | // read data output assignment 108 | data_t [NumPorts-1:0][Latency-1:0] rdata_q, rdata_d; 109 | if (Latency == 32'd0) begin : gen_no_read_lat 110 | for (genvar i = 0; i < NumPorts; i++) begin : gen_port 111 | assign rdata_o[i] = (req_i[i] && !we_i[i]) ? sram[addr_i[i]] : sram[r_addr_q[i]]; 112 | end 113 | end else begin : gen_read_lat 114 | 115 | always_comb begin 116 | for (int unsigned i = 0; i < NumPorts; i++) begin 117 | rdata_o[i] = rdata_q[i][0]; 118 | for (int unsigned j = 0; j < (Latency-1); j++) begin 119 | rdata_d[i][j] = rdata_q[i][j+1]; 120 | end 121 | rdata_d[i][Latency-1] = (req_i[i] && !we_i[i]) ? sram[addr_i[i]] : sram[r_addr_q[i]]; 122 | end 123 | end 124 | end 125 | 126 | // In case simulation initialization is disabled (SimInit == 'none'), don't assign to the sram 127 | // content at all. This improves simulation performance in tools like verilator 128 | if (SimInit == "none") begin 129 | // write memory array without initialization 130 | always_ff @(posedge clk_i or negedge rst_ni) begin 131 | if (!rst_ni) begin 132 | for (int i = 0; i < NumPorts; i++) begin 133 | r_addr_q[i] <= {AddrWidth{1'b0}}; 134 | end 135 | end else begin 136 | // read value latch happens before new data is written to the sram 137 | for (int unsigned i = 0; i < NumPorts; i++) begin 138 | if (Latency != 0) begin 139 | for (int unsigned j = 0; j < Latency; j++) begin 140 | rdata_q[i][j] <= rdata_d[i][j]; 141 | end 142 | end 143 | end 144 | // there is a request for the SRAM, latch the required register 145 | for (int unsigned i = 0; i < NumPorts; i++) begin 146 | if (req_i[i]) begin 147 | if (we_i[i]) begin 148 | // update value when write is set at clock 149 | for (int unsigned j = 0; j < BeWidth; j++) begin 150 | if (be_i[i][j]) begin 151 | sram[addr_i[i]][j*ByteWidth+:ByteWidth] <= wdata_i[i][j*ByteWidth+:ByteWidth]; 152 | end 153 | end 154 | end else begin 155 | // otherwise update read address for subsequent non request cycles 156 | r_addr_q[i] <= addr_i[i]; 157 | end 158 | end // if req_i 159 | end // for ports 160 | end // if !rst_ni 161 | end 162 | end else begin 163 | // write memory array 164 | always_ff @(posedge clk_i or negedge rst_ni) begin 165 | if (!rst_ni) begin 166 | sram <= init_val; 167 | for (int i = 0; i < NumPorts; i++) begin 168 | r_addr_q[i] <= {AddrWidth{1'b0}}; 169 | // initialize the read output register for each port 170 | if (Latency != 32'd0) begin 171 | for (int unsigned j = 0; j < Latency; j++) begin 172 | rdata_q[i][j] <= init_val[{AddrWidth{1'b0}}]; 173 | end 174 | end 175 | end 176 | end else begin 177 | // read value latch happens before new data is written to the sram 178 | for (int unsigned i = 0; i < NumPorts; i++) begin 179 | if (Latency != 0) begin 180 | for (int unsigned j = 0; j < Latency; j++) begin 181 | rdata_q[i][j] <= rdata_d[i][j]; 182 | end 183 | end 184 | end 185 | // there is a request for the SRAM, latch the required register 186 | for (int unsigned i = 0; i < NumPorts; i++) begin 187 | if (req_i[i]) begin 188 | if (we_i[i]) begin 189 | // update value when write is set at clock 190 | for (int unsigned j = 0; j < BeWidth; j++) begin 191 | if (be_i[i][j]) begin 192 | sram[addr_i[i]][j*ByteWidth+:ByteWidth] <= wdata_i[i][j*ByteWidth+:ByteWidth]; 193 | end 194 | end 195 | end else begin 196 | // otherwise update read address for subsequent non request cycles 197 | r_addr_q[i] <= addr_i[i]; 198 | end 199 | end // if req_i 200 | end // for ports 201 | end // if !rst_ni 202 | end 203 | end 204 | 205 | // Validate parameters. 206 | // pragma translate_off 207 | `ifndef VERILATOR 208 | `ifndef TARGET_SYNTHESIS 209 | initial begin: p_assertions 210 | assert ($bits(addr_i) == NumPorts * AddrWidth) else $fatal(1, "AddrWidth problem on `addr_i`"); 211 | assert ($bits(wdata_i) == NumPorts * DataWidth) else $fatal(1, "DataWidth problem on `wdata_i`"); 212 | assert ($bits(be_i) == NumPorts * BeWidth) else $fatal(1, "BeWidth problem on `be_i`" ); 213 | assert ($bits(rdata_o) == NumPorts * DataWidth) else $fatal(1, "DataWidth problem on `rdata_o`"); 214 | assert (NumWords >= 32'd1) else $fatal(1, "NumWords has to be > 0"); 215 | assert (DataWidth >= 32'd1) else $fatal(1, "DataWidth has to be > 0"); 216 | assert (ByteWidth >= 32'd1) else $fatal(1, "ByteWidth has to be > 0"); 217 | assert (NumPorts >= 32'd1) else $fatal(1, "The number of ports must be at least 1!"); 218 | end 219 | initial begin: p_sim_hello 220 | if (PrintSimCfg) begin 221 | $display("#################################################################################"); 222 | $display("tc_sram functional instantiated with the configuration:" ); 223 | $display("Instance: %m" ); 224 | $display("Number of ports (dec): %0d", NumPorts ); 225 | $display("Number of words (dec): %0d", NumWords ); 226 | $display("Address width (dec): %0d", AddrWidth ); 227 | $display("Data width (dec): %0d", DataWidth ); 228 | $display("Byte width (dec): %0d", ByteWidth ); 229 | $display("Byte enable width (dec): %0d", BeWidth ); 230 | $display("Latency Cycles (dec): %0d", Latency ); 231 | $display("Simulation init (str): %0s", SimInit ); 232 | $display("#################################################################################"); 233 | end 234 | end 235 | for (genvar i = 0; i < NumPorts; i++) begin : gen_assertions 236 | assert property ( @(posedge clk_i) disable iff (!rst_ni) 237 | (req_i[i] |-> (addr_i[i] < NumWords))) else 238 | $warning("Request address %0h not mapped, port %0d, expect random write or read behavior!", 239 | addr_i[i], i); 240 | end 241 | 242 | `endif 243 | `endif 244 | // pragma translate_on 245 | endmodule 246 | -------------------------------------------------------------------------------- /src/rtl/tc_sram_impl.sv: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | // Author: Paul Scheffler 12 | 13 | // Description: A wrapper for `tc_sram` with generic ports for implementation-related IOs, which 14 | // may be used to connect dynamic control and status signals. In this model, `impl_i` 15 | // is ignored and `impl_o` is statically driven. If you need such IOs in your 16 | // implementation, you may substitute this module directly instead of `tc_sram`. 17 | // 18 | // Additional parameters: 19 | // - impl_in_t: Implementation-related inputs, such as pseudo-static macro configuration inputs. 20 | // - impl_out_t: Implementation-related outputs. This model only supports driving static values. 21 | // - ImplOutSim: Static output assumed by `impl_out_t` in behavioral simulation. 22 | // 23 | // Additional ports: 24 | // - `impl_i`: Implementation-related inputs 25 | // - `impl_o`: Implementation-related outputs 26 | 27 | module tc_sram_impl #( 28 | parameter int unsigned NumWords = 32'd1024, // Number of Words in data array 29 | parameter int unsigned DataWidth = 32'd128, // Data signal width 30 | parameter int unsigned ByteWidth = 32'd8, // Width of a data byte 31 | parameter int unsigned NumPorts = 32'd2, // Number of read and write ports 32 | parameter int unsigned Latency = 32'd1, // Latency when the read data is available 33 | parameter SimInit = "none", // Simulation initialization 34 | parameter bit PrintSimCfg = 1'b0, // Print configuration 35 | parameter ImplKey = "none", // Reference to specific implementation 36 | parameter type impl_in_t = logic, // Type for implementation inputs 37 | parameter type impl_out_t = logic, // Type for implementation outputs 38 | parameter impl_out_t ImplOutSim = 'X, // Implementation output in simulation 39 | // DEPENDENT PARAMETERS, DO NOT OVERWRITE! 40 | parameter int unsigned AddrWidth = (NumWords > 32'd1) ? $clog2(NumWords) : 32'd1, 41 | parameter int unsigned BeWidth = (DataWidth + ByteWidth - 32'd1) / ByteWidth, // ceil_div 42 | parameter type addr_t = logic [AddrWidth-1:0], 43 | parameter type data_t = logic [DataWidth-1:0], 44 | parameter type be_t = logic [BeWidth-1:0] 45 | ) ( 46 | input logic clk_i, // Clock 47 | input logic rst_ni, // Asynchronous reset active low 48 | // implementation-related IO 49 | input impl_in_t impl_i, 50 | output impl_out_t impl_o, 51 | // input ports 52 | input logic [NumPorts-1:0] req_i, // request 53 | input logic [NumPorts-1:0] we_i, // write enable 54 | input addr_t [NumPorts-1:0] addr_i, // request address 55 | input data_t [NumPorts-1:0] wdata_i, // write data 56 | input be_t [NumPorts-1:0] be_i, // write byte enable 57 | // output ports 58 | output data_t [NumPorts-1:0] rdata_o // read data 59 | ); 60 | 61 | // We drive a static value for `impl_o` in behavioral simulation. 62 | assign impl_o = ImplOutSim; 63 | 64 | tc_sram #( 65 | .NumWords ( NumWords ), 66 | .DataWidth ( DataWidth ), 67 | .ByteWidth ( ByteWidth ), 68 | .NumPorts ( NumPorts ), 69 | .Latency ( Latency ), 70 | .SimInit ( SimInit ), 71 | .PrintSimCfg ( PrintSimCfg ), 72 | .ImplKey ( ImplKey ) 73 | ) i_tc_sram ( 74 | .clk_i, 75 | .rst_ni, 76 | .req_i, 77 | .we_i, 78 | .addr_i, 79 | .wdata_i, 80 | .be_i, 81 | .rdata_o 82 | ); 83 | 84 | endmodule 85 | -------------------------------------------------------------------------------- /src/tc_pwr.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2018 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | 11 | // Description: This file contains power-related cells 12 | // Mainly shifters at the moment. 13 | 14 | 15 | module tc_pwr_level_shifter_in ( 16 | input logic in_i, 17 | output logic out_o 18 | ); 19 | 20 | assign out_o = in_i; 21 | 22 | endmodule 23 | 24 | module tc_pwr_level_shifter_in_clamp_lo ( 25 | input logic in_i, 26 | output logic out_o, 27 | input logic clamp_i 28 | ); 29 | 30 | assign out_o = clamp_i ? 1'b0 : in_i; 31 | 32 | endmodule 33 | 34 | module tc_pwr_level_shifter_in_clamp_hi ( 35 | input logic in_i, 36 | output logic out_o, 37 | input logic clamp_i 38 | ); 39 | 40 | assign out_o = clamp_i ? 1'b1 : in_i; 41 | 42 | endmodule 43 | 44 | module tc_pwr_level_shifter_out ( 45 | input logic in_i, 46 | output logic out_o 47 | ); 48 | 49 | assign out_o = in_i; 50 | 51 | endmodule 52 | 53 | module tc_pwr_level_shifter_out_clamp_lo ( 54 | input logic in_i, 55 | output logic out_o, 56 | input logic clamp_i 57 | ); 58 | 59 | assign out_o = clamp_i ? 1'b0 : in_i; 60 | 61 | endmodule 62 | 63 | module tc_pwr_level_shifter_out_clamp_hi ( 64 | input logic in_i, 65 | output logic out_o, 66 | input logic clamp_i 67 | ); 68 | 69 | assign out_o = clamp_i ? 1'b1 : in_i; 70 | 71 | endmodule 72 | 73 | module tc_pwr_power_gating ( 74 | input logic sleep_i, 75 | output logic sleepout_o 76 | ); 77 | 78 | assign sleepout_o = sleep_i; 79 | 80 | endmodule 81 | 82 | module tc_pwr_isolation_lo ( 83 | input logic data_i, 84 | input logic ena_i, 85 | output logic data_o 86 | ); 87 | 88 | assign data_o = ena_i ? data_i : 1'b0; 89 | 90 | endmodule 91 | 92 | module tc_pwr_isolation_hi ( 93 | input logic data_i, 94 | input logic ena_i, 95 | output logic data_o 96 | ); 97 | 98 | assign data_o = ena_i ? data_i : 1'b1; 99 | 100 | endmodule 101 | -------------------------------------------------------------------------------- /src_files.yml: -------------------------------------------------------------------------------- 1 | tech_cells_rtl: 2 | flags: [ 3 | skip_synthesis, 4 | ] 5 | files: [ 6 | src/deprecated/cluster_clk_cells.sv, 7 | src/deprecated/cluster_pwr_cells.sv, 8 | src/deprecated/generic_memory.sv, 9 | src/deprecated/generic_rom.sv, 10 | src/deprecated/pad_functional.sv, 11 | src/deprecated/pulp_buffer.sv, 12 | src/deprecated/pulp_clk_cells.sv, 13 | src/deprecated/pulp_pwr_cells.sv, 14 | src/rtl/tc_clk.sv, 15 | src/rtl/tc_sram.sv, 16 | src/tc_pwr.sv, 17 | ] 18 | 19 | tech_cells_rtl_synth: 20 | files: [ 21 | src/deprecated/pulp_clock_gating_async.sv, 22 | ] 23 | 24 | tech_cells_fpga: 25 | targets: [ 26 | xilinx, 27 | ] 28 | files: [ 29 | src/deprecated/cluster_clk_cells_xilinx.sv, 30 | src/deprecated/cluster_pwr_cells.sv, 31 | src/deprecated/pulp_clk_cells_xilinx.sv, 32 | src/deprecated/pulp_pwr_cells.sv, 33 | src/deprecated/pulp_buffer.sv, 34 | src/fpga/tc_clk_xilinx.sv, 35 | src/fpga/tc_sram_xilinx.sv, 36 | src/tc_pwr.sv, 37 | ] 38 | -------------------------------------------------------------------------------- /test/tb_tc_sram.sv: -------------------------------------------------------------------------------- 1 | // Copyright 2020 ETH Zurich and University of Bologna. 2 | // Copyright and related rights are licensed under the Solderpad Hardware 3 | // License, Version 0.51 (the "License"); you may not use this file except in 4 | // compliance with the License. You may obtain a copy of the License at 5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law 6 | // or agreed to in writing, software, hardware and materials distributed under 7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the 9 | // specific language governing permissions and limitations under the License. 10 | // 11 | // Author: Wolfgang Roenninger , ETH Zurich 12 | // Description: Testbench for the functional `*_sram` modules 13 | 14 | module tb_tc_sram #( 15 | parameter int unsigned NumPorts = 32'd2, 16 | parameter int unsigned Latency = 32'd1, 17 | parameter int unsigned NumWords = 32'd1024, 18 | parameter int unsigned DataWidth = 32'd64, 19 | parameter int unsigned ByteWidth = 32'd8, 20 | parameter int unsigned NoReq = 32'd200000, 21 | parameter string SimInit = "zeros", 22 | parameter time CyclTime = 10ns, 23 | parameter time ApplTime = 2ns, 24 | parameter time TestTime = 8ns 25 | ); 26 | 27 | //----------------------------------- 28 | // Clock generator 29 | //----------------------------------- 30 | logic clk, rst_n; 31 | clk_rst_gen #( 32 | .ClkPeriod ( CyclTime ), 33 | .RstClkCycles( 5 ) 34 | ) i_clk_gen ( 35 | .clk_o ( clk ), 36 | .rst_no ( rst_n ) 37 | ); 38 | 39 | logic [NumPorts-1:0] done; 40 | 41 | localparam int unsigned AddrWidth = (NumWords > 32'd1) ? $clog2(NumWords) : 32'd1; 42 | localparam int unsigned BeWidth = (DataWidth + ByteWidth - 32'd1) / ByteWidth; 43 | 44 | typedef logic [AddrWidth-1:0] addr_t; 45 | typedef logic [DataWidth-1:0] data_t; 46 | typedef logic [BeWidth-1:0] be_t; 47 | 48 | // signal declarations for each sram 49 | logic [NumPorts-1:0] req, we; 50 | addr_t [NumPorts-1:0] addr; 51 | data_t [NumPorts-1:0] wdata, rdata; 52 | be_t [NumPorts-1:0] be; 53 | 54 | // golden model 55 | data_t memory [NumWords-1:0]; 56 | longint unsigned failed_test; 57 | 58 | // This process drives the requests on the port with random data. 59 | for (genvar i = 0; i < NumPorts; i++) begin : gen_stimuli 60 | initial begin : proc_drive_port 61 | automatic logic stim_write; 62 | automatic addr_t stim_addr; 63 | automatic data_t stim_data; 64 | automatic be_t stim_be; 65 | 66 | done[i] <= 1'b0; 67 | req[i] <= 1'b0; 68 | we[i] <= 1'b0; 69 | addr[i] <= addr_t'(0); 70 | wdata[i] <= data_t'(0); 71 | be[i] <= be_t'(0); 72 | 73 | @(posedge rst_n); 74 | repeat (10) @(posedge clk); 75 | 76 | for (int unsigned j = 0; j < NoReq; j++) begin 77 | stim_write = bit'($urandom()); 78 | for (int unsigned k = 0; k < AddrWidth; k++) begin 79 | stim_addr[k] = bit'($urandom()); 80 | end 81 | // this statement makes sure that only valid addresses are in a request 82 | while (stim_addr >= NumWords) begin 83 | for (int unsigned k = 0; k < AddrWidth; k++) begin 84 | stim_addr[k] = bit'($urandom()); 85 | end 86 | end 87 | for (int unsigned k = 0; k < DataWidth; k++) begin 88 | stim_data[k] = bit'($urandom()); 89 | end 90 | for (int unsigned k = 0; k < BeWidth; k++) begin 91 | stim_be[k] = bit'($urandom()); 92 | end 93 | 94 | req[i] <= #ApplTime 1'b1; 95 | we[i] <= #ApplTime stim_write; 96 | addr[i] <= #ApplTime stim_addr; 97 | wdata[i] <= #ApplTime stim_data; 98 | be[i] <= #ApplTime stim_be; 99 | @(posedge clk); 100 | req[i] <= #ApplTime 1'b0; 101 | we[i] <= #ApplTime 1'b0; 102 | addr[i] <= #ApplTime addr_t'(0); 103 | wdata[i] <= #ApplTime data_t'(0); 104 | be[i] <= #ApplTime be_t'(0); 105 | 106 | repeat ($urandom_range(0,5)) @(posedge clk); 107 | end 108 | done[i] <= 1'b1; 109 | end 110 | end 111 | 112 | // This process controls the golden model 113 | // - The memory array is initialized according to the parameter 114 | // - Data is written exactly at the clock edge, if there is a write request on a port. 115 | // - At `TestTime` a process is launched on read requests which lives for `Latency` cycles. 116 | // This process asserts the expected read output at `TestTime` in the respective cycle. 117 | initial begin: proc_golden_model 118 | failed_test = 0; 119 | for (int unsigned i = 0; i < NumWords; i++) begin 120 | for (int unsigned j = 0; j < DataWidth; j++) begin 121 | case (SimInit) 122 | "zeros": memory[i][j] = 1'b0; 123 | "ones": memory[i][j] = 1'b1; 124 | default: memory[i][j] = 1'bx; 125 | endcase 126 | end 127 | end 128 | 129 | @(posedge rst_n); 130 | 131 | forever begin 132 | @(posedge clk); 133 | // writes get latched at clock in golden model array 134 | for (int unsigned i = 0; i < NumPorts; i++) begin 135 | if (req[i] && we[i]) begin 136 | for (int unsigned j = 0; j < DataWidth; j++) begin 137 | if (be[i][j/ByteWidth]) begin 138 | memory[addr[i]][j] = wdata[i][j]; 139 | end 140 | end 141 | end 142 | end 143 | 144 | // read test process is launched at `TestTime` 145 | #TestTime; 146 | fork 147 | for (int unsigned i = 0; i < NumPorts; i++) begin 148 | check_read(i, addr[i]); 149 | end 150 | join_none 151 | end 152 | end 153 | 154 | // Read test process. This task lives for a number of cycles determined by `Latency`. 155 | task automatic check_read(input int unsigned port, input addr_t read_addr); 156 | // only continue if there is a read request at this port 157 | if (req[port] && !we[port]) begin 158 | data_t exp_data = memory[read_addr]; 159 | 160 | if (Latency > 0) begin 161 | repeat (Latency) @(posedge clk); 162 | #TestTime; 163 | end 164 | 165 | for (int unsigned i = 0; i < DataWidth; i++) begin 166 | if (!$isunknown(exp_data[i])) begin 167 | assert(exp_data[i] === rdata[port][i]) else begin 168 | $warning("Port: %0d unexpected bit[%0h], Addr: %0h expected: %0h, measured: %0h", 169 | port, i, read_addr, exp_data[i], rdata[port][i]); 170 | failed_test++; 171 | end 172 | end 173 | end 174 | end 175 | endtask : check_read 176 | 177 | // Stop the simulation at the end. 178 | initial begin : proc_stop 179 | @(posedge rst_n); 180 | wait (&done); 181 | repeat (10) @(posedge clk); 182 | $info("Simulation done, errors: %0d", failed_test); 183 | $stop(); 184 | end 185 | 186 | tc_sram #( 187 | .NumWords ( NumWords ), // Number of Words in data array 188 | .DataWidth ( DataWidth ), // Data signal width 189 | .ByteWidth ( ByteWidth ), // Width of a data byte 190 | .NumPorts ( NumPorts ), // Number of read and write ports 191 | .Latency ( Latency ), // Latency when the read data is available 192 | .SimInit ( SimInit ), // Simulation initialization 193 | .PrintSimCfg ( 1'b1 ) // Print configuration 194 | ) i_tc_sram_dut ( 195 | .clk_i ( clk ), // Clock 196 | .rst_ni ( rst_n ), // Asynchronous reset active low 197 | .req_i ( req ), // request 198 | .we_i ( we ), // write enable 199 | .addr_i ( addr ), // request address 200 | .wdata_i ( wdata ), // write data 201 | .be_i ( be ), // write byte enable 202 | .rdata_o ( rdata ) // read data 203 | ); 204 | endmodule 205 | --------------------------------------------------------------------------------