pub module lfsr_galois #(
/// Size of the LFSR in bits
param SIZE : u32 = 64 ,
const TAPVEC_T: type = logic<SIZE>,
/// Bit-vector representing the taps of the LFSR.
/// Default values provided for `SIZE` in range [2, 64]
param TAPVEC: TAPVEC_T = case SIZE {
2 : 2'h3,
3 : 3'h5,
4 : 4'h9,
5 : 5'h12,
6 : 6'h21,
7 : 7'h41,
8 : 8'h8e,
9 : 9'h108,
10 : 10'h204,
11 : 11'h402,
12 : 12'h829,
13 : 13'h100d,
14 : 14'h2015,
15 : 15'h4001,
16 : 16'h8016,
17 : 17'h10004,
18 : 18'h20013,
19 : 19'h40013,
20 : 20'h80004,
21 : 21'h100002,
22 : 22'h200001,
23 : 23'h400010,
24 : 24'h80000d,
25 : 25'h1000004,
26 : 26'h2000023,
27 : 27'h4000013,
28 : 28'h8000004,
29 : 29'h10000002,
30 : 30'h20000029,
31 : 31'h40000004,
32 : 32'h80000057,
33 : 33'h100000029,
34 : 34'h200000073,
35 : 35'h400000002,
36 : 36'h80000003b,
37 : 37'h100000001f,
38 : 38'h2000000031,
39 : 39'h4000000008,
40 : 40'h800000001c,
41 : 41'h10000000004,
42 : 42'h2000000001f,
43 : 43'h4000000002c,
44 : 44'h80000000032,
45 : 45'h10000000000d,
46 : 46'h200000000097,
47 : 47'h400000000010,
48 : 48'h80000000005b,
49 : 49'h1000000000038,
50 : 50'h200000000000e,
51 : 51'h4000000000025,
52 : 52'h8000000000004,
53 : 53'h10000000000023,
54 : 54'h2000000000003e,
55 : 55'h40000000000023,
56 : 56'h8000000000004a,
57 : 57'h100000000000016,
58 : 58'h200000000000031,
59 : 59'h40000000000003d,
60 : 60'h800000000000001,
61 : 61'h1000000000000013,
62 : 62'h2000000000000034,
63 : 63'h4000000000000001,
64 : 64'h800000000000000d,
default: '0,
},
) (
/// Clock
i_clk: input clock,
/// Enable - LFSR shifts only when enabled. Active high.
i_en: input logic,
/// Flag to set value of LFSR. Active High.
i_set: input logic,
/// Value which LFSR is set to when `i_set` is set.
i_setval: input logic<SIZE>,
/// LFSR value.
o_val: output logic<SIZE>,
) {
var val_next: logic<SIZE>;
assign val_next[SIZE - 1] = o_val[0];
for i in 0..(SIZE - 1) :g_taps {
const K: u32 = SIZE - 2 - i;
if TAPVEC[K] :g_tap {
assign val_next[K] = if i_set ? i_setval[K] : o_val[K + 1] ^ o_val[0];
} else :g_notap {
assign val_next[K] = if i_set ? i_setval[K] : o_val[K + 1];
}
}
always_ff (i_clk) {
if i_en {
o_val = val_next;
}
}
}
#[test(test_lfsr_galois)]
embed (inline) sv{{{
module test_lfsr_galois;
parameter MAXSIZE = 24;
parameter MINSIZE = 2;
logic [MAXSIZE-1:MINSIZE] done;
logic [MAXSIZE-1:MINSIZE] working;
logic i_clk;
for (genvar i = MINSIZE; i < MAXSIZE; ++i) begin
initial $info("Spawning LFSR of Size %d", i);
lfsr_galois_bench #(.SIZE(i)) u_lfsr(.i_clk, .done(done[i]), .working(working[i]));
end
initial forever @(posedge i_clk) begin
if (&done) begin
if (|working) begin
$info("Finishing Simulations with \033[32m100%% Success\033[0m");
end else begin
$error("Finishing Simulations with \033[31mErrors\033[0m");
end
$finish;
end
end
initial begin
i_clk = 1'b0;
forever #5 i_clk = ~i_clk;
end
endmodule
module lfsr_galois_bench #(parameter SIZE=64) (input i_clk, output logic done, output logic working);
logic [SIZE:0] limit;
logic i_en, i_set;
logic [SIZE-1:0] i_setval;
logic [SIZE-1:0] o_val;
std_lfsr_galois #(.SIZE(SIZE)) dut (.*);
initial begin
int outvecs [logic[SIZE-1:0]];
working = 1'b1;
$info("Begining LFSR of Size %d", SIZE);
done = 1'b0;
i_en = 1'b1;
i_set = 1'b1;
i_setval = 16'h0001;
@(posedge i_clk);
@(posedge i_clk);
i_set = 1'b0;
limit = '1;
limit[0] = 1'b0;
limit[SIZE] = 1'b0;
for (int i = 0; i < limit; i += 1) begin
@(posedge i_clk);
assert(0 == outvecs.exists(o_val));
working &= !outvecs.exists(o_val);
outvecs[o_val] = 1'b1;
end
done = 1'b1;
if (working)
$info("Succesfully Ending LFSR of Size %0d", SIZE);
else
$error("Failure Detecing in LFSR of size %0d", SIZE);
end
endmodule
}}}