1// DESCRIPTION: Verilator: Verilog Test module
2//
3// This file ONLY is placed under the Creative Commons Public Domain, for
4// any use, without warranty, 2018 by Wilson Snyder.
5// SPDX-License-Identifier: CC0-1.0
6
7module t (/*AUTOARG*/
8   // Inputs
9   clk
10   );
11   input clk;
12
13   integer      cyc = 0;
14   reg [63:0]   crc;
15   reg [63:0]   sum;
16   reg          rst;
17
18   // Two phases, random so nothing optimizes away, and focused so get hits
19   logic        inval;
20   wire [30:0]  wdat     = (cyc < 50 ? crc[30:0] : {29'h0, crc[1:0]});
21   wire [30:0]  cdat     = (cyc < 50 ? crc[30:0] : {29'h0, crc[1:0]});
22   wire         wdat_val = 1'b1;
23   wire         camen    = crc[32];
24   wire         ren      = crc[33];
25   wire         wen      = crc[34];
26   wire [7:0]   rwidx    = (cyc < 50 ? crc[63:56] : {6'h0, crc[57:56]});
27
28   /*AUTOWIRE*/
29   // Beginning of automatic wires (for undeclared instantiated-module outputs)
30   logic                hit_d2r;                // From cam of cam.v
31   logic [7:0]          hitidx_d1r;             // From cam of cam.v
32   logic [255:0]        hitvec_d1r;             // From cam of cam.v
33   logic [30:0]         rdat_d2r;               // From cam of cam.v
34   logic                rdat_val_d2r;           // From cam of cam.v
35   // End of automatics
36
37   cam cam (/*AUTOINST*/
38            // Outputs
39            .hitvec_d1r                 (hitvec_d1r[255:0]),
40            .hitidx_d1r                 (hitidx_d1r[7:0]),
41            .hit_d2r                    (hit_d2r),
42            .rdat_d2r                   (rdat_d2r[30:0]),
43            .rdat_val_d2r               (rdat_val_d2r),
44            // Inputs
45            .clk                        (clk),
46            .rst                        (rst),
47            .camen                      (camen),
48            .inval                      (inval),
49            .cdat                       (cdat[30:0]),
50            .ren                        (ren),
51            .wen                        (wen),
52            .wdat                       (wdat[30:0]),
53            .wdat_val                   (wdat_val),
54            .rwidx                      (rwidx[7:0]));
55
56   // Aggregate outputs into a single result vector
57   wire [63:0] result = {hitvec_d1r[15:0], 15'h0, hit_d2r, rdat_val_d2r, rdat_d2r};
58
59   // Test loop
60   always @ (posedge clk) begin
61`ifdef TEST_VERBOSE
62      $write("[%0t] cyc==%0d crc=%x result=%x\n", $time, cyc, crc, result);
63`endif
64      cyc <= cyc + 1;
65      crc <= {crc[62:0], crc[63] ^ crc[2] ^ crc[0]};
66      sum <= result ^ {sum[62:0], sum[63] ^ sum[2] ^ sum[0]};
67      if (cyc==0) begin
68         // Setup
69         crc <= 64'h5aef0c8d_d70a4497;
70         sum <= '0;
71         rst <= 1'b1;
72      end
73      else if (cyc<10) begin
74         sum <= '0;
75         rst <= 1'b0;
76      end
77      else if (cyc==70) begin
78         inval <= 1'b1;
79      end
80      else if (cyc==71) begin
81         inval <= 1'b0;
82      end
83      else if (cyc==99) begin
84         $write("[%0t] cyc==%0d crc=%x sum=%x\n", $time, cyc, crc, sum);
85         if (crc !== 64'hc77bb9b3784ea091) $stop;
86`define EXPECTED_SUM 64'h5182640870b07199
87         if (sum !== `EXPECTED_SUM) $stop;
88         $write("*-* All Finished *-*\n");
89         $finish;
90      end
91   end
92
93endmodule
94
95module cam
96  (
97   input                clk,
98   input                rst,
99
100   input                camen,
101   input                inval,
102   input [30:0]         cdat,
103   output logic [255:0] hitvec_d1r,
104   output logic [7:0]   hitidx_d1r,
105   output logic         hit_d2r,
106
107   input                ren,
108   input                wen,
109   input [30:0]         wdat,
110   input                wdat_val,
111   input [7:0]          rwidx,
112   output logic [30:0]  rdat_d2r,
113   output logic         rdat_val_d2r
114   );
115
116   logic                camen_d1r;
117   logic                inval_d1r;
118   logic                ren_d1r;
119   logic                wen_d1r;
120   logic [7:0]          rwidx_d1r;
121   logic [30:0]         cdat_d1r;
122   logic [30:0]         wdat_d1r;
123   logic                wdat_val_d1r;
124
125   always_ff @(posedge clk) begin
126      camen_d1r <= camen;
127      inval_d1r <= inval;
128      ren_d1r <= ren;
129      wen_d1r <= wen;
130
131      cdat_d1r <= cdat;
132      rwidx_d1r <= rwidx;
133      wdat_d1r <= wdat;
134      wdat_val_d1r <= wdat_val;
135   end
136
137   typedef struct packed {
138      logic [30:0] data;
139      logic        valid;
140   } entry_t;
141   entry_t [255:0] entries;
142
143   always_ff @(posedge clk) begin
144      if (camen_d1r) begin
145         for (int i = 0; i < 256; i = i + 1) begin
146            hitvec_d1r[i] <= entries[i].valid & (entries[i].data == cdat_d1r);
147         end
148      end
149   end
150   always_ff @(posedge clk) begin
151      hit_d2r <= | hitvec_d1r;
152   end
153
154   always_ff @(posedge clk) begin
155      if (rst) begin
156         for (int i = 0; i < 256; i = i + 1) begin
157            entries[i] <= '0;
158         end
159      end
160      else if (wen_d1r) begin
161         entries[rwidx_d1r] <= '{valid:wdat_val_d1r, data:wdat_d1r};
162      end
163      else if (inval_d1r) begin
164         for (int i = 0; i < 256; i = i + 1) begin
165            entries[i] <= '{valid:'0, data:entries[i].data};
166         end
167      end
168   end
169
170   always_ff @(posedge clk) begin
171      if (ren_d1r) begin
172         rdat_d2r <= entries[rwidx_d1r].data;
173         rdat_val_d2r <= entries[rwidx_d1r].valid;
174      end
175   end
176
177endmodule
178