176 lines
4.1 KiB
Systemverilog
176 lines
4.1 KiB
Systemverilog
// DESCRIPTION: Verilator: Verilog Test module
|
|
//
|
|
// This file ONLY is placed under the Creative Commons Public Domain.
|
|
// SPDX-FileCopyrightText: 2018 Wilson Snyder
|
|
// SPDX-License-Identifier: CC0-1.0
|
|
|
|
module t (
|
|
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
|