blob: 70373f281635b0720f3858b8d49a9668e66ac379 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Testbench module for prim_lfsr, sweeps through all implementations
// within a certain range to check whether they are max length.
module prim_lfsr_tb;
//////////////////////////////////////////////////////
// config
//////////////////////////////////////////////////////
// this can be overriden on the command line
// supported types are GAL_XOR, FIB_XNOR
`ifdef LFSR_TYPE
localparam LfsrType = `LFSR_TYPE;
`else
localparam LfsrType = "GAL_XOR";
`endif
`ifdef MIN_LFSR_DW
localparam int unsigned MinLfsrDw = `MIN_LFSR_DW;
`else
localparam int unsigned MinLfsrDw = 4;
`endif
`ifdef MAX_LFSR_DW
localparam int unsigned MaxLfsrDw = `MAX_LFSR_DW;
`else
localparam int unsigned MaxLfsrDw = 32;
`endif
// leave this constant
localparam logic SEED = 1'b1;
localparam time CLK_PERIOD = 10000;
//////////////////////////////////////////////////////
// clock
//////////////////////////////////////////////////////
wire clk, rst_n;
clk_rst_if main_clk (
.clk,
.rst_n
);
//////////////////////////////////////////////////////
// DUTs
//////////////////////////////////////////////////////
logic [MaxLfsrDw:0] en, err;
logic [MaxLfsrDw:MinLfsrDw][MaxLfsrDw-1:0] data_out;
logic [MaxLfsrDw:MinLfsrDw][MaxLfsrDw-1:0] lfsr_periods;
for (genvar k = MinLfsrDw; k <= MaxLfsrDw; k++) begin : gen_duts
prim_lfsr #(
.LfsrType(LfsrType),
.LfsrDw(k),
.InDw(1),
.OutDw(k),
.Seed(k'(SEED)),
.Custom('0),
// enable internal max length check
.MaxLenSVA(1'b1)
) i_prim_lfsr (
.clk_i(clk),
.rst_ni(rst_n),
.en_i(en[k]),
.data_i(1'b0),
.data_o(data_out[k][k-1:0])
);
if (k < MaxLfsrDw) begin : gen_tie_off
assign data_out[k][MaxLfsrDw-1:k] = '0;
end
// calculate period of LFSR:
assign lfsr_periods[k] = MaxLfsrDw'({{(k-1){1'b1}}, 1'b0});
end
//////////////////////////////////////////////////////
// stimuli application / response checking
//////////////////////////////////////////////////////
initial begin : p_stimuli
en = '0;
err = '0;
main_clk.set_period_ns(CLK_PERIOD);
main_clk.set_active();
main_clk.apply_reset();
$display("LFSR maxlen test started for %s (%0d bit to %0d bit).",
LfsrType, MinLfsrDw, MaxLfsrDw);
main_clk.wait_clks(10);
// enable all LFSRs
en = '1;
$display("Running for 2**%0d-1 cycles...", MaxLfsrDw);
for (longint unsigned k = 0; k <= lfsr_periods[MaxLfsrDw]; k++ ) begin
main_clk.wait_clks(1);
for (int unsigned j = MinLfsrDw; j <= MaxLfsrDw; j++) begin
// check if we reached the initial state again
if (data_out[j] == MaxLfsrDw'(SEED) && en[j]) begin
// $display("cycle: %d -- lfsr: %d -- %x ?= %x, %x",
// k, j, data_out[j], SEED, en);
en[j] = 1'b0;
// we expect this to occur only after the maximum length period
if (lfsr_periods[j] == k) begin
$display("Maxlen check for LFSR %0d succeeded!", j);
end else begin
err[j] = 1'b1;
$error("Error LFSR %0d is not maximal length!", j);
end
end
end
end
main_clk.wait_clks(10);
for (int unsigned j = MinLfsrDw; j <= MaxLfsrDw; j++) begin
if (en[j]) begin
$error("Error LFSR %0d never got back to initial state!", j);
err[j] = 1'b1;
end
end
if (!err) begin
$display("All LFSRs from %0d bit to %0d have maximum length!",
MinLfsrDw, MaxLfsrDw);
// signature for makefile
$display("TEST PASSED CHECKS");
end else begin
$display("One or more checks have failed!");
// signature for makefile
$display("TEST FAILED CHECKS");
end
$finish();
end
endmodule : prim_lfsr_tb