├── .github └── workflows │ └── actions.yml ├── LICENSE ├── README.md ├── hdl ├── FIFO1.v ├── FIFO2.v ├── ff.v ├── ifc_or.v └── or_gate.v ├── slides ├── Introduction.md ├── README.md ├── Theory.md ├── crv.md ├── index.md ├── testplan.md └── verification.md └── tests ├── Makefile ├── crv.py ├── ifc_coverage.py ├── ifc_test.py ├── or_test.py └── wrappers ├── ifc_test.v └── or_test.v /.github/workflows/actions.yml: -------------------------------------------------------------------------------- 1 | name: learning-cocotb 2 | run-name: ${{ github.actor }} is learning Cocotb 3 | on: [push] 4 | jobs: 5 | verify: 6 | runs-on: ubuntu-latest 7 | timeout-minutes: 3 8 | steps: 9 | - uses: actions/checkout@v3 10 | - run: sudo apt install -y --no-install-recommends iverilog 11 | - run: pip3 install cocotb cocotb-bus 12 | - run: make -C tests 13 | - uses: actions/upload-artifact@v3 14 | with: 15 | name: waveform 16 | path: tests/*.vcd 17 | - name: Publish Test Report 18 | uses: mikepenz/action-junit-report@v3 19 | if: always() # always run even if the previous step fails 20 | with: 21 | report_paths: '**/tests/results.xml' 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2022, learn-cocotb 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | * This repo contains the code used in the [cocotb learning journey video series](https://www.youtube.com/playlist?list=PL3Z0z1uoFF-CElbEpGoRa5ph-TJUzuKnm). 2 | * The source code for the slides are in the slides folder. 3 | * The code is tagged with the corresponding video name. 4 | * The assignments discussed in the video's are available at 5 | * [XOR Assignment](https://classroom.github.com/classrooms/115061083-learn-cocotb-classroom/assignments/xor-verification) 6 | * [Interfaces](https://classroom.github.com/classrooms/115061083-learn-cocotb-classroom/assignments/xor-verification) 7 | 8 | -------------------------------------------------------------------------------- /hdl/FIFO1.v: -------------------------------------------------------------------------------- 1 | 2 | `ifdef BSV_ASSIGNMENT_DELAY 3 | `else 4 | `define BSV_ASSIGNMENT_DELAY 5 | `endif 6 | 7 | `ifdef BSV_POSITIVE_RESET 8 | `define BSV_RESET_VALUE 1'b1 9 | `define BSV_RESET_EDGE posedge 10 | `else 11 | `define BSV_RESET_VALUE 1'b0 12 | `define BSV_RESET_EDGE negedge 13 | `endif 14 | 15 | `ifdef BSV_ASYNC_RESET 16 | `define BSV_ARESET_EDGE_META or `BSV_RESET_EDGE RST 17 | `else 18 | `define BSV_ARESET_EDGE_META 19 | `endif 20 | 21 | `ifdef BSV_RESET_FIFO_HEAD 22 | `define BSV_ARESET_EDGE_HEAD `BSV_ARESET_EDGE_META 23 | `else 24 | `define BSV_ARESET_EDGE_HEAD 25 | `endif 26 | 27 | // Depth 1 FIFO 28 | module FIFO1(CLK, 29 | RST, 30 | D_IN, 31 | ENQ, 32 | FULL_N, 33 | D_OUT, 34 | DEQ, 35 | EMPTY_N, 36 | CLR 37 | ); 38 | 39 | parameter width = 1; 40 | parameter guarded = 1'b1; 41 | input CLK; 42 | input RST; 43 | input [width - 1 : 0] D_IN; 44 | input ENQ; 45 | input DEQ; 46 | input CLR ; 47 | 48 | output FULL_N; 49 | output [width - 1 : 0] D_OUT; 50 | output EMPTY_N; 51 | 52 | reg [width - 1 : 0] D_OUT; 53 | reg empty_reg ; 54 | 55 | 56 | assign EMPTY_N = empty_reg ; 57 | 58 | 59 | `ifdef BSV_NO_INITIAL_BLOCKS 60 | `else // not BSV_NO_INITIAL_BLOCKS 61 | // synopsys translate_off 62 | initial 63 | begin 64 | D_OUT = {((width + 1)/2) {2'b10}} ; 65 | empty_reg = 1'b0 ; 66 | end // initial begin 67 | // synopsys translate_on 68 | `endif // BSV_NO_INITIAL_BLOCKS 69 | 70 | 71 | assign FULL_N = !empty_reg; 72 | 73 | always@(posedge CLK `BSV_ARESET_EDGE_META) 74 | begin 75 | if (RST == `BSV_RESET_VALUE) 76 | begin 77 | empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b0; 78 | end // if (RST == `BSV_RESET_VALUE) 79 | else 80 | begin 81 | if (CLR) 82 | begin 83 | empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b0; 84 | end // if (CLR) 85 | else if (ENQ) 86 | begin 87 | empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b1; 88 | end // if (ENQ) 89 | else if (DEQ) 90 | begin 91 | empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b0; 92 | end // if (DEQ) 93 | end // else: !if(RST == `BSV_RESET_VALUE) 94 | end // always@ (posedge CLK or `BSV_RESET_EDGE RST) 95 | 96 | always@(posedge CLK `BSV_ARESET_EDGE_HEAD) 97 | begin 98 | `ifdef BSV_RESET_FIFO_HEAD 99 | if (RST == `BSV_RESET_VALUE) 100 | begin 101 | D_OUT <= `BSV_ASSIGNMENT_DELAY {width {1'b0}} ; 102 | end 103 | else 104 | `endif 105 | begin 106 | if (ENQ) 107 | D_OUT <= `BSV_ASSIGNMENT_DELAY D_IN; 108 | end // else: !if(RST == `BSV_RESET_VALUE) 109 | end // always@ (posedge CLK or `BSV_RESET_EDGE RST) 110 | 111 | // synopsys translate_off 112 | always@(posedge CLK) 113 | begin: error_checks 114 | reg deqerror, enqerror ; 115 | 116 | deqerror = 0; 117 | enqerror = 0; 118 | if (RST == ! `BSV_RESET_VALUE) 119 | begin 120 | if ( ! empty_reg && DEQ ) 121 | begin 122 | deqerror = 1 ; 123 | $display( "Warning: FIFO1: %m -- Dequeuing from empty fifo" ) ; 124 | end 125 | if ( ! FULL_N && ENQ && (!DEQ || guarded) ) 126 | begin 127 | enqerror = 1 ; 128 | $display( "Warning: FIFO1: %m -- Enqueuing to a full fifo" ) ; 129 | end 130 | end // if (RST == ! `BSV_RESET_VALUE) 131 | end 132 | // synopsys translate_on 133 | 134 | endmodule 135 | 136 | -------------------------------------------------------------------------------- /hdl/FIFO2.v: -------------------------------------------------------------------------------- 1 | 2 | `ifdef BSV_ASSIGNMENT_DELAY 3 | `else 4 | `define BSV_ASSIGNMENT_DELAY 5 | `endif 6 | 7 | `ifdef BSV_POSITIVE_RESET 8 | `define BSV_RESET_VALUE 1'b1 9 | `define BSV_RESET_EDGE posedge 10 | `else 11 | `define BSV_RESET_VALUE 1'b0 12 | `define BSV_RESET_EDGE negedge 13 | `endif 14 | 15 | `ifdef BSV_ASYNC_RESET 16 | `define BSV_ARESET_EDGE_META or `BSV_RESET_EDGE RST 17 | `else 18 | `define BSV_ARESET_EDGE_META 19 | `endif 20 | 21 | `ifdef BSV_RESET_FIFO_HEAD 22 | `define BSV_ARESET_EDGE_HEAD `BSV_ARESET_EDGE_META 23 | `else 24 | `define BSV_ARESET_EDGE_HEAD 25 | `endif 26 | 27 | // Depth 2 FIFO 28 | module FIFO2(CLK, 29 | RST, 30 | D_IN, 31 | ENQ, 32 | FULL_N, 33 | D_OUT, 34 | DEQ, 35 | EMPTY_N, 36 | CLR); 37 | 38 | parameter width = 1; 39 | parameter guarded = 1'b1; 40 | 41 | input CLK ; 42 | input RST ; 43 | input [width - 1 : 0] D_IN; 44 | input ENQ; 45 | input DEQ; 46 | input CLR ; 47 | 48 | output FULL_N; 49 | output EMPTY_N; 50 | output [width - 1 : 0] D_OUT; 51 | 52 | reg full_reg; 53 | reg empty_reg; 54 | reg [width - 1 : 0] data0_reg; 55 | reg [width - 1 : 0] data1_reg; 56 | 57 | assign FULL_N = full_reg ; 58 | assign EMPTY_N = empty_reg ; 59 | assign D_OUT = data0_reg ; 60 | 61 | 62 | // Optimize the loading logic since state encoding is not power of 2! 63 | wire d0di = (ENQ && ! empty_reg ) || ( ENQ && DEQ && full_reg ) ; 64 | wire d0d1 = DEQ && ! full_reg ; 65 | wire d0h = ((! DEQ) && (! ENQ )) || (!DEQ && empty_reg ) || ( ! ENQ &&full_reg) ; 66 | wire d1di = ENQ & empty_reg ; 67 | 68 | `ifdef BSV_NO_INITIAL_BLOCKS 69 | `else // not BSV_NO_INITIAL_BLOCKS 70 | // synopsys translate_off 71 | initial 72 | begin 73 | data0_reg = {((width + 1)/2) {2'b10}} ; 74 | data1_reg = {((width + 1)/2) {2'b10}} ; 75 | empty_reg = 1'b0; 76 | full_reg = 1'b1; 77 | end // initial begin 78 | // synopsys translate_on 79 | `endif // BSV_NO_INITIAL_BLOCKS 80 | 81 | always@(posedge CLK `BSV_ARESET_EDGE_META) 82 | begin 83 | if (RST == `BSV_RESET_VALUE) 84 | begin 85 | empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b0; 86 | full_reg <= `BSV_ASSIGNMENT_DELAY 1'b1; 87 | end // if (RST == `BSV_RESET_VALUE) 88 | else 89 | begin 90 | if (CLR) 91 | begin 92 | empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b0; 93 | full_reg <= `BSV_ASSIGNMENT_DELAY 1'b1; 94 | end // if (CLR) 95 | else if ( ENQ && ! DEQ ) // just enq 96 | begin 97 | empty_reg <= `BSV_ASSIGNMENT_DELAY 1'b1; 98 | full_reg <= `BSV_ASSIGNMENT_DELAY ! empty_reg ; 99 | end 100 | else if ( DEQ && ! ENQ ) 101 | begin 102 | full_reg <= `BSV_ASSIGNMENT_DELAY 1'b1; 103 | empty_reg <= `BSV_ASSIGNMENT_DELAY ! full_reg; 104 | end // if ( DEQ && ! ENQ ) 105 | end // else: !if(RST == `BSV_RESET_VALUE) 106 | 107 | end // always@ (posedge CLK or `BSV_RESET_EDGE RST) 108 | 109 | 110 | always@(posedge CLK `BSV_ARESET_EDGE_HEAD) 111 | begin 112 | `ifdef BSV_RESET_FIFO_HEAD 113 | if (RST == `BSV_RESET_VALUE) 114 | begin 115 | data0_reg <= `BSV_ASSIGNMENT_DELAY {width {1'b0}} ; 116 | data1_reg <= `BSV_ASSIGNMENT_DELAY {width {1'b0}} ; 117 | end 118 | else 119 | `endif 120 | begin 121 | data0_reg <= `BSV_ASSIGNMENT_DELAY 122 | {width{d0di}} & D_IN | {width{d0d1}} & data1_reg | {width{d0h}} & data0_reg ; 123 | data1_reg <= `BSV_ASSIGNMENT_DELAY 124 | d1di ? D_IN : data1_reg ; 125 | end // else: !if(RST == `BSV_RESET_VALUE) 126 | end // always@ (posedge CLK or `BSV_RESET_EDGE RST) 127 | 128 | 129 | 130 | // synopsys translate_off 131 | always@(posedge CLK) 132 | begin: error_checks 133 | reg deqerror, enqerror ; 134 | 135 | deqerror = 0; 136 | enqerror = 0; 137 | if (RST == ! `BSV_RESET_VALUE) 138 | begin 139 | if ( ! empty_reg && DEQ ) 140 | begin 141 | deqerror = 1; 142 | $display( "Warning: FIFO2: %m -- Dequeuing from empty fifo" ) ; 143 | end 144 | if ( ! full_reg && ENQ && (!DEQ || guarded) ) 145 | begin 146 | enqerror = 1; 147 | $display( "Warning: FIFO2: %m -- Enqueuing to a full fifo" ) ; 148 | end 149 | end 150 | end // always@ (posedge CLK) 151 | // synopsys translate_on 152 | 153 | endmodule 154 | -------------------------------------------------------------------------------- /hdl/ff.v: -------------------------------------------------------------------------------- 1 | module ff( 2 | input wire CLK, 3 | input wire RST_N, 4 | input wire [7:0] D_IN, 5 | input wire EN, 6 | output wire RDY, 7 | output wire [7:0] D_OUT 8 | ); 9 | 10 | reg [7:0] dff; 11 | assign D_OUT=dff; 12 | assign RDY=1; 13 | always @(posedge CLK or negedge RST_N)begin 14 | if (! RST_N) 15 | dff<=0; 16 | else if(EN)dff<=D_IN; 17 | end 18 | endmodule 19 | 20 | 21 | -------------------------------------------------------------------------------- /hdl/ifc_or.v: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by Bluespec Compiler (build d05342e3) 3 | // 4 | // On Thu Oct 6 11:04:51 IST 2022 5 | // 6 | // 7 | // Ports: 8 | // Name I/O size props 9 | // a_rdy O 1 reg 10 | // b_rdy O 1 reg 11 | // y_data O 1 reg 12 | // y_rdy O 1 reg 13 | // CLK I 1 clock 14 | // RST_N I 1 reset 15 | // a_data I 1 reg 16 | // b_data I 1 reg 17 | // a_en I 1 18 | // b_en I 1 19 | // y_en I 1 20 | // 21 | // No combinational paths from inputs to outputs 22 | // 23 | // 24 | 25 | `ifdef BSV_ASSIGNMENT_DELAY 26 | `else 27 | `define BSV_ASSIGNMENT_DELAY 28 | `endif 29 | 30 | `ifdef BSV_POSITIVE_RESET 31 | `define BSV_RESET_VALUE 1'b1 32 | `define BSV_RESET_EDGE posedge 33 | `else 34 | `define BSV_RESET_VALUE 1'b0 35 | `define BSV_RESET_EDGE negedge 36 | `endif 37 | 38 | module ifc_or(CLK, 39 | RST_N, 40 | 41 | a_data, 42 | a_en, 43 | a_rdy, 44 | 45 | b_data, 46 | b_en, 47 | b_rdy, 48 | 49 | y_en, 50 | y_data, 51 | y_rdy); 52 | input CLK; 53 | input RST_N; 54 | 55 | // action method a 56 | input a_data; 57 | input a_en; 58 | output a_rdy; 59 | 60 | // action method b 61 | input b_data; 62 | input b_en; 63 | output b_rdy; 64 | 65 | // actionvalue method y 66 | input y_en; 67 | output y_data; 68 | output y_rdy; 69 | 70 | // signals for module outputs 71 | wire a_rdy, b_rdy, y_data, y_rdy; 72 | 73 | // ports of submodule a_ff 74 | wire a_ff$CLR, 75 | a_ff$DEQ, 76 | a_ff$D_IN, 77 | a_ff$D_OUT, 78 | a_ff$EMPTY_N, 79 | a_ff$ENQ, 80 | a_ff$FULL_N; 81 | 82 | // ports of submodule b_ff 83 | wire b_ff$CLR, 84 | b_ff$DEQ, 85 | b_ff$D_IN, 86 | b_ff$D_OUT, 87 | b_ff$EMPTY_N, 88 | b_ff$ENQ, 89 | b_ff$FULL_N; 90 | 91 | // ports of submodule y_ff 92 | wire y_ff$CLR, 93 | y_ff$DEQ, 94 | y_ff$D_IN, 95 | y_ff$D_OUT, 96 | y_ff$EMPTY_N, 97 | y_ff$ENQ, 98 | y_ff$FULL_N; 99 | 100 | // action method a 101 | assign a_rdy = a_ff$FULL_N ; 102 | 103 | // action method b 104 | assign b_rdy = b_ff$FULL_N ; 105 | 106 | // actionvalue method y 107 | assign y_data = y_ff$D_OUT ; 108 | assign y_rdy = y_ff$EMPTY_N ; 109 | 110 | // submodule a_ff 111 | FIFO2 #(.width(32'd1), .guarded(1'd1)) a_ff(.RST(RST_N), 112 | .CLK(CLK), 113 | .D_IN(a_ff$D_IN), 114 | .ENQ(a_ff$ENQ), 115 | .DEQ(a_ff$DEQ), 116 | .CLR(a_ff$CLR), 117 | .D_OUT(a_ff$D_OUT), 118 | .FULL_N(a_ff$FULL_N), 119 | .EMPTY_N(a_ff$EMPTY_N)); 120 | 121 | // submodule b_ff 122 | FIFO1 #(.width(32'd1), .guarded(1'd1)) b_ff(.RST(RST_N), 123 | .CLK(CLK), 124 | .D_IN(b_ff$D_IN), 125 | .ENQ(b_ff$ENQ), 126 | .DEQ(b_ff$DEQ), 127 | .CLR(b_ff$CLR), 128 | .D_OUT(b_ff$D_OUT), 129 | .FULL_N(b_ff$FULL_N), 130 | .EMPTY_N(b_ff$EMPTY_N)); 131 | 132 | // submodule y_ff 133 | FIFO2 #(.width(32'd1), .guarded(1'd1)) y_ff(.RST(RST_N), 134 | .CLK(CLK), 135 | .D_IN(y_ff$D_IN), 136 | .ENQ(y_ff$ENQ), 137 | .DEQ(y_ff$DEQ), 138 | .CLR(y_ff$CLR), 139 | .D_OUT(y_ff$D_OUT), 140 | .FULL_N(y_ff$FULL_N), 141 | .EMPTY_N(y_ff$EMPTY_N)); 142 | 143 | // submodule a_ff 144 | assign a_ff$D_IN = a_data ; 145 | assign a_ff$ENQ = a_en ; 146 | assign a_ff$DEQ = y_ff$FULL_N && a_ff$EMPTY_N && b_ff$EMPTY_N ; 147 | assign a_ff$CLR = 1'b0 ; 148 | 149 | // submodule b_ff 150 | assign b_ff$D_IN = b_data ; 151 | assign b_ff$ENQ = b_en ; 152 | assign b_ff$DEQ = y_ff$FULL_N && a_ff$EMPTY_N && b_ff$EMPTY_N ; 153 | assign b_ff$CLR = 1'b0 ; 154 | 155 | // submodule y_ff 156 | assign y_ff$D_IN = a_ff$D_OUT || b_ff$D_OUT ; 157 | assign y_ff$ENQ = y_ff$FULL_N && a_ff$EMPTY_N && b_ff$EMPTY_N ; 158 | assign y_ff$DEQ = y_en ; 159 | assign y_ff$CLR = 1'b0 ; 160 | endmodule // dut 161 | 162 | -------------------------------------------------------------------------------- /hdl/or_gate.v: -------------------------------------------------------------------------------- 1 | module or_gate( 2 | input wire a, 3 | input wire b, 4 | output wire y 5 | ); 6 | assign y=a|b; 7 | endmodule 8 | -------------------------------------------------------------------------------- /slides/Introduction.md: -------------------------------------------------------------------------------- 1 | * What is cocotb. 2 | * Where to get it. 3 | * How to install it. 4 | * Github Actions. 5 | * Assignments 6 | * A typical DUT 7 | * Resources. 8 | 9 | -------------------------------------------------------------------------------- /slides/README.md: -------------------------------------------------------------------------------- 1 | % Cocotb Learning Journey 2 | % Vijayvithal Jahagirdar 3 | % October 5 2022 4 | 5 | # What is cocotb 6 | 7 | * cocotb is a COroutine based COsimulation TestBench environment for verifying VHDL and SystemVerilog RTL using Python. 8 | * cocotb is completely free, open source (under the BSD License) and hosted on GitHub. 9 | 10 | Translation: Cocotb is a Python based verification framework for simulating RTL written using Verilog/VHDL or SV. 11 | 12 | # Learning Journey 13 | 14 | * Hello world. OR Gate. 15 | * Interfaces 16 | * Randomization 17 | * Drivers 18 | * Monitors 19 | * Scoreboards 20 | * Coverage 21 | * Functional coverage 22 | * Bins and cross coverage 23 | * CRV 24 | * BFM's: AXI, APB, Wishbone, Avalon, PCIe, Ethernet, UART, SPI, I2C... 25 | 26 | # Getting started 27 | 28 | * https://docs.cocotb.org/en/stable/ 29 | * [Github Classroom](https://classroom.github.com/classrooms/115061083-learn-cocotb-classroom) 30 | 31 | # Example "or Gate" 32 | 33 | A 2 input OR Gate is represented by the truth table 34 | 35 | | a | b | y | 36 | | -- | -- | -- | 37 | | 0 | 0 | 0 | 38 | | 0 | 1 | 1 | 39 | | 1 | 0 | 1 | 40 | | 1 | 1 | 1 | 41 | 42 | Where a and b are inputs to the gate and y is the output. 43 | 44 | # Assignment: "XOR gate verification" 45 | 46 | * [XOR gate verification](https://classroom.github.com/a/D3N4nEj7) 47 | 48 | # Interface 49 | * Data transfer takes place from Data Producer to Data Consumer. 50 | * Producers take $t_p$ cycles to produce a unit of data 51 | * Consumers can accept data every $t_c$ cycles 52 | * In most cases, Producers need to hold data until consumer can consume it or consumers need to wait for data from Producers. 53 | * There are various signalling scheme to ensure that data transfer takes place iff producer has data and consumer can accept the data. 54 | 55 | # Interfaces: Simple RDY/EN protocol specification. 56 | 57 | * Producers assert RDY when they have data to offer and keep it asserted until EN is asserted 58 | * Consumers assert RDY when they can consume data and keep it asserted until EN is asserted 59 | * EN is asserted when both Producer.RDY and COnsumer.RDY are asserted. 60 | 61 | # Delta delay and timing model 62 | [https://github.com/cocotb/cocotb/wiki/Timing-Model](https://github.com/cocotb/cocotb/wiki/Timing-Model) 63 | 64 | # Protocol Verification 65 | 66 | Based on the protocol description we have the following truth table 67 | 68 | | Data | En | Rdy | Description | 69 | | -- | -- | -- | -- | 70 | | dont care | 0 | 0 | Idle | 71 | | valid data | 0 | 1 | Ready | 72 | | valid data | 1 | 1 | Transaction | 73 | 74 | * The case where En is 1 and Rdy is 0 cannot occur. 75 | * Once Rdy goes high data cannot change until transaction completes. En goes high. 76 | * We need to verify all state transition 77 | 78 | # State transition verification 79 | 80 | | Previous State | Current State | 81 | | --- | --- | 82 | | Idle | Idle | 83 | | Idle | Ready | 84 | | Idle | Transaction | 85 | | Ready | Idle | 86 | | Ready | Ready | 87 | | Ready | Transaction | 88 | | Transaction | Idle | 89 | | Transaction | Ready | 90 | | Transaction | Transaction | 91 | 92 | # Cross Verification 93 | 94 | | A State | B State | 95 | | --- | --- | 96 | | Idle | Idle | 97 | | Idle | Ready | 98 | | Idle | Transaction | 99 | | Ready | Idle | 100 | | Ready | Ready | 101 | | Ready | Transaction | 102 | | Transaction | Idle | 103 | | Transaction | Ready | 104 | | Transaction | Transaction | 105 | 106 | # Assignment FIFO interface verification 107 | 108 | FIFO interface has a similar protocol to the EN/RDY protocol. 109 | 110 | * Data source signals are 111 | * not_empty, dout, dequeue 112 | * Data sink signals are 113 | * not_full, din, enqueue 114 | 115 | A transaction takes place when: 116 | 117 | * Source is not empty and 118 | * Sink is not full, 119 | 120 | The corresponding sink.enqueue and source.dequeue signals are asserted when the transfer takes place. 121 | 122 | # Backup Slides 123 | 124 | # Development and verification with Cocotb is fast 125 | 126 | While the actual simulation speed might be slower than a simulation on a commercial simulation with native support for SV+UVM, Overall verification with cocotb is fast because of the following factors. 127 | 128 | * Fast development 129 | * In my experience we can get a basic cocotb based test env up within hours. 130 | * Fast regression. 131 | * Commercial simulator licenses are expensive, regressions parallism will be limited by available licenses. 132 | * With cocotb + Icarus We can fire all out testcases at the same time resulting in lesser overall regression time. 133 | * Agile workflow 134 | * With commercial simulator, the number of regressions that can be fired by a team/week is restricted due to cost factor. Typically developers have to wait for the weekly regression to get feedback on their checkins. 135 | * With cocotb + icarus we can fire regression on every checkin resulting in continous and quick feedback loop. 136 | 137 | -------------------------------------------------------------------------------- /slides/Theory.md: -------------------------------------------------------------------------------- 1 | Observeable points. 2 | Controlable points. 3 | Vector space explosion. 4 | Whitebox, Blackbox and Graybox Verification. 5 | Coverage 6 | Randomization. 7 | 8 | -------------------------------------------------------------------------------- /slides/crv.md: -------------------------------------------------------------------------------- 1 | % Constrained Random Vector Generation 2 | % Vijayvithal Jahagirdar 3 | % October 5 2022 4 | 5 | # What are constraints 6 | 7 | * Constraints are limits on what values a given variable can take. 8 | * Mostly defined in protocol/architecture/design specification. 9 | * May also be defined in testplan to hit specific goals. 10 | 11 | # Example Specification: Ethernet packet 12 | 13 | * A packet consists of header and payload. 14 | * Header may or may not contain vlan tag. 15 | * Headers with vlan tag have size of 16 bytes otherwise 14 bytes 16 | * Packets have different ethertype min ethertype is 0x800 max can go upto 0xffff 17 | * Packets with ethertype 0x806 have a size of 64 18 | * packet length is between 64 and 1500 bytes 19 | * ... 20 | 21 | # Generation using plain randomization 22 | 23 | * Will require use of for loops, random.randint etc. 24 | * Difficult to specilize with special test specific constraints from outsize the class. 25 | 26 | # Generation from constraint class 27 | 28 | * Looks similar to specification 29 | -------------------------------------------------------------------------------- /slides/index.md: -------------------------------------------------------------------------------- 1 | [Introduction to this learning journey](README.md) 2 | Introduction.md 3 | [Introduction to cocotb: Linear programming] 4 | [Drivers and scoreboard: Parallel actions] 5 | [Verification theory](verification.md) 6 | [Testplan](testplan.md) 7 | [Coverage] 8 | [Constraints](crv.md) 9 | [Capstone project] 10 | -------------------------------------------------------------------------------- /slides/testplan.md: -------------------------------------------------------------------------------- 1 | % Cocotb Learning Journey: Testplan 2 | % Vijayvithal Jahagirdar 3 | % October 10 2022 4 | 5 | # Components of a verification plan 6 | 7 | * Logistics: machine, regression farm, bugtracking, cloud, software, licenses etc. 8 | * Environment: Unit Level, Subsystem, Chip Top, Back2Back Chips etc. and the verification component(Driver, BFM, Monitor, Generator, Assertions etc.) used for each. 9 | * Testcases: Specify Testcase detail and which Environment it is run on. 10 | * Goals: Code Coverage, Functional Coverage 11 | * Schedule: Resource allocation and assignment 12 | 13 | # Design specification 14 | 15 | * Implements a 2 input OR Gate 16 | * Interface: Simple RDY/EN protocol. 17 | * Producers assert RDY when they have data to offer and keep it asserted until EN is asserted 18 | * Consumers assert RDY when they can consume data and keep it asserted until EN is asserted 19 | * EN is asserted when both Producer.RDY and COnsumer.RDY are asserted. 20 | * Can take 0-20 cycles to produce/consume data. 21 | 22 | 23 | # Verification plan: Logistics: 24 | 25 | * Machine: 1 Laptop. 26 | * Repository: Github (url ....) 27 | * Regression: Github Actions 28 | * Issue tracking: Github Issues (url ....) 29 | * Software : Python >3.6, iverilog, xcelium/vcs/questasim, cocotb, cocotb-bus, cocotb-coverage 30 | * Licenses: Simulator License. 31 | * BFM: None 32 | 33 | # Verification plan: Environment: 34 | 35 | * Unit Level, Subsystem, Chip Top, Back2Back Chips etc. and the verification component(Driver, BFM, Monitor, Generator, Assertions etc.) used for each. 36 | 37 | # Verification plan: Testcases: TC1 38 | 39 | *TC1* 40 | 41 | * *Feature*: OR Gate Datapath test. 42 | * Description: Give inputs to the a and b pins of the DUT and check whether the expected value matches the output of the DUT 43 | * Scenario: Directed Truth table test 44 | * Given: Unit Test Environment 45 | * When: Input is ((0,0),(0,1),(1,0),(1,1)) 46 | * Then: Output is (0, 1, 1, 1) 47 | * Coverage: ... 48 | 49 | # Verification plan: Testcases: TC1 50 | 51 | *TC2* 52 | 53 | * *Feature*: OR Gate Datapath Randomize test. 54 | * Description: Give random inputs to the a and b pins of the DUT and check whether the expected value matches the output of the DUT 55 | * Scenario: Random test 56 | * Given: Unit Test Environment 57 | * When: Input A is 10 samples of random.randint(0,1) 58 | * AND: Input B is 10 samples of random.randint(0,1) 59 | * Then: Output is A | B 60 | * Coverage: ... 61 | 62 | # Verification plan: Goals: Code Coverage, Functional Coverage 63 | 64 | * 100 % Code, Branch and Toggle Coverage 65 | * 100 % Functional coverage 66 | 67 | # Verification plan: Schedule: 68 | 69 | | Resource | Testcase | Environment | Start Date | End Date | Status | 70 | | ---- | -- | -- | -- | -- | -- | 71 | | Vijay | TC1 | Unit_OR | 1 Oct 2022 | 2 Oct 2022 | Done | 72 | | Vijay | TC2 | Unit_OR | ... | ... | Pending | 73 | | Vijay | TC3 | Chip | ... | ... | Pending | 74 | # Verification: datapath 75 | 76 | * Bins 77 | * A: [0,1] 78 | * B: [0,1] 79 | * Y: [0,1] 80 | * Cross 81 | * A x B 82 | 83 | # Verification : protocol 84 | 85 | States: 86 | 87 | | Data | En | Rdy | Description | 88 | | -- | -- | -- | -- | 89 | | dont care | 0 | 0 | Idle | 90 | | valid data | 0 | 1 | Ready | 91 | | valid data | 1 | 1 | Transaction | 92 | 93 | * The case where En is 1 and Rdy is 0 cannot occur. 94 | * Once Rdy goes high data cannot change until transaction completes.i.e En goes high. 95 | * We need to verify all state transition 96 | 97 | 98 | 99 | # Verification : protocol: State transition verification 100 | 101 | | Previous State | Current State | 102 | | --- | --- | 103 | | Idle | Idle | 104 | | Idle | Ready | 105 | | Idle | Transaction | 106 | | ... | ... | 107 | 108 | # Verification: protocol: Bins and crosses 109 | 110 | * Bins 111 | * Current State = [Idle, Ready, Transaction] 112 | * Previous State = [Idle, Ready, Transaction] 113 | * Cross 114 | * Current State x Previous State 115 | 116 | # Verification: Delay 117 | 118 | * Bins 119 | * Delay= [Min, Max, Low, High] # 0, 20, 1-10, 11-19 120 | -------------------------------------------------------------------------------- /slides/verification.md: -------------------------------------------------------------------------------- 1 | % Cocotb Learning Journey: Verification Theory 2 | % Vijayvithal Jahagirdar 3 | % October 10 2022 4 | 5 | # Complete verification is not possible 6 | 7 | * The verification effort till now was to cover every row of the truth table for a 2 input logic. 8 | 9 | * A 64 input logic requires a truth table of $2^{64}$ rows. 10 | * Testing at one row per cycle, the simulation requires 18,446,744,073,709,551,616 cycles i.e 18Exa-Ops i.e 18,00,000 trillion Operations 11 | * The best in class server requires for 100+ years for verifying this 12 | * Solution: 13 | * *Directed Tests*: Select a subset of vectors most likely to catch a bug(Min,Max,walking one, walking zero,alternate ones and zeroes etc.) 14 | * *Random Test*: Select a random subset of vectors to increase the likelyhood of hitting unexpected scenario. 15 | 16 | # Directed vs random 17 | 18 | | Parameter | Directed tests | Random tests | 19 | | --- | ---- | ---- | 20 | | Effort for test environment | Less. | More | 21 | | Effort for testcases | More. | Less | 22 | | Simulation time | Less | More | 23 | | Hits known corner cases | Yes | No | 24 | | Hits unknown corner cases | May not | Yes | 25 | 26 | # Approach 27 | 28 | * Directed for initial bringup 29 | * Randomization for regression testing 30 | * Code and Functional coverage for signoff 31 | 32 | # Metric for completion of verification 33 | 34 | * Code Coverage: Measured by simulator 35 | * Statement/ line/ block coverage 36 | * Branch coverage 37 | * Toggle coverage 38 | * Functional Coverage: Defined by test env writer 39 | * Bins 40 | * Cross Coverage 41 | 42 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | SIM ?= icarus 2 | TOPLEVEL_LANG ?= verilog 3 | VERILOG_SOURCES += $(PWD)/../hdl/or_gate.v 4 | VERILOG_SOURCES += $(PWD)/wrappers/or_test.v 5 | VERILOG_SOURCES += $(PWD)/wrappers/ifc_test.v 6 | VERILOG_SOURCES += $(PWD)/../hdl/ifc_or.v 7 | VERILOG_SOURCES += $(PWD)/../hdl/FIFO1.v 8 | VERILOG_SOURCES += $(PWD)/../hdl/FIFO2.v 9 | all: or ifc 10 | or: 11 | rm -rf sim_build 12 | $(MAKE) sim MODULE=or_test TOPLEVEL=or_test 13 | ifc: 14 | rm -rf sim_build 15 | $(MAKE) sim MODULE=ifc_test TOPLEVEL=ifc_test 16 | coverage: 17 | rm -rf sim_build 18 | $(MAKE) sim MODULE=ifc_coverage TOPLEVEL=ifc_test 19 | include $(shell cocotb-config --makefiles)/Makefile.sim 20 | -------------------------------------------------------------------------------- /tests/crv.py: -------------------------------------------------------------------------------- 1 | # Packet: Fields Has VLAN, Type, HDRLength, PayloadLength, PacketLength 2 | import constraint 3 | p = constraint.Problem() 4 | p.addVariable('length', range(64, 1500)) 5 | p.addVariable('hdrlength', [14, 16]) 6 | p.addVariable('payloadlength', range(50, 1486)) 7 | p.addVariable('type', range(0x800, 0x807)) 8 | p.addVariable('hasVLAN', [True, False]) 9 | p.addConstraint(lambda hdr, payload, length: length == hdr + 10 | payload, ['hdrlength', 'payloadlength', 'length']) 11 | p.addConstraint(lambda vlan, hdrlen: hdrlen == 12 | 16 if vlan else hdrlen == 14, ['hasVLAN', 'hdrlength']) 13 | p.addConstraint(lambda type, length: length == 64 if type == 14 | 0x806 else True, ['type', 'length']) 15 | print(f"{p.getSolutions()}") 16 | -------------------------------------------------------------------------------- /tests/ifc_coverage.py: -------------------------------------------------------------------------------- 1 | import cocotb 2 | from cocotb.triggers import Timer, FallingEdge, RisingEdge, ReadOnly, NextTimeStep 3 | from cocotb_bus.drivers import BusDriver 4 | from cocotb_bus.monitors import BusMonitor 5 | from cocotb_coverage.coverage import CoverCross, CoverPoint, coverage_db 6 | import os 7 | 8 | 9 | def sb_fn(actual_value): 10 | global expected_value 11 | assert actual_value == expected_value.pop(0), "Scoreboard Matching Failed" 12 | 13 | 14 | @CoverPoint("top.a", # noqa F405 15 | xf=lambda a, b: a, 16 | bins=[0, 1], 17 | bins_labels=['True', 'False'] 18 | ) 19 | @CoverPoint("top.b", # noqa F405 20 | xf=lambda a, b: b, 21 | bins=[0, 1], 22 | bins_labels=['True', 'False'] 23 | ) 24 | @CoverCross("top.cross.ab", 25 | items=["top.b", 26 | "top.a" 27 | ] 28 | ) 29 | def cover(a, b): 30 | cocotb.log.info(f"AB={a} {b}") 31 | pass 32 | 33 | 34 | @cocotb.test() 35 | async def ifc_test(dut): 36 | global expected_value 37 | a = (0, 0, 1, 1) 38 | b = (0, 1, 0, 1) 39 | expected_value = [0, 1, 1, 1] 40 | dut.RST_N.value = 1 41 | await Timer(1, 'ns') 42 | dut.RST_N.value = 0 43 | await Timer(1, 'ns') 44 | await RisingEdge(dut.CLK) 45 | dut.RST_N.value = 1 46 | adrv = InputDriver(dut, 'a', dut.CLK) 47 | InputMonitor(dut, 'a', dut.CLK, callback=a_cover) 48 | bdrv = InputDriver(dut, 'b', dut.CLK) 49 | OutputDriver(dut, 'y', dut.CLK, sb_fn) 50 | 51 | for i in range(4): 52 | adrv.append(a[i]) 53 | bdrv.append(b[i]) 54 | cover(a[i], b[i]) 55 | while len(expected_value) > 0: 56 | await Timer(2, 'ns') 57 | coverage_db.report_coverage(cocotb.log.info, bins=True) 58 | coverage_file = os.path.join( 59 | os.getenv('RESULT_PATH', "./"), 'coverage.xml') 60 | coverage_db.export_to_xml(filename=coverage_file) 61 | 62 | 63 | class InputDriver(BusDriver): 64 | _signals = ['rdy', 'en', 'data'] 65 | 66 | def __init__(self, dut, name, clk): 67 | BusDriver.__init__(self, dut, name, clk) 68 | self.bus.en.value = 0 69 | self.clk = clk 70 | 71 | async def _driver_send(self, value, sync=True): 72 | if self.bus.rdy.value != 1: 73 | await RisingEdge(self.bus.rdy) 74 | self.bus.en.value = 1 75 | self.bus.data.value = value 76 | await ReadOnly() 77 | await RisingEdge(self.clk) 78 | self.bus.en.value = 0 79 | await NextTimeStep() 80 | 81 | 82 | class OutputDriver(BusDriver): 83 | _signals = ['rdy', 'en', 'data'] 84 | 85 | def __init__(self, dut, name, clk, sb_callback): 86 | BusDriver.__init__(self, dut, name, clk) 87 | self.bus.en.value = 0 88 | self.clk = clk 89 | self.callback = sb_callback 90 | self.append(0) 91 | 92 | async def _driver_send(self, value, sync=True): 93 | while True: 94 | if self.bus.rdy.value != 1: 95 | await RisingEdge(self.bus.rdy) 96 | self.bus.en.value = 1 97 | await ReadOnly() 98 | self.callback(self.bus.data.value) 99 | await RisingEdge(self.clk) 100 | await NextTimeStep() 101 | self.bus.en.value = 0 102 | 103 | 104 | class InputMonitor(BusMonitor): 105 | _signals = ['rdy', 'en', 'data'] 106 | 107 | async def _monitor_recv(self): 108 | fallingedge = FallingEdge(self.clock) 109 | rdonly = ReadOnly() 110 | prev_state = 'Idle' 111 | state = { 112 | 0: 'Idle', 113 | 1: 'RDY', 114 | 2: 'Error', 115 | 3: "Txn" 116 | } 117 | while True: 118 | await fallingedge 119 | await rdonly 120 | s = state[self.bus.rdy.value | (self.bus.en.value << 1)] 121 | self._recv({'current': s, 'previous': prev_state}) 122 | prev_state = s 123 | 124 | 125 | @CoverPoint(f"top.a.ifc_state", # noqa F405 126 | xf=lambda x: x['current'], 127 | bins=['Idle', 'RDY', 'Txn'], 128 | ) 129 | @CoverPoint(f"top.a.previfc_state", # noqa F405 130 | xf=lambda x: x['previous'], 131 | bins=['Idle', 'RDY', 'Txn'], 132 | ) 133 | @CoverCross("top.cross.ifc.a", 134 | items=[ 135 | "top.a.previfc_state", "top.a.ifc_state" 136 | ] 137 | ) 138 | def a_cover(state): 139 | cocotb.log.warning(f"state={state}") 140 | pass 141 | -------------------------------------------------------------------------------- /tests/ifc_test.py: -------------------------------------------------------------------------------- 1 | import cocotb 2 | from cocotb.triggers import Timer, RisingEdge, ReadOnly, NextTimeStep, FallingEdge 3 | from cocotb_bus.drivers import BusDriver 4 | from cocotb_coverage.coverage import CoverCross, CoverPoint, coverage_db 5 | from cocotb_bus.monitors import BusMonitor 6 | import os 7 | import random 8 | 9 | 10 | def sb_fn(actual_value): 11 | global expected_value 12 | assert actual_value == expected_value.pop(0), "Scoreboard Matching Failed" 13 | 14 | 15 | @CoverPoint("top.a", # noqa F405 16 | xf=lambda x, y: x, 17 | bins=[0, 1] 18 | ) 19 | @CoverPoint("top.b", # noqa F405 20 | xf=lambda x, y: y, 21 | bins=[0, 1] 22 | ) 23 | @CoverCross("top.cross.ab", 24 | items=["top.a", 25 | "top.b" 26 | ] 27 | ) 28 | def ab_cover(a, b): 29 | pass 30 | 31 | 32 | @CoverPoint("top.prot.a.current", # noqa F405 33 | xf=lambda x: x['current'], 34 | bins=['Idle', 'Rdy', 'Txn'], 35 | ) 36 | @CoverPoint("top.prot.a.previous", # noqa F405 37 | xf=lambda x: x['previous'], 38 | bins=['Idle', 'Rdy', 'Txn'], 39 | ) 40 | @CoverCross("top.cross.a_prot.cross", 41 | items=["top.prot.a.previous", 42 | "top.prot.a.current" 43 | ], 44 | ign_bins=[('Rdy', 'Idle')] 45 | ) 46 | def a_prot_cover(txn): 47 | pass 48 | 49 | 50 | @cocotb.test() 51 | async def ifc_test(dut): 52 | global expected_value 53 | expected_value = [] 54 | dut.RST_N.value = 1 55 | await Timer(1, 'ns') 56 | dut.RST_N.value = 0 57 | await Timer(1, 'ns') 58 | await RisingEdge(dut.CLK) 59 | dut.RST_N.value = 1 60 | adrv = InputDriver(dut, 'a', dut.CLK) 61 | IO_Monitor(dut, 'a', dut.CLK, callback=a_prot_cover) 62 | bdrv = InputDriver(dut, 'b', dut.CLK) 63 | OutputDriver(dut, 'y', dut.CLK, sb_fn) 64 | 65 | for i in range(20): 66 | a = random.randint(0, 1) 67 | b = random.randint(0, 1) 68 | expected_value.append(a | b) 69 | adrv.append(a) 70 | bdrv.append(b) 71 | ab_cover(a, b) 72 | while len(expected_value) > 0: 73 | await Timer(2, 'ns') 74 | 75 | coverage_db.report_coverage(cocotb.log.info, bins=True) 76 | coverage_file = os.path.join( 77 | os.getenv('RESULT_PATH', "./"), 'coverage.xml') 78 | coverage_db.export_to_xml(filename=coverage_file) 79 | 80 | 81 | class InputDriver(BusDriver): 82 | _signals = ['rdy', 'en', 'data'] 83 | 84 | def __init__(self, dut, name, clk): 85 | BusDriver.__init__(self, dut, name, clk) 86 | self.bus.en.value = 0 87 | self.clk = clk 88 | 89 | async def _driver_send(self, value, sync=True): 90 | for i in range(random.randint(0, 20)): 91 | await RisingEdge(self.clk) 92 | if self.bus.rdy.value != 1: 93 | await RisingEdge(self.bus.rdy) 94 | self.bus.en.value = 1 95 | self.bus.data.value = value 96 | await ReadOnly() 97 | await RisingEdge(self.clk) 98 | self.bus.en.value = 0 99 | await NextTimeStep() 100 | 101 | 102 | class IO_Monitor(BusMonitor): 103 | _signals = ['rdy', 'en', 'data'] 104 | 105 | async def _monitor_recv(self): 106 | fallingedge = FallingEdge(self.clock) 107 | rdonly = ReadOnly() 108 | phases = { 109 | 0: 'Idle', 110 | 1: 'Rdy', 111 | 3: 'Txn' 112 | } 113 | prev = 'Idle' 114 | while True: 115 | await fallingedge 116 | await rdonly 117 | txn = (self.bus.en.value << 1) | self.bus.rdy.value 118 | self._recv({'previous': prev, 'current': phases[txn]}) 119 | prev = phases[txn] 120 | 121 | 122 | class OutputDriver(BusDriver): 123 | _signals = ['rdy', 'en', 'data'] 124 | 125 | def __init__(self, dut, name, clk, sb_callback): 126 | BusDriver.__init__(self, dut, name, clk) 127 | self.bus.en.value = 0 128 | self.clk = clk 129 | self.callback = sb_callback 130 | self.append(0) 131 | 132 | async def _driver_send(self, value, sync=True): 133 | while True: 134 | for i in range(random.randint(0, 20)): 135 | await RisingEdge(self.clk) 136 | if self.bus.rdy.value != 1: 137 | await RisingEdge(self.bus.rdy) 138 | self.bus.en.value = 1 139 | await ReadOnly() 140 | self.callback(self.bus.data.value) 141 | await RisingEdge(self.clk) 142 | await NextTimeStep() 143 | self.bus.en.value = 0 144 | -------------------------------------------------------------------------------- /tests/or_test.py: -------------------------------------------------------------------------------- 1 | import cocotb 2 | from cocotb.triggers import Timer, RisingEdge 3 | 4 | 5 | @cocotb.test() 6 | async def or_test(dut): 7 | a = (0, 0, 1, 1) 8 | b = (0, 1, 0, 1) 9 | y = (0, 1, 1, 1) 10 | 11 | for i in range(4): 12 | dut.a.value = a[i] 13 | dut.b.value = b[i] 14 | await Timer(1, 'ns') 15 | assert dut.y.value == y[i], f"Error at iteration {i}" 16 | -------------------------------------------------------------------------------- /tests/wrappers/ifc_test.v: -------------------------------------------------------------------------------- 1 | module ifc_test(CLK, 2 | RST_N, 3 | 4 | a_data, 5 | a_en, 6 | a_rdy, 7 | 8 | b_data, 9 | b_en, 10 | b_rdy, 11 | 12 | y_en, 13 | y_data, 14 | y_rdy); 15 | output reg CLK; 16 | input RST_N; 17 | 18 | // action method a 19 | input a_data; 20 | input a_en; 21 | output a_rdy; 22 | 23 | // action method b 24 | input b_data; 25 | input b_en; 26 | output b_rdy; 27 | 28 | // actionvalue method y 29 | input y_en; 30 | output y_data; 31 | output y_rdy; 32 | ifc_or dut( 33 | .CLK(CLK), 34 | .RST_N(RST_N), 35 | .a_data(a_data), 36 | .a_en(a_en), 37 | .a_rdy(a_rdy), 38 | .b_data(b_data), 39 | .b_en(b_en), 40 | .b_rdy(b_rdy), 41 | .y_en(y_en), 42 | .y_data(y_data), 43 | .y_rdy(y_rdy) 44 | ); 45 | 46 | initial begin 47 | $dumpfile("ifc.vcd"); 48 | $dumpvars; 49 | CLK=0; 50 | forever begin 51 | #5 CLK=~CLK; 52 | end 53 | end 54 | endmodule 55 | -------------------------------------------------------------------------------- /tests/wrappers/or_test.v: -------------------------------------------------------------------------------- 1 | module or_test( 2 | input wire a, 3 | input wire b, 4 | output wire y 5 | ); 6 | or_gate or_gate( 7 | .a(a), 8 | .b(b), 9 | .y(y) 10 | ); 11 | 12 | initial begin 13 | $dumpfile("or.vcd"); 14 | $dumpvars; 15 | end 16 | endmodule 17 | --------------------------------------------------------------------------------