verilator/test_regress/t/t_reloop_cam.v
2021-11-13 10:46:25 -05:00

178 lines
5.2 KiB
Systemverilog

// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2018 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
integer cyc = 0;
reg [63:0] crc;
reg [63:0] sum;
reg rst;
// Two phases, random so nothing optimizes away, and focused so get hits
logic inval;
wire [30:0] wdat = (cyc < 50 ? crc[30:0] : {29'h0, crc[1:0]});
wire [30:0] cdat = (cyc < 50 ? crc[30:0] : {29'h0, crc[1:0]});
wire wdat_val = 1'b1;
wire camen = crc[32];
wire ren = crc[33];
wire wen = crc[34];
wire [7:0] rwidx = (cyc < 50 ? crc[63:56] : {6'h0, crc[57:56]});
/*AUTOWIRE*/
// Beginning of automatic wires (for undeclared instantiated-module outputs)
logic hit_d2r; // From cam of cam.v
logic [7:0] hitidx_d1r; // From cam of cam.v
logic [255:0] hitvec_d1r; // From cam of cam.v
logic [30:0] rdat_d2r; // From cam of cam.v
logic rdat_val_d2r; // From cam of cam.v
// End of automatics
cam cam (/*AUTOINST*/
// Outputs
.hitvec_d1r (hitvec_d1r[255:0]),
.hitidx_d1r (hitidx_d1r[7:0]),
.hit_d2r (hit_d2r),
.rdat_d2r (rdat_d2r[30:0]),
.rdat_val_d2r (rdat_val_d2r),
// Inputs
.clk (clk),
.rst (rst),
.camen (camen),
.inval (inval),
.cdat (cdat[30:0]),
.ren (ren),
.wen (wen),
.wdat (wdat[30:0]),
.wdat_val (wdat_val),
.rwidx (rwidx[7:0]));
// Aggregate outputs into a single result vector
wire [63:0] result = {hitvec_d1r[15:0], 15'h0, hit_d2r, rdat_val_d2r, rdat_d2r};
// Test loop
always @ (posedge clk) begin
`ifdef TEST_VERBOSE
$write("[%0t] cyc==%0d crc=%x result=%x\n", $time, cyc, crc, result);
`endif
cyc <= cyc + 1;
crc <= {crc[62:0], crc[63] ^ crc[2] ^ crc[0]};
sum <= result ^ {sum[62:0], sum[63] ^ sum[2] ^ sum[0]};
if (cyc==0) begin
// Setup
crc <= 64'h5aef0c8d_d70a4497;
sum <= '0;
rst <= 1'b1;
end
else if (cyc<10) begin
sum <= '0;
rst <= 1'b0;
end
else if (cyc==70) begin
inval <= 1'b1;
end
else if (cyc==71) begin
inval <= 1'b0;
end
else if (cyc==99) begin
$write("[%0t] cyc==%0d crc=%x sum=%x\n", $time, cyc, crc, sum);
if (crc !== 64'hc77bb9b3784ea091) $stop;
`define EXPECTED_SUM 64'h5182640870b07199
if (sum !== `EXPECTED_SUM) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
end
endmodule
module cam
(
input clk,
input rst,
input camen,
input inval,
input [30:0] cdat,
output logic [255:0] hitvec_d1r,
output logic [7:0] hitidx_d1r,
output logic hit_d2r,
input ren,
input wen,
input [30:0] wdat,
input wdat_val,
input [7:0] rwidx,
output logic [30:0] rdat_d2r,
output logic rdat_val_d2r
);
logic camen_d1r;
logic inval_d1r;
logic ren_d1r;
logic wen_d1r;
logic [7:0] rwidx_d1r;
logic [30:0] cdat_d1r;
logic [30:0] wdat_d1r;
logic wdat_val_d1r;
always_ff @(posedge clk) begin
camen_d1r <= camen;
inval_d1r <= inval;
ren_d1r <= ren;
wen_d1r <= wen;
cdat_d1r <= cdat;
rwidx_d1r <= rwidx;
wdat_d1r <= wdat;
wdat_val_d1r <= wdat_val;
end
typedef struct packed {
logic [30:0] data;
logic valid;
} entry_t;
entry_t [255:0] entries;
always_ff @(posedge clk) begin
if (camen_d1r) begin
for (int i = 0; i < 256; i = i + 1) begin
hitvec_d1r[i] <= entries[i].valid & (entries[i].data == cdat_d1r);
end
end
end
always_ff @(posedge clk) begin
hit_d2r <= | hitvec_d1r;
end
always_ff @(posedge clk) begin
if (rst) begin
for (int i = 0; i < 256; i = i + 1) begin
entries[i] <= '0;
end
end
else if (wen_d1r) begin
entries[rwidx_d1r] <= '{valid:wdat_val_d1r, data:wdat_d1r};
end
else if (inval_d1r) begin
for (int i = 0; i < 256; i = i + 1) begin
entries[i] <= '{valid:'0, data:entries[i].data};
end
end
end
always_ff @(posedge clk) begin
if (ren_d1r) begin
rdat_d2r <= entries[rwidx_d1r].data;
rdat_val_d2r <= entries[rwidx_d1r].valid;
end
end
endmodule