File: t_hier_block.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 (331 lines) | stat: -rw-r--r-- 8,640 bytes parent folder | download | duplicates (3)
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2020 by Yutetsu TAKATSUKASA
// SPDX-License-Identifier: Unlicense

`ifdef USE_VLT
`define HIER_BLOCK
`else
`define HIER_BLOCK /*verilator hier_block*/
`endif

`ifdef SHOW_TIMESCALE
`timescale 1ns/1ps
`endif

interface byte_ifs(input clk);
   logic [7:0] data;
   modport sender(input clk, output data);
   modport receiver(input clk, input data);
endinterface;

`ifdef AS_PROT_LIB
module secret (
   clk
   );
`else
module t (/*AUTOARG*/
   // Inputs
   clk
   );
`endif
   input clk;

`ifdef PROTLIB_TOP
   secret i_secred(.clk(clk));
`else
   /* verilator lint_off UNOPTFLAT */
   wire [7:0] out0;
   wire [7:0] out1;
   wire [7:0] out2;
   wire [7:0] out3;
   /* verilator lint_on UNOPTFLAT */
   wire [7:0] out3_2;
   wire [7:0] out5;
   wire [7:0] out6;
   int count = 0;

   non_hier_sub0 i_sub0(.clk(clk), .in(out3), .out(out0));
   sub1 i_sub1(.clk(clk), .in(out0), .out(out1));
   sub2 i_sub2(.clk(clk), .in(out1), .out(out2));
   sub3 #(.P0(1)) i_sub3(.clk(clk), .in(out2), .out(out3));
   // Must not use the same wrapper
   sub3 #(.STR("abc"), .P0(1)) i_sub3_2(.clk(clk), .in(out2), .out(out3_2));
   delay #(.N(2), 8) i_delay0(clk, out3, out5);
   delay #(.N(3), 8) i_delay1(clk, out5, out6);

   always_ff @(posedge clk) begin
      if (out3 != out3_2) $stop;
      $display("%d out0:%d %d %d %d %d", count, out0, out1, out2, out3, out5, out6);
      if (count == 16) begin
         if (out6 == 19) begin
             $write("*-* All Finished *-*\n");
             $finish;
         end else begin
             $write("Missmatch\n");
             $stop;
         end
      end
      count <= count + 1;
   end

`ifdef CPP_MACRO
   initial begin
      $display("Macro for C++ compiler is defined for Verilator");
      $stop;
   end
`endif

`systemc_implementation
#include <iostream>
#define STRINGIFY_IMPL(str) #str
#define STRINGIFY(str) STRINGIFY_IMPL(str)
namespace {
struct statically_initialized {
   statically_initialized() {
      std::cout << "MACRO:" << STRINGIFY(CPP_MACRO) << " is defined" << std::endl;
   }
} g_statically_initialized;
}
`verilog

`endif  // PROTLIB_TOP

endmodule

module non_hier_sub0(
   input wire clk,
   input wire[7:0] in,
   output wire [7:0] out);

   sub0 i_sub0(.*);

endmodule

module sub0(
   input wire clk,
   input wire [7:0] in,
   output wire [7:0] out); `HIER_BLOCK

   logic [7:0] ff;

   always_ff @(posedge clk) ff <= in;
   assign out = ff;
endmodule

module sub1(
   input wire clk,
   input wire [11:4] in,  // Uses higher LSB to cover bug3539
   output wire [7:0] out); `HIER_BLOCK

   logic [7:0] ff;

   always_ff @(posedge clk) ff <= in + 1;
   assign out = ff;
endmodule

module sub2(
   input wire clk,
   input wire [7:0] in,
   output wire [7:0] out); `HIER_BLOCK

   logic [7:0] ff;

   // dpi_import_func returns (dpi_eport_func(v) -1)
   import "DPI-C" context function int dpi_import_func(int v);
   export "DPI-C" function dpi_export_func;

   function int dpi_export_func(int v);
       return v + 1;
   endfunction

   always_ff @(posedge clk) ff <= 8'(dpi_import_func({24'b0, in})) + 8'd2;

   byte_ifs in_ifs(.clk(clk));
   byte_ifs out_ifs(.clk(clk));
   assign in_ifs.data = ff;
   assign out = out_ifs.data;
   non_hier_sub3 i_sub3(.in(in_ifs), .out(out_ifs));

   always @(posedge clk)
      // dotted access within a hierarchical block should be OK
      if (i_sub3.in_wire != ff) begin
         $display("Error mismatch in %m");
         $stop;
      end
endmodule

module non_hier_sub3(
   byte_ifs.receiver in,
   byte_ifs.sender out);

   wire [7:0] in_wire, out_1, out_2;
   assign in_wire = in.data;
   localparam string sparam = "single quote escape comma:'\\,";
   // Parameter appears in the different order from module declaration
   sub3 #(.STR(sparam), .UNUSED(-16'sd3), .P0(8'd3)) i_sub3(.clk(in.clk), .in(in.data), .out(out_1));
   // Instantiate again, should use the same wrapper
   sub3 #(.STR(sparam), .UNUSED(-16'sd3), .P0(8'd3)) i_sub3_2(.clk(in.clk), .in(in.data), .out(out_2));
   always @(posedge in.clk)
      if (out_1 != out_2) $stop;

   assign out.data = out_1;
endmodule

module sub3 #(
   parameter logic [7:0] P0 = 2 + 1,
   type TYPE = logic,
   parameter int UNPACKED_ARRAY[2] = '{0, 1},
   parameter logic signed [15:0] UNUSED = -3,
   parameter string STR = "str") (
   input wire clk,
   input wire [7:0] in,
   output wire [7:0] out); `HIER_BLOCK

   initial $display("P0:%d UNUSED:%d %s", P0, UNUSED, STR);

   TYPE [7:0] ff;
   always_ff @(posedge clk) ff <= in + P0;
   always_ff @(posedge clk) if (out4 != out4_2) $stop;

   wire [7:0] out4;
   wire [7:0] out4_2;
   assign out = out4;
   /* verilator lint_off REALCVT */
   sub4 #(.P0(1.6), .P1(3.1), .P3(4.1)) i_sub4_0(.clk(clk), .in(ff), .out(out4));  // incr 2
   sub4 #(.P0(2.4), .P1(3.1), .P3(5)) i_sub4_1(.clk(clk), .in(ff), .out(out4_2));
   /* verilator lint_on REALCVT */
