veryl-std 0.20.3

A modern hardware description language
Documentation
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
}}}