├── .editorconfig ├── .gitignore ├── Bender.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── VERSION ├── fusesoc.core ├── src ├── clk_rst_gen.sv ├── rand_id_queue.sv ├── rand_stream_mst.sv ├── rand_stream_slv.sv ├── rand_synch_driver.sv ├── rand_synch_holdable_driver.sv ├── rand_verif_pkg.sv ├── signal_highlighter.sv ├── sim_timeout.sv └── stream_watchdog.sv ├── test └── tb_clk_rst_gen.sv └── util ├── compile_vsim └── run_vsim /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig (http://editorconfig.org/) 2 | root = true 3 | 4 | # Default Settings 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | indent_size = 4 9 | indent_style = space 10 | insert_final_newline = true 11 | tab_width = 4 12 | trim_trailing_whitespace = true 13 | max_line_length = 100 14 | 15 | [Makefile] 16 | indent_style = tab 17 | 18 | [{*.sv,*.svh}] 19 | indent_size = 2 20 | 21 | [*.yml] 22 | indent_size = 2 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /Bender.lock 2 | /build/ 3 | -------------------------------------------------------------------------------- /Bender.yml: -------------------------------------------------------------------------------- 1 | package: 2 | name: common_verification 3 | authors: 4 | - "Andreas Kurth " 5 | 6 | sources: 7 | # Files in this package are meant for simulation only. 8 | # Verilator does not support features commonly used in simulation (eg: rand conditioning) 9 | - target: any(simulation, verilator) 10 | files: 11 | - src/clk_rst_gen.sv 12 | - src/sim_timeout.sv 13 | - src/stream_watchdog.sv 14 | - src/signal_highlighter.sv 15 | 16 | - target: simulation 17 | files: 18 | # Source files grouped in levels. Files in level 0 have no dependencies on files in this 19 | # package. Files in level 1 only depend on files in level 0, files in level 2 on files in 20 | # levels 1 and 0, etc. Files within a level are ordered alphabetically. 21 | # Level 0 22 | - src/rand_id_queue.sv 23 | - src/rand_stream_mst.sv 24 | - src/rand_synch_holdable_driver.sv 25 | - src/rand_verif_pkg.sv 26 | # Level 1 27 | - src/rand_synch_driver.sv 28 | # Level 2 29 | - src/rand_stream_slv.sv 30 | 31 | - target: test 32 | files: 33 | - test/tb_clk_rst_gen.sv 34 | -------------------------------------------------------------------------------- /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 | 8 | ## Unreleased 9 | 10 | ### Added 11 | 12 | ### Changed 13 | 14 | ### Fixed 15 | 16 | ## 0.2.5 - 2025-01-07 17 | 18 | ### Fixed 19 | - FuseSoC core file updated to 0.2.5. 20 | 21 | ## 0.2.4 - 2024-12-04 22 | 23 | ### Fixed 24 | - Minor Verilator fixes ([#8](https://github.com/pulp-platform/common_verification/pull/8), [#9](https://github.com/pulp-platform/common_verification/pull/9)) 25 | 26 | ## 0.2.3 - 2022-09-14 27 | 28 | ### Added 29 | - Add support for fusesoc ([#4](https://github.com/pulp-platform/common_verification/pull/4)) 30 | 31 | ### Fixed 32 | - `rand_id_queue`: Rename `empty` method to `is_empty` for XSIM compatibility. ([#4](https://github.com/pulp-platform/common_verification/pull/4)) 33 | 34 | ## 0.2.2 - 2022-08-29 35 | 36 | ### Added 37 | - Add signal highlighter 38 | - Add stream watchdog 39 | 40 | ## 0.2.1 - 2021-12-02 41 | 42 | ### Fixed 43 | - `clk_rst_gen`: 44 | - Fix generation of odd clock periods. 45 | - Fix number of reset cycles. 46 | 47 | 48 | ## v0.2.0 - 2019-08-20 49 | 50 | ### Added 51 | - Add module to timeout simulations. 52 | 53 | ### Changed 54 | - Remove `timeunit` and `timeprecision` declarations from all modules. Multiple simulators do not 55 | properly implement precedence of these declarations (IEEE 1800-2012, 3.14.2.3), so we now avoid 56 | the declarations in favor of a simulation-wide precision declaration. 57 | - Rename parameters to comply with style guidelines. 58 | 59 | 60 | ## v0.1.2 - 2019-08-20 61 | 62 | ### Fixed 63 | - rand_synch_driver: Fix instantiation of `rand_synch_holdable_driver`. 64 | - rand_stream_slv: Fix instantiation of `rand_sync_driver`. 65 | 66 | 67 | ## v0.1.1 - 2019-02-26 68 | 69 | ### Fixed 70 | - Move all files into the `simulation` target. This precludes synthesis of files in this package 71 | when this package is included as dependency. 72 | 73 | 74 | ## v0.1.0 - 2019-02-25 75 | 76 | ### Added 77 | - Add standalone clock and reset generator. 78 | - Add randomizing synchronous driver and holdable driver. 79 | - Add randomizing stream master and slave. 80 | - Add ID queue with randomizing output. 81 | - Add `rand_verif_pkg` with task to wait for a random number (within interval) of clock cycles. 82 | -------------------------------------------------------------------------------- /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 | # Common Verification 2 | 3 | This repository contains commonly used SystemVerilog modules and classes for verification. This 4 | code is generally not synthesizable. 5 | 6 | ## Contents 7 | 8 | ### Basic Modules 9 | 10 | | Name | Description | Status | 11 | |----------------------|----------------------------------------------------------------------------|--------| 12 | | `clk_rst_gen` | Standalone clock and reset generator | active | 13 | | `sim_timeout` | Timeout for simulations | active | 14 | | `stream_watchdog` | Terminates a simulation after a number of cycles of inactivity of a stream | active | 15 | 16 | ### Generic Functions and Tasks 17 | 18 | `rand_verif_pkg` defines the following functions and tasks: 19 | 20 | | Name | Description | Status | 21 | |---------------------|-------------------------------------------------------------|--------| 22 | | `rand_wait` | Wait for a random number (within interval) of clock cycles | active | 23 | 24 | ### Simple Synchronous Drivers 25 | 26 | | Name | Description | Status | 27 | |-------------------------------|---------------------------------------------------|--------| 28 | | `rand_synch_driver` | Randomizing synchronous driver | active | 29 | | `rand_synch_holdable_driver` | Randomizing synchronous driver that can be halted | active | 30 | 31 | ### Stream (Ready/Valid) Masters and Slaves 32 | 33 | | Name | Description | Status | 34 | |-------------------|---------------------------------------|--------| 35 | | `rand_stream_mst` | Randomizing stream master | active | 36 | | `rand_stream_slv` | Randomizing stream slave | active | 37 | 38 | ### Data Structures 39 | 40 | | Name | Description | Status | 41 | |-------------------|---------------------------------------|--------| 42 | | `rand_id_queue` | ID queue with randomizing output | active | 43 | 44 | ### Simulation Helpers 45 | | Name | Description | Status | 46 | |----------------------|-------------------------------------------------------|--------| 47 | | `signal_highlighter` | Highlights a signal in the wave for better visibility | active | 48 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.2.5 2 | -------------------------------------------------------------------------------- /fusesoc.core: -------------------------------------------------------------------------------- 1 | CAPI=2: 2 | name: pulp-platform.org::common_verification:0.2.5 3 | 4 | filesets: 5 | # Files in this package are meant for simulation only. 6 | simulation: 7 | files: 8 | # Source files grouped in levels. Files in level 0 have no dependencies on files in this 9 | # package. Files in level 1 only depend on files in level 0, files in level 2 on files in 10 | # levels 1 and 0, etc. Files within a level are ordered alphabetically. 11 | # Level 0 12 | - src/clk_rst_gen.sv 13 | - src/rand_id_queue.sv 14 | - src/rand_stream_mst.sv 15 | - src/rand_synch_holdable_driver.sv 16 | - src/rand_verif_pkg.sv 17 | - src/signal_highlighter.sv 18 | - src/sim_timeout.sv 19 | - src/stream_watchdog.sv 20 | # Level 1 21 | - src/rand_synch_driver.sv 22 | # Level 2 23 | - src/rand_stream_slv.sv 24 | file_type : systemVerilogSource 25 | 26 | bench: 27 | files: 28 | - test/tb_clk_rst_gen.sv 29 | file_type : systemVerilogSource 30 | targets: 31 | default: 32 | filesets : [simulation] 33 | -------------------------------------------------------------------------------- /src/clk_rst_gen.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 | // Clock and Reset Generator 12 | module clk_rst_gen #( 13 | parameter time ClkPeriod = 0ps, // minimum: 2ps 14 | parameter int unsigned RstClkCycles = 0 15 | ) ( 16 | output logic clk_o, 17 | output logic rst_no 18 | ); 19 | 20 | logic clk; 21 | 22 | // Clock Generation 23 | initial begin 24 | clk = 1'b0; 25 | end 26 | always begin 27 | // Emit rising clock edge. 28 | clk = 1'b1; 29 | // Wait for at most half the clock period before emitting falling clock edge. Due to integer 30 | // division, this is not always exactly half the clock period but as close as we can get. 31 | #(ClkPeriod / 2); 32 | // Emit falling clock edge. 33 | clk = 1'b0; 34 | // Wait for remainder of clock period before continuing with next cycle. 35 | #((ClkPeriod + 1) / 2); 36 | end 37 | assign clk_o = clk; 38 | 39 | // Reset Generation 40 | initial begin 41 | static int unsigned rst_cnt = 0; 42 | rst_no = 1'b0; 43 | #(ClkPeriod / 2); // Start counting clock cycles on first complete cycle. 44 | while (rst_cnt < RstClkCycles) begin 45 | @(posedge clk); 46 | rst_cnt++; 47 | end 48 | rst_no = 1'b1; 49 | end 50 | 51 | // Validate parameters. 52 | `ifndef VERILATOR 53 | initial begin: validate_params 54 | assert (ClkPeriod >= 2ps) 55 | else $fatal(1, "The clock period must be at least 2ps!"); 56 | // Reason: Gets divided by two, and some simulators do not support non-integer time steps, so 57 | // if the time unit is 1ps, this would fail. 58 | assert (RstClkCycles > 0) 59 | else $fatal(1, "The number of clock cycles in reset must be greater than 0!"); 60 | end 61 | `endif 62 | 63 | endmodule 64 | -------------------------------------------------------------------------------- /src/rand_id_queue.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 | // Wrapper package so class can be used after `import rand_id_queue_pkg::*;`. 12 | package rand_id_queue_pkg; 13 | 14 | // ID Queue with Randomizing Output 15 | class rand_id_queue #( 16 | type data_t = logic, 17 | int unsigned ID_WIDTH = 0 18 | ); 19 | 20 | localparam int unsigned N_IDS = 2**ID_WIDTH; 21 | localparam type id_t = logic[ID_WIDTH-1:0]; 22 | 23 | data_t queues[N_IDS-1:0][$]; 24 | int unsigned size; 25 | 26 | function new(); 27 | size = 0; 28 | endfunction 29 | 30 | // Push a data element to the queue with the given ID. 31 | function void push(id_t id, data_t data); 32 | queues[id].push_back(data); 33 | size++; 34 | endfunction 35 | 36 | // Determine if the ID queue is empty. 37 | function bit empty(); 38 | return (size == 0); 39 | endfunction 40 | // vivado xsim doesn't support empty method name. previous is kept for backward compatibility 41 | function bit is_empty(); 42 | return (size == 0); 43 | endfunction 44 | 45 | // Pick a non-empty queue at random and return the front element. Not defined if the ID queue is 46 | // empty. 47 | function data_t peek(); 48 | return queues[rand_id()][0]; 49 | endfunction 50 | 51 | // Pick a non-empty queue at random, remove the front element from that queue, and return that 52 | // element. Not defined if the ID queue is empty. 53 | function data_t pop(); 54 | return pop_id(rand_id()); 55 | endfunction 56 | 57 | // Remove the front element of the queue with the given ID and return that element. Not defined 58 | // if the queue with the given ID is empty. 59 | function data_t pop_id(id_t id); 60 | size--; 61 | return queues[id].pop_front(); 62 | endfunction 63 | 64 | // Pick a non-empty queue at random and return the ID of that queue. Not defined if the ID queue 65 | // is empty. 66 | function id_t rand_id(); 67 | if (!is_empty()) begin 68 | id_t id; 69 | do begin 70 | void'(std::randomize(id)); 71 | end while (queues[id].size() == 0); 72 | return id; 73 | end else begin 74 | return 'x; 75 | end 76 | endfunction 77 | 78 | // Set the front element of the queue with the given ID. Not defined if the queue with the given 79 | // ID is empty; instead use `push()` to insert a new element. 80 | function void set(id_t id, data_t data); 81 | queues[id][0] = data; 82 | endfunction 83 | 84 | // Get the front element of the queue with the given ID. Not defined if the queue with the given 85 | // ID is empty. 86 | function data_t get(id_t id); 87 | return queues[id][0]; 88 | endfunction 89 | 90 | endclass 91 | 92 | endpackage 93 | -------------------------------------------------------------------------------- /src/rand_stream_mst.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 | // Randomizing Stream (Ready/Valid) Master 12 | module rand_stream_mst #( 13 | parameter type data_t = logic, 14 | // Minimum number of clock cycles to wait between applying two consecutive values. 15 | parameter int MinWaitCycles = -1, 16 | // Maximum number of clock cycles to wait between applying two consecutive values. 17 | parameter int MaxWaitCycles = -1, 18 | // Application delay: time delay before output changes after an active clock edge. 19 | parameter time ApplDelay = 0ps, 20 | // Acquisition delay: time delay before ready input is read after an active clock edge. 21 | parameter time AcqDelay = 0ps 22 | ) ( 23 | input logic clk_i, 24 | input logic rst_ni, 25 | 26 | output data_t data_o, 27 | output logic valid_o, 28 | input logic ready_i 29 | ); 30 | 31 | int unsigned rand_wait_cycles; 32 | 33 | function static void randomize_wait_cycles(); 34 | int unsigned rand_success; 35 | rand_success = std::randomize(rand_wait_cycles) with { 36 | rand_wait_cycles >= MinWaitCycles; 37 | rand_wait_cycles <= MaxWaitCycles; 38 | }; 39 | assert (rand_success) else $error("Failed to randomize wait cycles!"); 40 | endfunction 41 | 42 | initial begin 43 | data_o = '0; 44 | valid_o = 1'b0; 45 | wait (rst_ni); 46 | // Initially pick a random number of cycles to wait until we offer the first valid data. 47 | randomize_wait_cycles(); 48 | @(posedge clk_i); 49 | forever begin 50 | // Wait for the picked number of clock cycles. 51 | repeat(rand_wait_cycles) begin 52 | @(posedge clk_i); 53 | end 54 | // Delay application of data and valid output. 55 | #(ApplDelay); 56 | // Randomize data output and set valid output. 57 | void'(std::randomize(data_o)); 58 | valid_o = 1'b1; 59 | // Delay acquisition of ready signal. AcqDelay is relative to the clock edge, and we have 60 | // already waited for ApplDelay in this edge, so we need to subtract ApplDelay. 61 | #(AcqDelay-ApplDelay); 62 | // Sample the ready input. While the slave is not ready, wait a clock cycle plus the 63 | // acquisition delay and resample the ready input. 64 | while (!ready_i) begin 65 | @(posedge clk_i); 66 | #(AcqDelay); 67 | end 68 | // The slave is ready to acquire data on the next rising edge, so we pick a new number of 69 | // cycles to wait until we offer the next valid data. 70 | randomize_wait_cycles(); 71 | if (rand_wait_cycles == 0) begin 72 | // If we have to wait 0 cycles, we apply new data directly after next clock edge plus the 73 | // application delay. 74 | @(posedge clk_i); 75 | end else begin 76 | // If we have to wait more than 0 cycles, we unset the valid output and randomize the data 77 | // output after the next clock edge plus the application delay. 78 | @(posedge clk_i); 79 | #(ApplDelay); 80 | valid_o = 1'b0; 81 | void'(std::randomize(data_o)); 82 | end 83 | end 84 | end 85 | 86 | // Validate parameters. 87 | `ifndef VERILATOR 88 | initial begin: validate_params 89 | assert (MinWaitCycles >= 0) 90 | else $fatal("The minimum number of wait cycles must be at least 0!"); 91 | assert (MaxWaitCycles >= 0) 92 | else $fatal("The maximum number of wait cycles must be at least 0!"); 93 | assert (MaxWaitCycles >= MinWaitCycles) 94 | else $fatal("The maximum number of wait cycles must be at least the minimum number of wait cycles!"); 95 | assert (ApplDelay > 0ps) 96 | else $fatal("The application delay must be greater than 0!"); 97 | assert (AcqDelay > 0ps) 98 | else $fatal("The acquisition delay must be greater than 0!"); 99 | assert (AcqDelay > ApplDelay) 100 | else $fatal("The acquisition delay must be greater than the application delay!"); 101 | end 102 | `endif 103 | 104 | endmodule 105 | -------------------------------------------------------------------------------- /src/rand_stream_slv.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 | // Randomizing Stream (Ready/Valid) Slave 12 | module rand_stream_slv #( 13 | parameter type data_t = logic, 14 | // Minimum number of clock cycles to wait between applying two consecutive values. 15 | parameter int MinWaitCycles = -1, 16 | // Maximum number of clock cycles to wait between applying two consecutive values. 17 | parameter int MaxWaitCycles = -1, 18 | // Application delay: time delay before output changes after an active clock edge. 19 | parameter time ApplDelay = 0ps, 20 | // Acquisition delay: time delay before ready input is read after an active clock edge. 21 | parameter time AcqDelay = 0ps, 22 | // Store each inupt beat in an internal queue. 23 | parameter bit Enqueue = 1'b0 24 | ) ( 25 | input logic clk_i, 26 | input logic rst_ni, 27 | 28 | input data_t data_i, 29 | input logic valid_i, 30 | output logic ready_o 31 | ); 32 | 33 | if (Enqueue) begin: gen_queue 34 | data_t queue[$]; 35 | always @(posedge clk_i, negedge rst_ni) begin 36 | if (!rst_ni) begin 37 | queue = {}; 38 | end else begin 39 | #(AcqDelay); 40 | if (valid_i && ready_o) begin 41 | queue.push_back(data_i); 42 | end 43 | end 44 | end 45 | end 46 | 47 | rand_synch_driver #( 48 | .data_t (logic), 49 | .MinWaitCycles (MinWaitCycles), 50 | .MaxWaitCycles (MaxWaitCycles), 51 | .ApplDelay (ApplDelay) 52 | ) i_ready_driver ( 53 | .clk_i (clk_i), 54 | .rst_ni (rst_ni), 55 | .data_o (ready_o) 56 | ); 57 | 58 | `ifndef VERILATOR 59 | initial begin: validate_params 60 | assert (AcqDelay > 0ps) 61 | else $fatal("The acquisition delay must be greater than 0!"); 62 | assert (AcqDelay > ApplDelay) 63 | else $fatal("The acquisition delay must be greater than the application delay!"); 64 | end 65 | `endif 66 | 67 | endmodule 68 | -------------------------------------------------------------------------------- /src/rand_synch_driver.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 | // Randomizing Synchronous Driver 12 | module rand_synch_driver #( 13 | parameter type data_t = logic, 14 | // Minimum number of clock cycles to wait between applying two consecutive values. 15 | parameter int MinWaitCycles = -1, 16 | // Maximum number of clock cycles to wait between applying two consecutive values. 17 | parameter int MaxWaitCycles = -1, 18 | // Application delay: time delay before output changes after an active clock edge. 19 | parameter time ApplDelay = 0ps 20 | ) ( 21 | input logic clk_i, 22 | input logic rst_ni, 23 | 24 | output data_t data_o 25 | ); 26 | 27 | rand_synch_holdable_driver #( 28 | .data_t (data_t), 29 | .MinWaitCycles (MinWaitCycles), 30 | .MaxWaitCycles (MaxWaitCycles), 31 | .ApplDelay (ApplDelay) 32 | ) i_ready_driver ( 33 | .clk_i (clk_i), 34 | .rst_ni (rst_ni), 35 | .hold_i (1'b0), 36 | .data_o (data_o) 37 | ); 38 | 39 | endmodule 40 | -------------------------------------------------------------------------------- /src/rand_synch_holdable_driver.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 | // Randomizing Synchronous Holdable Driver 12 | module rand_synch_holdable_driver #( 13 | parameter type data_t = logic, 14 | // Minimum number of clock cycles to wait between applying two consecutive values. 15 | parameter int MinWaitCycles = -1, 16 | // Maximum number of clock cycles to wait between applying two consecutive values. 17 | parameter int MaxWaitCycles = -1, 18 | // Application delay: time delay before output changes after an active clock edge. 19 | parameter time ApplDelay = 0ps 20 | ) ( 21 | input logic clk_i, 22 | input logic rst_ni, 23 | 24 | input logic hold_i, 25 | output data_t data_o 26 | ); 27 | 28 | initial begin 29 | int unsigned rand_delay, rand_success; 30 | data_o = '0; 31 | wait (rst_ni); 32 | @(posedge clk_i); 33 | forever begin 34 | rand_success = std::randomize(rand_delay) with { 35 | rand_delay >= MinWaitCycles; 36 | rand_delay <= MaxWaitCycles; 37 | }; 38 | assert (rand_success) else $error("Failed to randomize wait cycles!"); 39 | repeat(rand_delay) begin 40 | @(posedge clk_i); 41 | end 42 | #(ApplDelay); 43 | if (!hold_i) begin 44 | void'(std::randomize(data_o)); 45 | end 46 | end 47 | end 48 | 49 | // Validate parameters. 50 | `ifndef VERILATOR 51 | initial begin: validate_params 52 | assert (MinWaitCycles >= 0) 53 | else $fatal("The minimum number of wait cycles must be at least 0!"); 54 | assert (MaxWaitCycles >= 0) 55 | else $fatal("The maximum number of wait cycles must be at least 0!"); 56 | assert (MaxWaitCycles >= MinWaitCycles) 57 | else $fatal("The maximum number of wait cycles must be at least the minimum number of wait cycles!"); 58 | assert (ApplDelay > 0ps) 59 | else $fatal("The application delay must be greater than 0!"); 60 | end 61 | `endif 62 | 63 | endmodule 64 | -------------------------------------------------------------------------------- /src/rand_verif_pkg.sv: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 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 | // Package with functions and tasks commonly used in constrained randomized verification 13 | package rand_verif_pkg; 14 | 15 | // Pick a random number from the interval [min, max] and wait for that number of clock cyles. 16 | task automatic rand_wait(input int unsigned min, max, ref logic clk); 17 | int unsigned rand_success, cycles; 18 | rand_success = std::randomize(cycles) with { 19 | cycles >= min; 20 | cycles <= max; 21 | }; 22 | assert (rand_success) else $error("Failed to randomize wait cycles!"); 23 | repeat (cycles) @(posedge clk); 24 | endtask 25 | 26 | endpackage 27 | -------------------------------------------------------------------------------- /src/signal_highlighter.sv: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 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 | // Author: Thomas Benz 13 | 14 | /// Highlights a signal in the waveform for easier viewing 15 | module signal_highlighter #( 16 | parameter type T = logic 17 | )( 18 | input logic ready_i, 19 | input logic valid_i, 20 | input T data_i 21 | ); 22 | 23 | T in_wave; 24 | 25 | always_comb begin 26 | in_wave = 'Z; 27 | if (ready_i & valid_i) begin 28 | in_wave = data_i; 29 | end 30 | end 31 | 32 | endmodule 33 | -------------------------------------------------------------------------------- /src/sim_timeout.sv: -------------------------------------------------------------------------------- 1 | module sim_timeout #( 2 | parameter longint unsigned Cycles = 0, 3 | parameter bit ResetRestartsTimeout = 1'b0 4 | ) ( 5 | input logic clk_i, 6 | input logic rst_ni 7 | ); 8 | 9 | longint unsigned cycles = 0; 10 | always_ff @(posedge clk_i, negedge rst_ni) begin 11 | if (ResetRestartsTimeout && !rst_ni) begin 12 | cycles <= 0; 13 | end else begin 14 | cycles <= cycles + 1; 15 | end 16 | if (cycles > Cycles) begin 17 | $fatal(1, "Timeout exceeded!"); 18 | end 19 | end 20 | 21 | `ifndef VERILATOR 22 | initial begin: validate_params 23 | assert (Cycles > 0) 24 | else $fatal("The number of timeout cycles must be greater than 0!"); 25 | end 26 | `endif 27 | 28 | endmodule 29 | -------------------------------------------------------------------------------- /src/stream_watchdog.sv: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 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 | // Author: Thomas Benz 13 | 14 | /// Terminates simulation in case a ready-valid handshake is inactive or deadlocked for NumCycles 15 | module stream_watchdog #( 16 | parameter int unsigned NumCycles 17 | )( 18 | input logic clk_i, 19 | input logic rst_ni, 20 | input logic valid_i, 21 | input logic ready_i 22 | ); 23 | 24 | int unsigned cnt; 25 | 26 | initial begin : wd 27 | // initialize counter 28 | cnt = NumCycles; 29 | 30 | // count down when inactive, restore on activity 31 | while (cnt > 0) begin 32 | if (valid_i && ready_i || !rst_ni) begin 33 | cnt = NumCycles; 34 | end else begin 35 | cnt--; 36 | end 37 | @(posedge clk_i); 38 | end 39 | 40 | // tripped watchdog 41 | $fatal(1, "Tripped Watchdog (%m) at %dns, Inactivity for %d cycles", $time(), NumCycles); 42 | end 43 | 44 | endmodule 45 | -------------------------------------------------------------------------------- /test/tb_clk_rst_gen.sv: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 ETH Zurich, University of Bologna 2 | // Licensed under the Solderpad Hardware License, Version 0.51. 3 | // SPDX-License-Identifier: SHL-0.51 4 | // 5 | // Authors: 6 | // - Andreas Kurth 7 | 8 | module tb_clk_rst_gen #( 9 | parameter time TbClkPeriod = 10ns, 10 | parameter int unsigned TbClkCycles = 12, 11 | parameter int unsigned TbRstClkCycles = 7, 12 | parameter bit TbDebugPrint = 1'b0 13 | ) (); 14 | 15 | logic clk, 16 | rst_n; 17 | 18 | // DUT 19 | clk_rst_gen #( 20 | .ClkPeriod (TbClkPeriod), 21 | .RstClkCycles (TbRstClkCycles) 22 | ) i_dut ( 23 | .clk_o (clk), 24 | .rst_no (rst_n) 25 | ); 26 | 27 | int unsigned clk_cnt, 28 | rst_cnt; 29 | initial begin 30 | clk_cnt = 0; 31 | rst_cnt = 0; 32 | while (1) begin 33 | #(TbClkPeriod - 1); // Advance to end of clock cycle. 34 | if (rst_n == 1'b0) begin 35 | rst_cnt++; 36 | if (TbDebugPrint) $info("Reset clock cycle complete"); 37 | end 38 | @(posedge clk); 39 | clk_cnt++; 40 | if (TbDebugPrint) $info("Clock cycle complete"); 41 | end 42 | end 43 | 44 | initial begin 45 | static time TB_RUN_TIME = TbClkCycles * TbClkPeriod + (TbClkPeriod / 2); 46 | assert (TbRstClkCycles < TbClkCycles) 47 | else $fatal(1, "The number of clock cycles must be larger than the number of reset cycles!"); 48 | #TB_RUN_TIME; 49 | assert (clk_cnt == TbClkCycles) 50 | else $error("Counted %0d instead of %0d clock cycles!", clk_cnt, TbClkCycles); 51 | assert (rst_cnt == TbRstClkCycles) 52 | else $error("Counted %0d instead of %0d reset clock cycles!", rst_cnt, TbRstClkCycles); 53 | $finish(); 54 | end 55 | 56 | endmodule 57 | -------------------------------------------------------------------------------- /util/compile_vsim: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright (c) 2021 ETH Zurich, University of Bologna 4 | # Licensed under the Apache License, Version 2.0. 5 | # SPDX-License-Identifier: Apache-2.0 6 | # 7 | # Authors: 8 | # - Andreas Kurth 9 | 10 | set -e 11 | 12 | [ ! -z "$VSIM" ] || VSIM=vsim 13 | 14 | bender script vsim -t test \ 15 | --vlog-arg="-svinputport=compat" \ 16 | --vlog-arg="-override_timescale 1ns/1ps" \ 17 | --vlog-arg="-suppress 2583" \ 18 | > compile.tcl 19 | echo 'return 0' >> compile.tcl 20 | 21 | $VSIM -c -do 'exit -code [source compile.tcl]' 22 | -------------------------------------------------------------------------------- /util/run_vsim: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright (c) 2021 ETH Zurich, University of Bologna 4 | # Licensed under the Apache License, Version 2.0. 5 | # SPDX-License-Identifier: Apache-2.0 6 | # 7 | # Authors: 8 | # - Andreas Kurth 9 | 10 | set -e 11 | readonly ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) 12 | 13 | [ ! -z "$VSIM" ] || VSIM=vsim 14 | 15 | call_vsim() { 16 | echo "run -all" | $VSIM "$@" | tee vsim.log 2>&1 17 | grep "Errors: 0," vsim.log 18 | } 19 | 20 | exec_test() { 21 | if [ ! -e "$ROOT/test/tb_$1.sv" ]; then 22 | echo "Testbench for '$1' not found!" 23 | exit 1 24 | fi 25 | case "$1" in 26 | clk_rst_gen) 27 | for CLK_PERIOD_NS in 4 7; do 28 | for RST_CLK_CYCLES in 5 8; do 29 | call_vsim tb_$1 -t 1ns \ 30 | -gTbClkPeriod="${CLK_PERIOD_NS}ns" -gTbRstClkCycles="$RST_CLK_CYCLES" 31 | done 32 | done 33 | ;; 34 | *) 35 | call_vsim tb_$1 -t 1ns -coverage -voptargs="+acc +cover=bcesfx" 36 | ;; 37 | esac 38 | } 39 | 40 | if [ "$#" -eq 0 ]; then 41 | tests=() 42 | while IFS= read -r -d $'\0'; do 43 | tb_name="$(basename -s .sv $REPLY)" 44 | dut_name="${tb_name#tb_}" 45 | tests+=("$dut_name") 46 | done < <(find "$ROOT/test" -name 'tb_*.sv' -a \( ! -name '*_pkg.sv' \) -print0) 47 | else 48 | tests=("$@") 49 | fi 50 | 51 | for t in "${tests[@]}"; do 52 | exec_test $t 53 | done 54 | --------------------------------------------------------------------------------