1// DESCRIPTION: Verilator: Verilog Test module
2// This file ONLY is placed into the Public Domain, for any use,
3// without warranty, 2019 by Todd Strader.
4// SPDX-License-Identifier: CC0-1.0
5
6`define DRIVE(sig) \
7/* Just throw a bunch of bits at the input */ \
8/* verilator lint_off WIDTH */ \
9sig``_in <= {8{crc}}; \
10/* verilator lint_on WIDTH */
11`define CHECK(sig) \
12if (cyc > 0 && sig``_in != sig``_out) begin \
13   $display(`"%%Error (%m) sig``_in (0x%0x) != sig``_out (0x%0x)`", \
14            sig``_in, sig``_out); \
15     $stop; \
16       end
17
18module t #(parameter GATED_CLK = 0) (/*AUTOARG*/
19   // Inputs
20   clk
21   );
22   input clk;
23
24   localparam last_cyc =
25`ifdef TEST_BENCHMARK
26              `TEST_BENCHMARK;
27`else
28   10;
29`endif
30
31   genvar     x;
32   generate
33      for (x = 0; x < 2; x = x + 1) begin: gen_loop
34         integer cyc = 0;
35         reg [63:0] crc = 64'h5aef0c8d_d70a4497;
36         logic [31:0] accum_in;
37         logic [31:0] accum_out;
38         logic        accum_bypass;
39         logic [31:0] accum_bypass_out;
40         logic [31:0] accum_out_expect;
41         logic [31:0] accum_bypass_out_expect;
42         logic        s1_in;
43         logic        s1_out;
44         logic        s1up_in[2];
45         logic        s1up_out[2];
46         logic [1:0]  s2_in;
47         logic [1:0]  s2_out;
48         logic [7:0]  s8_in;
49         logic [7:0]  s8_out;
50         logic [32:0] s33_in;
51         logic [32:0] s33_out;
52         logic [63:0] s64_in;
53         logic [63:0] s64_out;
54         logic [64:0] s65_in;
55         logic [64:0] s65_out;
56         logic [128:0] s129_in;
57         logic [128:0] s129_out;
58         logic [3:0] [31:0] s4x32_in;
59         logic [3:0] [31:0] s4x32_out;
60         /*verilator lint_off LITENDIAN*/
61         logic [0:15]       s6x16up_in[0:1][2:0];
62         logic [0:15]       s6x16up_out[0:1][2:0];
63         /*verilator lint_on LITENDIAN*/
64         logic [15:0]       s8x16up_in[1:0][0:3];
65         logic [15:0]       s8x16up_out[1:0][0:3];
66         logic [15:0]       s8x16up_3d_in[1:0][0:1][0:1];
67         logic [15:0]       s8x16up_3d_out[1:0][0:1][0:1];
68
69         wire 		    clk_en = crc[0];
70
71         secret
72           secret (
73                   .accum_in,
74                   .accum_out,
75                   .accum_bypass,
76                   .accum_bypass_out,
77                   .s1_in,
78                   .s1_out,
79                   .s1up_in,
80                   .s1up_out,
81                   .s2_in,
82                   .s2_out,
83                   .s8_in,
84                   .s8_out,
85                   .s33_in,
86                   .s33_out,
87                   .s64_in,
88                   .s64_out,
89                   .s65_in,
90                   .s65_out,
91                   .s129_in,
92                   .s129_out,
93                   .s4x32_in,
94                   .s4x32_out,
95                   .s6x16up_in,
96                   .s6x16up_out,
97                   .s8x16up_in,
98                   .s8x16up_out,
99                   .s8x16up_3d_in,
100                   .s8x16up_3d_out,
101                   .clk_en,
102                   .clk);
103
104         always @(posedge clk) begin
105`ifdef TEST_VERBOSE
106            $display("[%0t] x=%0d, cyc=%0d accum_in=%0d accum_out=%0d accum_bypass_out=%0d",
107                     $time, x, cyc, accum_in, accum_out, accum_bypass_out);
108`endif
109            cyc <= cyc + 1;
110            crc <= {crc[62:0], crc[63] ^ crc[2] ^ crc[0]};
111            accum_in <= accum_in + 5;
112            `DRIVE(s1)
113            `DRIVE(s2)
114            `DRIVE(s8)
115            `DRIVE(s33)
116            `DRIVE(s64)
117            `DRIVE(s65)
118            `DRIVE(s129)
119            `DRIVE(s4x32)
120            {s1up_in[1], s1up_in[0]} <= {^crc, ~(^crc)};
121            {s6x16up_in[0][0], s6x16up_in[0][1], s6x16up_in[0][2]} <= crc[47:0];
122            {s6x16up_in[1][0], s6x16up_in[1][1], s6x16up_in[1][2]} <= ~crc[63:16];
123            {s8x16up_in[0][0], s8x16up_in[0][1], s8x16up_in[0][2], s8x16up_in[0][3]} <= crc;
124            {s8x16up_in[1][0], s8x16up_in[1][1], s8x16up_in[1][2], s8x16up_in[1][3]} <= ~crc;
125            {s8x16up_3d_in[0][0][0], s8x16up_3d_in[0][0][1]} <= ~crc[31:0];
126            {s8x16up_3d_in[0][1][0], s8x16up_3d_in[0][1][1]} <= ~crc[63:32];
127            {s8x16up_3d_in[1][0][0], s8x16up_3d_in[1][0][1]} <= crc[31:0];
128            {s8x16up_3d_in[1][1][0], s8x16up_3d_in[1][1][1]} <= crc[63:32];
129            if (cyc == 0) begin
130               accum_in <= x*100;
131               accum_bypass <= '0;
132            end else if (cyc > 0) begin
133               if (accum_out_expect != accum_out) begin
134                  $display("%%Error: (%m) accum_out expected %0d got %0d",
135                           accum_out_expect, accum_out);
136                  $stop;
137               end
138               if (accum_bypass_out_expect != accum_bypass_out) begin
139                  $display("%%Error: (%m) accum_bypass_out expected %0d got %0d",
140                           accum_bypass_out_expect, accum_bypass_out);
141                  $stop;
142               end
143            end
144
145            if (cyc == 5) accum_bypass <= '1;
146
147            if (x == 0 && cyc == last_cyc) begin
148               $display("final cycle = %0d", cyc);
149               $write("*-* All Finished *-*\n");
150               $finish;
151            end
152         end
153
154         logic possibly_gated_clk;
155         if (GATED_CLK != 0) begin: yes_gated_clock
156            logic clk_en_latch /*verilator clock_enable*/;
157            /* verilator lint_off COMBDLY */
158            /* verilator lint_off LATCH */
159            always_comb if (clk == '0) clk_en_latch <= clk_en;
160            /* verilator lint_on LATCH */
161            /* verilator lint_on COMBDLY */
162            assign possibly_gated_clk = clk & clk_en_latch;
163         end else begin: no_gated_clock
164            assign possibly_gated_clk = clk;
165         end
166
167         always @(posedge possibly_gated_clk) begin
168            // 7 is the secret_value inside the secret module
169            accum_out_expect <= accum_in + accum_out_expect + 7;
170         end
171
172         always @(*) begin
173            // XSim (and maybe all event simulators?) sees the moment where
174            // s1_in has not yet propagated to s1_out, however, they do always
175            // both change at the same time
176            /* verilator lint_off STMTDLY */
177            #1;
178            /* verilator lint_on STMTDLY */
179            `CHECK(s1)
180            `CHECK(s1up)
181            `CHECK(s2)
182            `CHECK(s8)
183            `CHECK(s33)
184            `CHECK(s64)
185            `CHECK(s65)
186            `CHECK(s129)
187            `CHECK(s4x32)
188            `CHECK(s6x16up)
189            `CHECK(s8x16up)
190            `CHECK(s8x16up_3d)
191         end
192
193         assign accum_bypass_out_expect = accum_bypass ? accum_in :
194                                          accum_out_expect;
195      end
196   endgenerate
197
198endmodule
199