endmodule

module sub4 #(
   parameter int P0 = 1.1,
   parameter P1 = 2,
   parameter real P3 = 3) (
   input wire clk,
   input wire [7:0] in,
   output wire[7:0] out); `HIER_BLOCK

   initial begin
      if (P1 == 2) begin
         $display("P1(%f) is not properly set", P1);
         $stop;
      end
   end

   reg [7:0] ff;
   always_ff @(posedge clk) ff <= in + 8'(P0);
   assign out = ff;

   logic [127:0] sub5_in[2][3];
   wire [7:0] sub5_out[2][3];
   sub5 i_sub5(.clk(clk), .in(sub5_in), .out(sub5_out));

   int count = 0;
   always @(posedge clk) begin
      if (!count[0]) begin
         sub5_in[0][0] <= 128'd0;
         sub5_in[0][1] <= 128'd1;
         sub5_in[0][2] <= 128'd2;
         sub5_in[1][0] <= 128'd3;
         sub5_in[1][1] <= 128'd4;
         sub5_in[1][2] <= 128'd5;
      end else begin
         sub5_in[0][0] <= 128'd0;
         sub5_in[0][1] <= 128'd0;
         sub5_in[0][2] <= 128'd0;
         sub5_in[1][0] <= 128'd0;
         sub5_in[1][1] <= 128'd0;
         sub5_in[1][2] <= 128'd0;
      end
   end

   always @(posedge clk) begin
      count <= count + 1;
      if (count > 0) begin
         for (int i = 0; i < 2; ++i) begin
             for (int j = 0; j < 3; ++j) begin
                 automatic byte exp = !count[0] ? 8'(3 * (1 - i) + (2- j) + 1) : 8'b0;
                if (sub5_out[i][j] != exp) begin
                   $display("in[%d][%d] act:%d exp:%d", i, j, sub5_out[i][j], exp);
                   $stop;
                end
            end
         end
      end
   end
endmodule

module sub5 (input wire clk, input wire [127:0] in[2][3], output logic [7:0] out[2][3]); `HIER_BLOCK

   int count = 0;
   always @(posedge clk) begin
      count <= count + 1;
      if (count > 0) begin
         for (int i = 0; i < 2; ++i) begin
            for (int j = 0; j < 3; ++j) begin
               automatic bit [127:0] exp = count[0] ? 128'(3 * i + 128'(j)) : 128'd0;
               if (in[i][j] != exp) begin
                 $display("in[%d][%d] act:%d exp:%d", i, j, in[i][j], exp);
                 $stop;
               end
            end
         end
      end
   end

   always @(posedge clk) begin
      if (count[0]) begin
         out[0][0] <= 8'd6;
         out[0][1] <= 8'd5;
         out[0][2] <= 8'd4;
         out[1][0] <= 8'd3;
         out[1][1] <= 8'd2;
         out[1][2] <= 8'd1;
      end else begin
         out[0][0] <= 8'd0;
         out[0][1] <= 8'd0;
         out[0][2] <= 8'd0;
         out[1][0] <= 8'd0;
         out[1][1] <= 8'd0;
         out[1][2] <= 8'd0;
      end
   end

   wire [7:0] val0[2];
   wire [7:0] val1[2];
   wire [7:0] val2[2];
   wire [7:0] val3[2];
   sub6                   i_sub0(.out(val0));
   sub6 #(.P0(1))         i_sub1(.out(val1));  // Setting the default value
   sub6 #(.P0(1), .P1(2)) i_sub2(.out(val2));  // Setting the default value
   sub6 #(.P0(1), .P1(3)) i_sub3(.out(val3));

   always @(posedge clk) begin
      if (val0[0] != 1 || val0[1] != 2) $stop;
      if (val1[0] != 1 || val1[1] != 2) $stop;
      if (val2[0] != 1 || val2[1] != 2) $stop;
      if (val3[0] != 1 || val3[1] != 3) $stop;
   end
endmodule

module sub6 #(parameter P0 = 1, parameter P1 = 2) (output wire [7:0] out[2]); `HIER_BLOCK
   assign out[0] = 8'(P0);
   assign out[1] = 8'(P1);
endmodule

module delay #(
   parameter N = 1,
   parameter WIDTH = 8) (
   input wire clk,
   input wire[WIDTH-1:0] in,
   output wire [WIDTH-1:0]out); `HIER_BLOCK

   reg [WIDTH-1:0] tmp;
   always_ff @(posedge clk) tmp <= in;
   if (N > 1) begin
      delay #(.N(N - 1), WIDTH) i_delay(clk, tmp, out);
   end else begin
      assign out = tmp;
   end
endmodule