diff --git a/src/lfsr/lfsr_galois.veryl b/src/lfsr/lfsr_galois.veryl new file mode 100644 index 0000000..d052151 --- /dev/null +++ b/src/lfsr/lfsr_galois.veryl @@ -0,0 +1,112 @@ +pub module lfsr_galois #( + /// Size of the LFSR in bits + parameter SIZE : u32 = 64 , + localparam tapvec: type = logic, + /// Bit-vector representing the taps of the LFSR. + /// Default values provided for `SIZE` in range [2, 64] + parameter TAPVEC: tapvec = 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 logic, + /// 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, + /// LFSR value. + o_val: output logic, +) { + + var val_next: logic; + + assign val_next[SIZE - 1] = o_val[0]; + for i in 0..(SIZE - 1) :g_taps { + localparam k: u32 = SIZE - 2 - i; + if TAPVEC[k] :g_tap { + assign val_next[k] = if i_set { + i_setval[k] + } else { + o_val[k + 1] ^ o_val[0] + }; + } else :g_notap { + assign val_next[k] = if i_set { + i_setval[k] + } else { + o_val[k + 1] + }; + } + } + + always_ff (i_clk) { + if i_en { + o_val = val_next; + } + } +} diff --git a/testbench/lfsr_galois_bench.sv b/testbench/lfsr_galois_bench.sv new file mode 100644 index 0000000..bf6ad21 --- /dev/null +++ b/testbench/lfsr_galois_bench.sv @@ -0,0 +1,83 @@ +module testbench; + 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 $display ("Spawning LFSR of Size %d", i); + lfsr_galois_bench #(.SIZE(i)) u_lfsr(.i_clk, .done(done[i]), .working(working[i])); + end + default clocking + @(posedge i_clk); + endclocking + + initial forever begin + ##4 + if (&done) begin + if (|working) begin + $display("Finishing Simulations with \033[32m100%% Success\033[0m"); + end else begin + $display("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 (.*); + + + default clocking + @(posedge i_clk); + endclocking + + + initial begin + int outvecs [logic[SIZE-1:0]]; + working = 1'b1; + $display("Begining LFSR of Size %d", SIZE); + done = 1'b0; + i_en = 1'b1; + i_set = 1'b1; + i_setval = 16'h0001; + + ##2; + + i_set = 1'b0; + limit = '1; + limit[0] = 1'b0; + limit[SIZE] = 1'b0; + + for (int i = 0; i < limit; i += 1) begin + ##1; + assert(0 == outvecs.exists(o_val)); + working &= !outvecs.exists(o_val); + outvecs[o_val] = 1'b1; + end + + done = 1'b1; + + if (working) + $display("Succesfully Ending LFSR of Size %0d", SIZE); + else + $display("Failure Detecing in LFSR of size %0d", SIZE); + + end + +endmodule