mirror of
https://github.com/verilator/verilator.git
synced 2025-01-10 16:47:48 +00:00
199 lines
6.6 KiB
Systemverilog
199 lines
6.6 KiB
Systemverilog
// DESCRIPTION: Verilator: Verilog Test module
|
|
// This file ONLY is placed into the Public Domain, for any use,
|
|
// without warranty, 2019 by Todd Strader.
|
|
// SPDX-License-Identifier: CC0-1.0
|
|
|
|
`define DRIVE(sig) \
|
|
/* Just throw a bunch of bits at the input */ \
|
|
/* verilator lint_off WIDTH */ \
|
|
sig``_in <= {8{crc}}; \
|
|
/* verilator lint_on WIDTH */
|
|
`define CHECK(sig) \
|
|
if (cyc > 0 && sig``_in != sig``_out) begin \
|
|
$display(`"%%Error (%m) sig``_in (0x%0x) != sig``_out (0x%0x)`", \
|
|
sig``_in, sig``_out); \
|
|
$stop; \
|
|
end
|
|
|
|
module t #(parameter GATED_CLK = 0) (/*AUTOARG*/
|
|
// Inputs
|
|
clk
|
|
);
|
|
input clk;
|
|
|
|
localparam last_cyc =
|
|
`ifdef TEST_BENCHMARK
|
|
`TEST_BENCHMARK;
|
|
`else
|
|
10;
|
|
`endif
|
|
|
|
genvar x;
|
|
generate
|
|
for (x = 0; x < 2; x = x + 1) begin: gen_loop
|
|
integer cyc = 0;
|
|
reg [63:0] crc = 64'h5aef0c8d_d70a4497;
|
|
logic [31:0] accum_in;
|
|
logic [31:0] accum_out;
|
|
logic accum_bypass;
|
|
logic [31:0] accum_bypass_out;
|
|
logic [31:0] accum_out_expect;
|
|
logic [31:0] accum_bypass_out_expect;
|
|
logic s1_in;
|
|
logic s1_out;
|
|
logic s1up_in[2];
|
|
logic s1up_out[2];
|
|
logic [1:0] s2_in;
|
|
logic [1:0] s2_out;
|
|
logic [7:0] s8_in;
|
|
logic [7:0] s8_out;
|
|
logic [32:0] s33_in;
|
|
logic [32:0] s33_out;
|
|
logic [63:0] s64_in;
|
|
logic [63:0] s64_out;
|
|
logic [64:0] s65_in;
|
|
logic [64:0] s65_out;
|
|
logic [128:0] s129_in;
|
|
logic [128:0] s129_out;
|
|
logic [3:0] [31:0] s4x32_in;
|
|
logic [3:0] [31:0] s4x32_out;
|
|
/*verilator lint_off LITENDIAN*/
|
|
logic [0:15] s6x16up_in[0:1][2:0];
|
|
logic [0:15] s6x16up_out[0:1][2:0];
|
|
/*verilator lint_on LITENDIAN*/
|
|
logic [15:0] s8x16up_in[1:0][0:3];
|
|
logic [15:0] s8x16up_out[1:0][0:3];
|
|
logic [15:0] s8x16up_3d_in[1:0][0:1][0:1];
|
|
logic [15:0] s8x16up_3d_out[1:0][0:1][0:1];
|
|
|
|
wire clk_en = crc[0];
|
|
|
|
secret
|
|
secret (
|
|
.accum_in,
|
|
.accum_out,
|
|
.accum_bypass,
|
|
.accum_bypass_out,
|
|
.s1_in,
|
|
.s1_out,
|
|
.s1up_in,
|
|
.s1up_out,
|
|
.s2_in,
|
|
.s2_out,
|
|
.s8_in,
|
|
.s8_out,
|
|
.s33_in,
|
|
.s33_out,
|
|
.s64_in,
|
|
.s64_out,
|
|
.s65_in,
|
|
.s65_out,
|
|
.s129_in,
|
|
.s129_out,
|
|
.s4x32_in,
|
|
.s4x32_out,
|
|
.s6x16up_in,
|
|
.s6x16up_out,
|
|
.s8x16up_in,
|
|
.s8x16up_out,
|
|
.s8x16up_3d_in,
|
|
.s8x16up_3d_out,
|
|
.clk_en,
|
|
.clk);
|
|
|
|
always @(posedge clk) begin
|
|
`ifdef TEST_VERBOSE
|
|
$display("[%0t] x=%0d, cyc=%0d accum_in=%0d accum_out=%0d accum_bypass_out=%0d",
|
|
$time, x, cyc, accum_in, accum_out, accum_bypass_out);
|
|
`endif
|
|
cyc <= cyc + 1;
|
|
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
|
accum_in <= accum_in + 5;
|
|
`DRIVE(s1)
|
|
`DRIVE(s2)
|
|
`DRIVE(s8)
|
|
`DRIVE(s33)
|
|
`DRIVE(s64)
|
|
`DRIVE(s65)
|
|
`DRIVE(s129)
|
|
`DRIVE(s4x32)
|
|
{s1up_in[1], s1up_in[0]} <= {^crc, ~(^crc)};
|
|
{s6x16up_in[0][0], s6x16up_in[0][1], s6x16up_in[0][2]} <= crc[47:0];
|
|
{s6x16up_in[1][0], s6x16up_in[1][1], s6x16up_in[1][2]} <= ~crc[63:16];
|
|
{s8x16up_in[0][0], s8x16up_in[0][1], s8x16up_in[0][2], s8x16up_in[0][3]} <= crc;
|
|
{s8x16up_in[1][0], s8x16up_in[1][1], s8x16up_in[1][2], s8x16up_in[1][3]} <= ~crc;
|
|
{s8x16up_3d_in[0][0][0], s8x16up_3d_in[0][0][1]} <= ~crc[31:0];
|
|
{s8x16up_3d_in[0][1][0], s8x16up_3d_in[0][1][1]} <= ~crc[63:32];
|
|
{s8x16up_3d_in[1][0][0], s8x16up_3d_in[1][0][1]} <= crc[31:0];
|
|
{s8x16up_3d_in[1][1][0], s8x16up_3d_in[1][1][1]} <= crc[63:32];
|
|
if (cyc == 0) begin
|
|
accum_in <= x*100;
|
|
accum_bypass <= '0;
|
|
end else if (cyc > 0) begin
|
|
if (accum_out_expect != accum_out) begin
|
|
$display("%%Error: (%m) accum_out expected %0d got %0d",
|
|
accum_out_expect, accum_out);
|
|
$stop;
|
|
end
|
|
if (accum_bypass_out_expect != accum_bypass_out) begin
|
|
$display("%%Error: (%m) accum_bypass_out expected %0d got %0d",
|
|
accum_bypass_out_expect, accum_bypass_out);
|
|
$stop;
|
|
end
|
|
end
|
|
|
|
if (cyc == 5) accum_bypass <= '1;
|
|
|
|
if (x == 0 && cyc == last_cyc) begin
|
|
$display("final cycle = %0d", cyc);
|
|
$write("*-* All Finished *-*\n");
|
|
$finish;
|
|
end
|
|
end
|
|
|
|
logic possibly_gated_clk;
|
|
if (GATED_CLK != 0) begin: yes_gated_clock
|
|
logic clk_en_latch /*verilator clock_enable*/;
|
|
/* verilator lint_off COMBDLY */
|
|
/* verilator lint_off LATCH */
|
|
always_comb if (clk == '0) clk_en_latch <= clk_en;
|
|
/* verilator lint_on LATCH */
|
|
/* verilator lint_on COMBDLY */
|
|
assign possibly_gated_clk = clk & clk_en_latch;
|
|
end else begin: no_gated_clock
|
|
assign possibly_gated_clk = clk;
|
|
end
|
|
|
|
always @(posedge possibly_gated_clk) begin
|
|
// 7 is the secret_value inside the secret module
|
|
accum_out_expect <= accum_in + accum_out_expect + 7;
|
|
end
|
|
|
|
always @(*) begin
|
|
// XSim (and maybe all event simulators?) sees the moment where
|
|
// s1_in has not yet propagated to s1_out, however, they do always
|
|
// both change at the same time
|
|
/* verilator lint_off STMTDLY */
|
|
#1;
|
|
/* verilator lint_on STMTDLY */
|
|
`CHECK(s1)
|
|
`CHECK(s1up)
|
|
`CHECK(s2)
|
|
`CHECK(s8)
|
|
`CHECK(s33)
|
|
`CHECK(s64)
|
|
`CHECK(s65)
|
|
`CHECK(s129)
|
|
`CHECK(s4x32)
|
|
`CHECK(s6x16up)
|
|
`CHECK(s8x16up)
|
|
`CHECK(s8x16up_3d)
|
|
end
|
|
|
|
assign accum_bypass_out_expect = accum_bypass ? accum_in :
|
|
accum_out_expect;
|
|
end
|
|
endgenerate
|
|
|
|
endmodule
|