File: t_virtual_interface_method.v

package info (click to toggle)
verilator 5.038-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 162,552 kB
  • sloc: cpp: 139,204; python: 20,931; ansic: 10,222; yacc: 6,000; lex: 1,925; makefile: 1,260; sh: 494; perl: 282; fortran: 22
file content (136 lines) | stat: -rw-r--r-- 2,979 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2003 by Wilson Snyder. This program is free software; you
// can redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
// Create stimulus and Drive the interface
class DriverStim;
  protected virtual example_if v_if;

  task run();
    bit[7:0] x;
    bit[7:0] y;

    v_if.reset();
    forever begin
      x++;
      y++;

      $display("[DriverStim] initiating calculation, x: %8b y: %8b", x, y);
      v_if.initiate_calculation(x, y);
    end
  endtask: run

  function void bind_if(virtual example_if v_if);
    this.v_if = v_if;
  endfunction: bind_if
endclass: DriverStim
// Monitor returns from interface and check them
class MonitorCheck;
  localparam NUM_TXNS = 10;
  protected virtual example_if v_if;

  task run();
    logic[8:0] result;
    int txns_received = 0;

    forever begin
      v_if.wait_for_result(result);
      $display(
        "[MonitorCheck] (%d) result %7b carry_out %1b",
        txns_received, result[7:0], result[8]
        );
      if(++txns_received == NUM_TXNS)  begin
        $write("*-* All Finished *-*\n");
        $finish();
      end
    end
  endtask: run

  function void bind_if(virtual example_if v_if);
    this.v_if = v_if;
  endfunction: bind_if
endclass: MonitorCheck

module example(
  input  logic clk,
  input  logic rstn,
  input  logic[7:0] x,
  input  logic[7:0] y,
  output logic[8:0] z
  );

  // 8 bit full adder
  always_ff @(posedge clk)
    if(!rstn) z <= '0;
    else      z <= x + y;
endmodule: example
// interfaces with the DUT

interface example_if();
  localparam CLK_FREQ_MHz = 400;
  localparam CLK_PERIOD   = 1/((CLK_FREQ_MHz * 1e6) * (1e-12));

  logic      clk;
  logic      rstn;
  logic[7:0] x;
  logic[7:0] y;
  logic[8:0] z;

  initial begin: clk_gen
    forever #(CLK_PERIOD/2) clk = !clk;
  end: clk_gen

  task reset();
    $display("reset called");
    rstn = 0;
    @(posedge clk);
    $display("clock tick");
    rstn = 1;
    @(posedge clk);
  endtask: reset

  event calc_clkd;
  task initiate_calculation(
    input logic[7:0] x_in,
    input logic[7:0] y_in
    );

    x = x_in;
    y = y_in;
    @(posedge clk);
    ->calc_clkd;
  endtask: initiate_calculation

  task wait_for_result(output logic[8:0] result);
    @(calc_clkd);
    result = z;
  endtask: wait_for_result
endinterface: example_if

module t(/*AUTOARG*/);

  example_if example_if_inst();

  example DUT(
    .clk (example_if_inst.clk),
    .rstn(example_if_inst.rstn),
    .x   (example_if_inst.x),
    .y   (example_if_inst.y),
    .z   (example_if_inst.z)
    );


  initial begin: main
    DriverStim   driverStim = new();
    MonitorCheck monitorCheck = new();

    driverStim.bind_if(example_if_inst);
    monitorCheck.bind_if(example_if_inst);

    fork
      driverStim.run();
      monitorCheck.run();
    join_none
  end: main
endmodule: t