forked from github/verilator
178 lines
5.2 KiB
Systemverilog
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
|