Full Code of alexforencich/verilog-lfsr for AI

master c1f86d036745 cached
54 files
191.6 KB
55.8k tokens
99 symbols
1 requests
Download .txt
Showing preview only (206K chars total). Download the full file or copy to clipboard to get everything.
Repository: alexforencich/verilog-lfsr
Branch: master
Commit: c1f86d036745
Files: 54
Total size: 191.6 KB

Directory structure:
gitextract_d0iwnulu/

├── .github/
│   └── workflows/
│       └── regression-tests.yml
├── .gitignore
├── AUTHORS
├── COPYING
├── README.md
├── rtl/
│   ├── lfsr.v
│   ├── lfsr_crc.v
│   ├── lfsr_descramble.v
│   ├── lfsr_prbs_check.v
│   ├── lfsr_prbs_gen.v
│   └── lfsr_scramble.v
├── tb/
│   ├── lfsr/
│   │   ├── Makefile
│   │   └── test_lfsr.py
│   ├── lfsr_crc/
│   │   ├── Makefile
│   │   └── test_lfsr_crc.py
│   ├── lfsr_descramble/
│   │   ├── Makefile
│   │   └── test_lfsr_descramble.py
│   ├── lfsr_prbs_check/
│   │   ├── Makefile
│   │   └── test_lfsr_prbs_check.py
│   ├── lfsr_prbs_gen/
│   │   ├── Makefile
│   │   └── test_lfsr_prbs_gen.py
│   ├── lfsr_scramble/
│   │   ├── Makefile
│   │   └── test_lfsr_scramble.py
│   ├── test_lfsr_crc32.py
│   ├── test_lfsr_crc32.v
│   ├── test_lfsr_crc_crc32.py
│   ├── test_lfsr_crc_crc32.v
│   ├── test_lfsr_crc_crc32_64.py
│   ├── test_lfsr_crc_crc32_64.v
│   ├── test_lfsr_descramble.py
│   ├── test_lfsr_descramble.v
│   ├── test_lfsr_descramble_64.py
│   ├── test_lfsr_descramble_64.v
│   ├── test_lfsr_prbs31.py
│   ├── test_lfsr_prbs31.v
│   ├── test_lfsr_prbs9.py
│   ├── test_lfsr_prbs9.v
│   ├── test_lfsr_prbs_check_prbs31.py
│   ├── test_lfsr_prbs_check_prbs31.v
│   ├── test_lfsr_prbs_check_prbs31_64.py
│   ├── test_lfsr_prbs_check_prbs31_64.v
│   ├── test_lfsr_prbs_check_prbs9.py
│   ├── test_lfsr_prbs_check_prbs9.v
│   ├── test_lfsr_prbs_gen_prbs31.py
│   ├── test_lfsr_prbs_gen_prbs31.v
│   ├── test_lfsr_prbs_gen_prbs31_64.py
│   ├── test_lfsr_prbs_gen_prbs31_64.v
│   ├── test_lfsr_prbs_gen_prbs9.py
│   ├── test_lfsr_prbs_gen_prbs9.v
│   ├── test_lfsr_scramble.py
│   ├── test_lfsr_scramble.v
│   ├── test_lfsr_scramble_64.py
│   └── test_lfsr_scramble_64.v
└── tox.ini

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/regression-tests.yml
================================================
name: Regression Tests

on: [push, pull_request]

jobs:
  build:
    name: Python ${{ matrix.python-version }} (${{ matrix.group }}/10)
    runs-on: ubuntu-20.04
    
    strategy:
      matrix:
        python-version: [3.9]
        group: [1, 2, 3, 4, 5]

    steps:
    - uses: actions/checkout@v1

    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v2
      with:
        python-version: ${{ matrix.python-version }}

    - name: Install Icarus Verilog
      run: |
        sudo apt install -y --no-install-recommends iverilog

    - name: Install Python dependencies
      run: |
        python -m pip install --upgrade pip
        pip install tox tox-gh-actions

    - name: Test with tox
      run: tox -- --splits 5 --group ${{ matrix.group }} --splitting-algorithm least_duration


================================================
FILE: .gitignore
================================================
*~
*.lxt
*.pyc
*.vvp
*.kate-swp



================================================
FILE: AUTHORS
================================================
Alex Forencich <alex@alexforencich.com>


================================================
FILE: COPYING
================================================
Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: README.md
================================================
# Verilog LFSR Readme

[![Build Status](https://github.com/alexforencich/verilog-lfsr/workflows/Regression%20Tests/badge.svg?branch=master)](https://github.com/alexforencich/verilog-lfsr/actions/)

For more information and updates: http://alexforencich.com/wiki/en/verilog/lfsr/start

GitHub repository: https://github.com/alexforencich/verilog-lfsr

## Deprecation Notice

This repository is superseded by https://github.com/fpganinja/taxi.  All new features and bug fixes will be applied there, and commercial support is also available.  As a result, this repo is deprecated and will not receive any future maintenance or support.

## Introduction

Fully parametrizable combinatorial parallel LFSR/CRC module.  Implements an unrolled LFSR next state computation.  Includes full cocotb testbenches.

## Documentation

### lfsr module

Fully parametrizable combinatorial parallel LFSR/CRC module.  Implements an unrolled LFSR next state computation.

### lfsr_crc module

Wrapper for lfsr module for standard CRC computation.

### lfsr_descramble module

Wrapper for lfsr module for self-synchronizing descrambler.

### lfsr_prbs_check module

Wrapper for lfsr module for standard PRBS check.

### lfsr_prbs_gen module

Wrapper for lfsr module for standard PRBS computation.

### lfsr_scramble module

Wrapper for lfsr module for self-synchronizing scrambler.

### Source Files

    lfsr.v             : Parametrizable combinatorial LFSR/CRC module
    lfsr_crc.v         : Parametrizable CRC computation wrapper
    lfsr_descramble.v  : Parametrizable LFSR self-synchronizing descrambler
    lfsr_prbs_check.v  : Parametrizable PRBS checker wrapper
    lfsr_prbs_gen.v    : Parametrizable PRBS generator wrapper
    lfsr_scramble.v    : Parametrizable LFSR self-synchronizing scrambler

## Testing

Running the included testbenches requires [cocotb](https://github.com/cocotb/cocotb) and [Icarus Verilog](http://iverilog.icarus.com/).  The testbenches can be run with pytest directly (requires [cocotb-test](https://github.com/themperek/cocotb-test)), pytest via tox, or via cocotb makefiles.


================================================
FILE: rtl/lfsr.v
================================================
/*

Copyright (c) 2016-2023 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`resetall
`timescale 1ns / 1ps
`default_nettype none

/*
 * Parametrizable combinatorial parallel LFSR/CRC
 */
module lfsr #
(
    // width of LFSR
    parameter LFSR_WIDTH = 31,
    // LFSR polynomial
    parameter LFSR_POLY = 31'h10000001,
    // LFSR configuration: "GALOIS", "FIBONACCI"
    parameter LFSR_CONFIG = "FIBONACCI",
    // LFSR feed forward enable
    parameter LFSR_FEED_FORWARD = 0,
    // bit-reverse input and output
    parameter REVERSE = 0,
    // width of data input
    parameter DATA_WIDTH = 8,
    // implementation style: "AUTO", "LOOP", "REDUCTION"
    parameter STYLE = "AUTO"
)
(
    input  wire [DATA_WIDTH-1:0] data_in,
    input  wire [LFSR_WIDTH-1:0] state_in,
    output wire [DATA_WIDTH-1:0] data_out,
    output wire [LFSR_WIDTH-1:0] state_out
);

/*

Fully parametrizable combinatorial parallel LFSR/CRC module.  Implements an unrolled LFSR
next state computation, shifting DATA_WIDTH bits per pass through the module.  Input data
is XORed with LFSR feedback path, tie data_in to zero if this is not required.

Works in two parts: statically computes a set of bit masks, then uses these bit masks to
select bits for XORing to compute the next state.  

Ports:

data_in

Data bits to be shifted through the LFSR (DATA_WIDTH bits)

state_in

LFSR/CRC current state input (LFSR_WIDTH bits)

data_out

Data bits shifted out of LFSR (DATA_WIDTH bits)

state_out

LFSR/CRC next state output (LFSR_WIDTH bits)

Parameters:

LFSR_WIDTH

Specify width of LFSR/CRC register

LFSR_POLY

Specify the LFSR/CRC polynomial in hex format.  For example, the polynomial

x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1

would be represented as

32'h04c11db7

Note that the largest term (x^32) is suppressed.  This term is generated automatically based
on LFSR_WIDTH.

LFSR_CONFIG

Specify the LFSR configuration, either Fibonacci or Galois.  Fibonacci is generally used
for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,
scramblers, and descrambers, while Galois is generally used for cyclic redundancy check
generators and checkers.

Fibonacci style (example for 64b66b scrambler, 0x8000000001)

   DIN (LSB first)
    |
    V
   (+)<---------------------------(+)<-----------------------------.
    |                              ^                               |
    |  .----.  .----.       .----. |  .----.       .----.  .----.  |
    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'
    |  '----'  '----'       '----'    '----'       '----'  '----'
    V
   DOUT

Galois style (example for CRC16, 0x8005)

    ,-------------------+-------------------------+----------(+)<-- DIN (MSB first)
    |                   |                         |           ^
    |  .----.  .----.   V   .----.       .----.   V   .----.  |
    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |--+---> DOUT
       '----'  '----'       '----'       '----'       '----'

LFSR_FEED_FORWARD

Generate feed forward instead of feed back LFSR.  Enable this for PRBS checking and self-
synchronous descrambling.

Fibonacci feed-forward style (example for 64b66b descrambler, 0x8000000001)

   DIN (LSB first)
    |
    |  .----.  .----.       .----.    .----.       .----.  .----.
    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--.
    |  '----'  '----'       '----' |  '----'       '----'  '----'  |
    |                              V                               |
   (+)<---------------------------(+)------------------------------'
    |
    V
   DOUT

Galois feed-forward style

    ,-------------------+-------------------------+------------+--- DIN (MSB first)
    |                   |                         |            |
    |  .----.  .----.   V   .----.       .----.   V   .----.   V
    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |->(+)-> DOUT
       '----'  '----'       '----'       '----'       '----'

REVERSE

Bit-reverse LFSR input and output.  Shifts MSB first by default, set REVERSE for LSB first.

DATA_WIDTH

Specify width of input and output data bus.  The module will perform one shift per input
data bit, so if the input data bus is not required tie data_in to zero and set DATA_WIDTH
to the required number of shifts per clock cycle.  

STYLE

Specify implementation style.  Can be "AUTO", "LOOP", or "REDUCTION".  When "AUTO"
is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate
directives.  "REDUCTION" and "LOOP" are functionally identical, however they simulate
and synthesize differently.  "REDUCTION" is implemented with a loop over a Verilog
reduction operator.  "LOOP" is implemented as a doubly-nested loop with no reduction
operator.  "REDUCTION" is very fast for simulation in iverilog and synthesizes well in
Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing
problems with the optimizer.  "LOOP" synthesizes will in both ISE and Quartus.  "AUTO"
will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey
synthesis translate directives.

Settings for common LFSR/CRC implementations:

Name        Configuration           Length  Polynomial      Initial value   Notes
CRC16-IBM   Galois, bit-reverse     16      16'h8005        16'hffff
CRC16-CCITT Galois                  16      16'h1021        16'h1d0f
CRC32       Galois, bit-reverse     32      32'h04c11db7    32'hffffffff    Ethernet FCS; invert final output
CRC32C      Galois, bit-reverse     32      32'h1edc6f41    32'hffffffff    iSCSI, Intel CRC32 instruction; invert final output
PRBS6       Fibonacci               6       6'h21           any
PRBS7       Fibonacci               7       7'h41           any
PRBS9       Fibonacci               9       9'h021          any             ITU V.52
PRBS10      Fibonacci               10      10'h081         any             ITU
PRBS11      Fibonacci               11      11'h201         any             ITU O.152
PRBS15      Fibonacci, inverted     15      15'h4001        any             ITU O.152
PRBS17      Fibonacci               17      17'h04001       any
PRBS20      Fibonacci               20      20'h00009       any             ITU V.57
PRBS23      Fibonacci, inverted     23      23'h040001      any             ITU O.151
PRBS29      Fibonacci, inverted     29      29'h08000001    any
PRBS31      Fibonacci, inverted     31      31'h10000001    any
64b66b      Fibonacci, bit-reverse  58      58'h8000000001  any             10G Ethernet
128b130b    Galois, bit-reverse     23      23'h210125      any             PCIe gen 3

*/

function [LFSR_WIDTH+DATA_WIDTH-1:0] lfsr_mask(input [31:0] index);
    reg [LFSR_WIDTH-1:0] lfsr_mask_state[LFSR_WIDTH-1:0];
    reg [DATA_WIDTH-1:0] lfsr_mask_data[LFSR_WIDTH-1:0];
    reg [LFSR_WIDTH-1:0] output_mask_state[DATA_WIDTH-1:0];
    reg [DATA_WIDTH-1:0] output_mask_data[DATA_WIDTH-1:0];

    reg [LFSR_WIDTH-1:0] state_val;
    reg [DATA_WIDTH-1:0] data_val;

    reg [DATA_WIDTH-1:0] data_mask;

    integer i, j;

    begin
        // init bit masks
        for (i = 0; i < LFSR_WIDTH; i = i + 1) begin
            lfsr_mask_state[i] = 0;
            lfsr_mask_state[i][i] = 1'b1;
            lfsr_mask_data[i] = 0;
        end
        for (i = 0; i < DATA_WIDTH; i = i + 1) begin
            output_mask_state[i] = 0;
            if (i < LFSR_WIDTH) begin
                output_mask_state[i][i] = 1'b1;
            end
            output_mask_data[i] = 0;
        end

        // simulate shift register
        if (LFSR_CONFIG == "FIBONACCI") begin
            // Fibonacci configuration
            for (data_mask = {1'b1, {DATA_WIDTH-1{1'b0}}}; data_mask != 0; data_mask = data_mask >> 1) begin
                // determine shift in value
                // current value in last FF, XOR with input data bit (MSB first)
                state_val = lfsr_mask_state[LFSR_WIDTH-1];
                data_val = lfsr_mask_data[LFSR_WIDTH-1];
                data_val = data_val ^ data_mask;

                // add XOR inputs from correct indicies
                for (j = 1; j < LFSR_WIDTH; j = j + 1) begin
                    if ((LFSR_POLY >> j) & 1) begin
                        state_val = lfsr_mask_state[j-1] ^ state_val;
                        data_val = lfsr_mask_data[j-1] ^ data_val;
                    end
                end

                // shift
                for (j = LFSR_WIDTH-1; j > 0; j = j - 1) begin
                    lfsr_mask_state[j] = lfsr_mask_state[j-1];
                    lfsr_mask_data[j] = lfsr_mask_data[j-1];
                end
                for (j = DATA_WIDTH-1; j > 0; j = j - 1) begin
                    output_mask_state[j] = output_mask_state[j-1];
                    output_mask_data[j] = output_mask_data[j-1];
                end
                output_mask_state[0] = state_val;
                output_mask_data[0] = data_val;
                if (LFSR_FEED_FORWARD) begin
                    // only shift in new input data
                    state_val = {LFSR_WIDTH{1'b0}};
                    data_val = data_mask;
                end
                lfsr_mask_state[0] = state_val;
                lfsr_mask_data[0] = data_val;
            end
        end else if (LFSR_CONFIG == "GALOIS") begin
            // Galois configuration
            for (data_mask = {1'b1, {DATA_WIDTH-1{1'b0}}}; data_mask != 0; data_mask = data_mask >> 1) begin
                // determine shift in value
                // current value in last FF, XOR with input data bit (MSB first)
                state_val = lfsr_mask_state[LFSR_WIDTH-1];
                data_val = lfsr_mask_data[LFSR_WIDTH-1];
                data_val = data_val ^ data_mask;

                // shift
                for (j = LFSR_WIDTH-1; j > 0; j = j - 1) begin
                    lfsr_mask_state[j] = lfsr_mask_state[j-1];
                    lfsr_mask_data[j] = lfsr_mask_data[j-1];
                end
                for (j = DATA_WIDTH-1; j > 0; j = j - 1) begin
                    output_mask_state[j] = output_mask_state[j-1];
                    output_mask_data[j] = output_mask_data[j-1];
                end
                output_mask_state[0] = state_val;
                output_mask_data[0] = data_val;
                if (LFSR_FEED_FORWARD) begin
                    // only shift in new input data
                    state_val = {LFSR_WIDTH{1'b0}};
                    data_val = data_mask;
                end
                lfsr_mask_state[0] = state_val;
                lfsr_mask_data[0] = data_val;

                // add XOR inputs at correct indicies
                for (j = 1; j < LFSR_WIDTH; j = j + 1) begin
                    if ((LFSR_POLY >> j) & 1) begin
                        lfsr_mask_state[j] = lfsr_mask_state[j] ^ state_val;
                        lfsr_mask_data[j] = lfsr_mask_data[j] ^ data_val;
                    end
                end
            end
        end else begin
            $error("Error: unknown configuration setting!");
            $finish;
        end

        // reverse bits if selected
        if (REVERSE) begin
            if (index < LFSR_WIDTH) begin
                state_val = 0;
                for (i = 0; i < LFSR_WIDTH; i = i + 1) begin
                    state_val[i] = lfsr_mask_state[LFSR_WIDTH-index-1][LFSR_WIDTH-i-1];
                end

                data_val = 0;
                for (i = 0; i < DATA_WIDTH; i = i + 1) begin
                    data_val[i] = lfsr_mask_data[LFSR_WIDTH-index-1][DATA_WIDTH-i-1];
                end
            end else begin
                state_val = 0;
                for (i = 0; i < LFSR_WIDTH; i = i + 1) begin
                    state_val[i] = output_mask_state[DATA_WIDTH-(index-LFSR_WIDTH)-1][LFSR_WIDTH-i-1];
                end

                data_val = 0;
                for (i = 0; i < DATA_WIDTH; i = i + 1) begin
                    data_val[i] = output_mask_data[DATA_WIDTH-(index-LFSR_WIDTH)-1][DATA_WIDTH-i-1];
                end
            end
        end else begin
            if (index < LFSR_WIDTH) begin
                state_val = lfsr_mask_state[index];
                data_val = lfsr_mask_data[index];
            end else begin
                state_val = output_mask_state[index-LFSR_WIDTH];
                data_val = output_mask_data[index-LFSR_WIDTH];
            end
        end
        lfsr_mask = {data_val, state_val};
    end
endfunction

// synthesis translate_off
`define SIMULATION
// synthesis translate_on

`ifdef SIMULATION
// "AUTO" style is "REDUCTION" for faster simulation
parameter STYLE_INT = (STYLE == "AUTO") ? "REDUCTION" : STYLE;
`else
// "AUTO" style is "LOOP" for better synthesis result
parameter STYLE_INT = (STYLE == "AUTO") ? "LOOP" : STYLE;
`endif

genvar n;

generate

if (STYLE_INT == "REDUCTION") begin

    // use Verilog reduction operator
    // fast in iverilog
    // significantly larger than generated code with ISE (inferred wide XORs may be tripping up optimizer)
    // slightly smaller than generated code with Quartus
    // --> better for simulation

    for (n = 0; n < LFSR_WIDTH; n = n + 1) begin : lfsr_state
        wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n);
        assign state_out[n] = ^({data_in, state_in} & mask);
    end
    for (n = 0; n < DATA_WIDTH; n = n + 1) begin : lfsr_data
        wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n+LFSR_WIDTH);
        assign data_out[n] = ^({data_in, state_in} & mask);
    end

end else if (STYLE_INT == "LOOP") begin

    // use nested loops
    // very slow in iverilog
    // slightly smaller than generated code with ISE
    // same size as generated code with Quartus
    // --> better for synthesis

    for (n = 0; n < LFSR_WIDTH; n = n + 1) begin : lfsr_state
        wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n);

        reg state_reg;

        assign state_out[n] = state_reg;

        integer i;

        always @* begin
            state_reg = 1'b0;
            for (i = 0; i < LFSR_WIDTH; i = i + 1) begin
                if (mask[i]) begin
                    state_reg = state_reg ^ state_in[i];
                end
            end
            for (i = 0; i < DATA_WIDTH; i = i + 1) begin
                if (mask[i+LFSR_WIDTH]) begin
                    state_reg = state_reg ^ data_in[i];
                end
            end
        end
    end
    for (n = 0; n < DATA_WIDTH; n = n + 1) begin : lfsr_data
        wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n+LFSR_WIDTH);

        reg data_reg;

        assign data_out[n] = data_reg;

        integer i;

        always @* begin
            data_reg = 1'b0;
            for (i = 0; i < LFSR_WIDTH; i = i + 1) begin
                if (mask[i]) begin
                    data_reg = data_reg ^ state_in[i];
                end
            end
            for (i = 0; i < DATA_WIDTH; i = i + 1) begin
                if (mask[i+LFSR_WIDTH]) begin
                    data_reg = data_reg ^ data_in[i];
                end
            end
        end
    end

end else begin

    initial begin
        $error("Error: unknown style setting!");
        $finish;
    end

end

endgenerate

endmodule

`resetall


================================================
FILE: rtl/lfsr_crc.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`resetall
`timescale 1ns / 1ps
`default_nettype none

/*
 * LFSR CRC generator
 */
module lfsr_crc #
(
    // width of LFSR
    parameter LFSR_WIDTH = 32,
    // LFSR polynomial
    parameter LFSR_POLY = 32'h04c11db7,
    // Initial state
    parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},
    // LFSR configuration: "GALOIS", "FIBONACCI"
    parameter LFSR_CONFIG = "GALOIS",
    // bit-reverse input and output
    parameter REVERSE = 1,
    // invert output
    parameter INVERT = 1,
    // width of data input and output
    parameter DATA_WIDTH = 8,
    // implementation style: "AUTO", "LOOP", "REDUCTION"
    parameter STYLE = "AUTO"
)
(
    input  wire                  clk,
    input  wire                  rst,
    input  wire [DATA_WIDTH-1:0] data_in,
    input  wire                  data_in_valid,
    output wire [LFSR_WIDTH-1:0] crc_out
);

/*

Fully parametrizable combinatorial parallel LFSR CRC module.  Implements an unrolled LFSR
next state computation.  

Ports:

clk

Clock input

rst

Reset module, set state to LFSR_INIT

data_in

CRC data input

data_in_valid

Shift input data through CRC when asserted

data_out

LFSR output (OUTPUT_WIDTH bits)

Parameters:

LFSR_WIDTH

Specify width of LFSR/CRC register

LFSR_POLY

Specify the LFSR/CRC polynomial in hex format.  For example, the polynomial

x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1

would be represented as

32'h04c11db7

Note that the largest term (x^32) is suppressed.  This term is generated automatically based
on LFSR_WIDTH.

LFSR_INIT

Initial state of LFSR.  Defaults to all 1s.

LFSR_CONFIG

Specify the LFSR configuration, either Fibonacci or Galois.  Fibonacci is generally used
for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,
scramblers, and descrambers, while Galois is generally used for cyclic redundancy check
generators and checkers.

Fibonacci style (example for 64b66b scrambler, 0x8000000001)

   DIN (LSB first)
    |
    V
   (+)<---------------------------(+)<-----------------------------.
    |                              ^                               |
    |  .----.  .----.       .----. |  .----.       .----.  .----.  |
    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'
    |  '----'  '----'       '----'    '----'       '----'  '----'
    V
   DOUT

Galois style (example for CRC16, 0x8005)

    ,-------------------+-------------------------+----------(+)<-- DIN (MSB first)
    |                   |                         |           ^
    |  .----.  .----.   V   .----.       .----.   V   .----.  |
    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |--+---> DOUT
       '----'  '----'       '----'       '----'       '----'

REVERSE

Bit-reverse LFSR input and output.  Shifts MSB first by default, set REVERSE for LSB first.

INVERT

Bitwise invert CRC output.

DATA_WIDTH

Specify width of input data bus.  The module will perform one shift per input data bit,
so if the input data bus is not required tie data_in to zero and set DATA_WIDTH to the
required number of shifts per clock cycle.  

STYLE

Specify implementation style.  Can be "AUTO", "LOOP", or "REDUCTION".  When "AUTO"
is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate
directives.  "REDUCTION" and "LOOP" are functionally identical, however they simulate
and synthesize differently.  "REDUCTION" is implemented with a loop over a Verilog
reduction operator.  "LOOP" is implemented as a doubly-nested loop with no reduction
operator.  "REDUCTION" is very fast for simulation in iverilog and synthesizes well in
Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing
problems with the optimizer.  "LOOP" synthesizes will in both ISE and Quartus.  "AUTO"
will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey
synthesis translate directives.

Settings for common LFSR/CRC implementations:

Name        Configuration           Length  Polynomial      Initial value   Notes
CRC16-IBM   Galois, bit-reverse     16      16'h8005        16'hffff
CRC16-CCITT Galois                  16      16'h1021        16'h1d0f
CRC32       Galois, bit-reverse     32      32'h04c11db7    32'hffffffff    Ethernet FCS; invert final output
CRC32C      Galois, bit-reverse     32      32'h1edc6f41    32'hffffffff    iSCSI, Intel CRC32 instruction; invert final output

*/

reg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;
reg [LFSR_WIDTH-1:0] output_reg = 0;

wire [LFSR_WIDTH-1:0] lfsr_state;

assign crc_out = output_reg;

lfsr #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_CONFIG(LFSR_CONFIG),
    .LFSR_FEED_FORWARD(0),
    .REVERSE(REVERSE),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
lfsr_inst (
    .data_in(data_in),
    .state_in(state_reg),
    .data_out(),
    .state_out(lfsr_state)
);

always @(posedge clk) begin
    if (rst) begin
        state_reg <= LFSR_INIT;
        output_reg <= 0;
    end else begin
        if (data_in_valid) begin
            state_reg <= lfsr_state;
            if (INVERT) begin
                output_reg <= ~lfsr_state;
            end else begin
                output_reg <= lfsr_state;
            end
        end
    end
end

endmodule

`resetall


================================================
FILE: rtl/lfsr_descramble.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`resetall
`timescale 1ns / 1ps
`default_nettype none

/*
 * LFSR descrambler
 */
module lfsr_descramble #
(
    // width of LFSR
    parameter LFSR_WIDTH = 58,
    // LFSR polynomial
    parameter LFSR_POLY = 58'h8000000001,
    // Initial state
    parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},
    // LFSR configuration: "GALOIS", "FIBONACCI"
    parameter LFSR_CONFIG = "FIBONACCI",
    // bit-reverse input and output
    parameter REVERSE = 1,
    // width of data bus
    parameter DATA_WIDTH = 64,
    // implementation style: "AUTO", "LOOP", "REDUCTION"
    parameter STYLE = "AUTO"
)
(
    input  wire                  clk,
    input  wire                  rst,
    input  wire [DATA_WIDTH-1:0] data_in,
    input  wire                  data_in_valid,
    output wire [DATA_WIDTH-1:0] data_out
);

/*

Fully parametrizable combinatorial parallel LFSR CRC module.  Implements an unrolled LFSR
next state computation.  

Ports:

clk

Clock input

rst

Reset module, set state to LFSR_INIT

data_in

Scrambled data input (DATA_WIDTH bits)

data_in_valid

Shift input data through CRC when asserted

data_out

Descrambled data output (DATA_WIDTH bits)

Parameters:

LFSR_WIDTH

Specify width of LFSR/CRC register

LFSR_POLY

Specify the LFSR/CRC polynomial in hex format.  For example, the polynomial

x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1

would be represented as

32'h04c11db7

Note that the largest term (x^32) is suppressed.  This term is generated automatically based
on LFSR_WIDTH.

LFSR_INIT

Initial state of LFSR.  Defaults to all 1s.

LFSR_CONFIG

Specify the LFSR configuration, either Fibonacci or Galois.  Fibonacci is generally used
for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,
scramblers, and descrambers, while Galois is generally used for cyclic redundancy check
generators and checkers.

Fibonacci style (example for 64b66b scrambler, 0x8000000001)

   DIN (LSB first)
    |
    V
   (+)<---------------------------(+)<-----------------------------.
    |                              ^                               |
    |  .----.  .----.       .----. |  .----.       .----.  .----.  |
    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'
    |  '----'  '----'       '----'    '----'       '----'  '----'
    V
   DOUT

Galois style (example for CRC16, 0x8005)

    ,-------------------+-------------------------+----------(+)<-- DIN (MSB first)
    |                   |                         |           ^
    |  .----.  .----.   V   .----.       .----.   V   .----.  |
    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |--+---> DOUT
       '----'  '----'       '----'       '----'       '----'

REVERSE

Bit-reverse LFSR input and output.

DATA_WIDTH

Specify width of the data bus.  The module will perform one shift per input data bit.

STYLE

Specify implementation style.  Can be "AUTO", "LOOP", or "REDUCTION".  When "AUTO"
is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate
directives.  "REDUCTION" and "LOOP" are functionally identical, however they simulate
and synthesize differently.  "REDUCTION" is implemented with a loop over a Verilog
reduction operator.  "LOOP" is implemented as a doubly-nested loop with no reduction
operator.  "REDUCTION" is very fast for simulation in iverilog and synthesizes well in
Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing
problems with the optimizer.  "LOOP" synthesizes will in both ISE and Quartus.  "AUTO"
will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey
synthesis translate directives.

Settings for common LFSR/CRC implementations:

Name        Configuration           Length  Polynomial      Initial value   Notes
CRC32       Galois, bit-reverse     32      32'h04c11db7    32'hffffffff    Ethernet FCS; invert final output
PRBS6       Fibonacci               6       6'h21           any
PRBS7       Fibonacci               7       7'h41           any
PRBS9       Fibonacci               9       9'h021          any             ITU V.52
PRBS10      Fibonacci               10      10'h081         any             ITU
PRBS11      Fibonacci               11      11'h201         any             ITU O.152
PRBS15      Fibonacci, inverted     15      15'h4001        any             ITU O.152
PRBS17      Fibonacci               17      17'h04001       any
PRBS20      Fibonacci               20      20'h00009       any             ITU V.57
PRBS23      Fibonacci, inverted     23      23'h040001      any             ITU O.151
PRBS29      Fibonacci, inverted     29      29'h08000001    any
PRBS31      Fibonacci, inverted     31      31'h10000001    any
64b66b      Fibonacci, bit-reverse  58      58'h8000000001  any             10G Ethernet
128b130b    Galois, bit-reverse     23      23'h210125      any             PCIe gen 3

*/

reg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;
reg [DATA_WIDTH-1:0] output_reg = 0;

wire [DATA_WIDTH-1:0] lfsr_data;
wire [LFSR_WIDTH-1:0] lfsr_state;

assign data_out = output_reg;

lfsr #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_CONFIG(LFSR_CONFIG),
    .LFSR_FEED_FORWARD(1),
    .REVERSE(REVERSE),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
lfsr_inst (
    .data_in(data_in),
    .state_in(state_reg),
    .data_out(lfsr_data),
    .state_out(lfsr_state)
);

always @(posedge clk) begin
    if (rst) begin
        state_reg <= LFSR_INIT;
        output_reg <= 0;
    end else begin
        if (data_in_valid) begin
            state_reg <= lfsr_state;
            output_reg <= lfsr_data;
        end
    end
end

endmodule

`resetall


================================================
FILE: rtl/lfsr_prbs_check.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`resetall
`timescale 1ns / 1ps
`default_nettype none

/*
 * LFSR PRBS checker
 */
module lfsr_prbs_check #
(
    // width of LFSR
    parameter LFSR_WIDTH = 31,
    // LFSR polynomial
    parameter LFSR_POLY = 31'h10000001,
    // Initial state
    parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},
    // LFSR configuration: "GALOIS", "FIBONACCI"
    parameter LFSR_CONFIG = "FIBONACCI",
    // bit-reverse input and output
    parameter REVERSE = 0,
    // invert input
    parameter INVERT = 1,
    // width of data input and output
    parameter DATA_WIDTH = 8,
    // implementation style: "AUTO", "LOOP", "REDUCTION"
    parameter STYLE = "AUTO"
)
(
    input  wire                    clk,
    input  wire                    rst,
    input  wire [DATA_WIDTH-1:0]   data_in,
    input  wire                    data_in_valid,
    output wire [DATA_WIDTH-1:0]   data_out
);

/*

Fully parametrizable combinatorial parallel LFSR PRBS checker.  Implements an unrolled LFSR
PRBS checker.  

Ports:

clk

Clock input

rst

Reset input, set state to LFSR_INIT

data_in

PRBS data input (DATA_WIDTH bits)

data_in_valid

Shift input data through LFSR when asserted

data_out

Error output (DATA_WIDTH bits)

Parameters:

LFSR_WIDTH

Specify width of LFSR/CRC register

LFSR_POLY

Specify the LFSR/CRC polynomial in hex format.  For example, the polynomial

x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1

would be represented as

32'h04c11db7

Note that the largest term (x^32) is suppressed.  This term is generated automatically based
on LFSR_WIDTH.

LFSR_INIT

Initial state of LFSR.  Defaults to all 1s.

LFSR_CONFIG

Specify the LFSR configuration, either Fibonacci or Galois.  Fibonacci is generally used
for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,
scramblers, and descrambers, while Galois is generally used for cyclic redundancy check
generators and checkers.

Fibonacci style (example for 64b66b scrambler, 0x8000000001)

   DIN (LSB first)
    |
    V
   (+)<---------------------------(+)<-----------------------------.
    |                              ^                               |
    |  .----.  .----.       .----. |  .----.       .----.  .----.  |
    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'
    |  '----'  '----'       '----'    '----'       '----'  '----'
    V
   DOUT

Galois style (example for CRC16, 0x8005)

    ,-------------------+-------------------------+----------(+)<-- DIN (MSB first)
    |                   |                         |           ^
    |  .----.  .----.   V   .----.       .----.   V   .----.  |
    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |--+---> DOUT
       '----'  '----'       '----'       '----'       '----'

REVERSE

Bit-reverse LFSR output.  Shifts MSB first by default, set REVERSE for LSB first.

INVERT

Bitwise invert PRBS input.

DATA_WIDTH

Specify width of output data bus.

STYLE

Specify implementation style.  Can be "AUTO", "LOOP", or "REDUCTION".  When "AUTO"
is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate
directives.  "REDUCTION" and "LOOP" are functionally identical, however they simulate
and synthesize differently.  "REDUCTION" is implemented with a loop over a Verilog
reduction operator.  "LOOP" is implemented as a doubly-nested loop with no reduction
operator.  "REDUCTION" is very fast for simulation in iverilog and synthesizes well in
Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing
problems with the optimizer.  "LOOP" synthesizes will in both ISE and Quartus.  "AUTO"
will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey
synthesis translate directives.

Settings for common LFSR/CRC implementations:

Name        Configuration           Length  Polynomial      Initial value   Notes
CRC32       Galois, bit-reverse     32      32'h04c11db7    32'hffffffff    Ethernet FCS; invert final output
PRBS6       Fibonacci               6       6'h21           any
PRBS7       Fibonacci               7       7'h41           any
PRBS9       Fibonacci               9       9'h021          any             ITU V.52
PRBS10      Fibonacci               10      10'h081         any             ITU
PRBS11      Fibonacci               11      11'h201         any             ITU O.152
PRBS15      Fibonacci, inverted     15      15'h4001        any             ITU O.152
PRBS17      Fibonacci               17      17'h04001       any
PRBS20      Fibonacci               20      20'h00009       any             ITU V.57
PRBS23      Fibonacci, inverted     23      23'h040001      any             ITU O.151
PRBS29      Fibonacci, inverted     29      29'h08000001    any
PRBS31      Fibonacci, inverted     31      31'h10000001    any
64b66b      Fibonacci, bit-reverse  58      58'h8000000001  any             10G Ethernet
128b130b    Galois, bit-reverse     23      23'h210125      any             PCIe gen 3

*/

reg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;
reg [DATA_WIDTH-1:0] output_reg = 0;

wire [DATA_WIDTH-1:0] lfsr_data;
wire [LFSR_WIDTH-1:0] lfsr_state;

assign data_out = output_reg;

lfsr #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_CONFIG(LFSR_CONFIG),
    .LFSR_FEED_FORWARD(1),
    .REVERSE(REVERSE),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
lfsr_inst (
    .data_in(INVERT ? ~data_in : data_in),
    .state_in(state_reg),
    .data_out(lfsr_data),
    .state_out(lfsr_state)
);

always @(posedge clk) begin
    if (rst) begin
        state_reg <= LFSR_INIT;
        output_reg <= 0;
    end else begin
        if (data_in_valid) begin
            state_reg <= lfsr_state;
            output_reg <= lfsr_data;
        end
    end
end

endmodule

`resetall


================================================
FILE: rtl/lfsr_prbs_gen.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`resetall
`timescale 1ns / 1ps
`default_nettype none

/*
 * LFSR PRBS generator
 */
module lfsr_prbs_gen #
(
    // width of LFSR
    parameter LFSR_WIDTH = 31,
    // LFSR polynomial
    parameter LFSR_POLY = 31'h10000001,
    // Initial state
    parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},
    // LFSR configuration: "GALOIS", "FIBONACCI"
    parameter LFSR_CONFIG = "FIBONACCI",
    // bit-reverse input and output
    parameter REVERSE = 0,
    // invert output
    parameter INVERT = 1,
    // width of data output
    parameter DATA_WIDTH = 8,
    // implementation style: "AUTO", "LOOP", "REDUCTION"
    parameter STYLE = "AUTO"
)
(
    input  wire                  clk,
    input  wire                  rst,
    input  wire                  enable,
    output wire [DATA_WIDTH-1:0] data_out
);

/*

Fully parametrizable combinatorial parallel LFSR PRBS module.  Implements an unrolled LFSR
next state computation.  

Ports:

clk

Clock input

rst

Reset input, set state to LFSR_INIT

enable

Generate new output data

data_out

LFSR output (DATA_WIDTH bits)

Parameters:

LFSR_WIDTH

Specify width of LFSR/CRC register

LFSR_POLY

Specify the LFSR/CRC polynomial in hex format.  For example, the polynomial

x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1

would be represented as

32'h04c11db7

Note that the largest term (x^32) is suppressed.  This term is generated automatically based
on LFSR_WIDTH.

LFSR_INIT

Initial state of LFSR.  Defaults to all 1s.

LFSR_CONFIG

Specify the LFSR configuration, either Fibonacci or Galois.  Fibonacci is generally used
for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,
scramblers, and descrambers, while Galois is generally used for cyclic redundancy check
generators and checkers.

Fibonacci style (example for 64b66b scrambler, 0x8000000001)

   DIN (LSB first)
    |
    V
   (+)<---------------------------(+)<-----------------------------.
    |                              ^                               |
    |  .----.  .----.       .----. |  .----.       .----.  .----.  |
    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'
    |  '----'  '----'       '----'    '----'       '----'  '----'
    V
   DOUT

Galois style (example for CRC16, 0x8005)

    ,-------------------+-------------------------+----------(+)<-- DIN (MSB first)
    |                   |                         |           ^
    |  .----.  .----.   V   .----.       .----.   V   .----.  |
    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |--+---> DOUT
       '----'  '----'       '----'       '----'       '----'

REVERSE

Bit-reverse LFSR output.  Shifts MSB first by default, set REVERSE for LSB first.

INVERT

Bitwise invert PRBS output.

DATA_WIDTH

Specify width of output data bus.

STYLE

Specify implementation style.  Can be "AUTO", "LOOP", or "REDUCTION".  When "AUTO"
is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate
directives.  "REDUCTION" and "LOOP" are functionally identical, however they simulate
and synthesize differently.  "REDUCTION" is implemented with a loop over a Verilog
reduction operator.  "LOOP" is implemented as a doubly-nested loop with no reduction
operator.  "REDUCTION" is very fast for simulation in iverilog and synthesizes well in
Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing
problems with the optimizer.  "LOOP" synthesizes will in both ISE and Quartus.  "AUTO"
will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey
synthesis translate directives.

Settings for common LFSR/CRC implementations:

Name        Configuration           Length  Polynomial      Initial value   Notes
CRC32       Galois, bit-reverse     32      32'h04c11db7    32'hffffffff    Ethernet FCS; invert final output
PRBS6       Fibonacci               6       6'h21           any
PRBS7       Fibonacci               7       7'h41           any
PRBS9       Fibonacci               9       9'h021          any             ITU V.52
PRBS10      Fibonacci               10      10'h081         any             ITU
PRBS11      Fibonacci               11      11'h201         any             ITU O.152
PRBS15      Fibonacci, inverted     15      15'h4001        any             ITU O.152
PRBS17      Fibonacci               17      17'h04001       any
PRBS20      Fibonacci               20      20'h00009       any             ITU V.57
PRBS23      Fibonacci, inverted     23      23'h040001      any             ITU O.151
PRBS29      Fibonacci, inverted     29      29'h08000001    any
PRBS31      Fibonacci, inverted     31      31'h10000001    any
64b66b      Fibonacci, bit-reverse  58      58'h8000000001  any             10G Ethernet
128b130b    Galois, bit-reverse     23      23'h210125      any             PCIe gen 3

*/

reg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;
reg [DATA_WIDTH-1:0] output_reg = 0;

wire [DATA_WIDTH-1:0] lfsr_data;
wire [LFSR_WIDTH-1:0] lfsr_state;

assign data_out = output_reg;

lfsr #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_CONFIG(LFSR_CONFIG),
    .LFSR_FEED_FORWARD(0),
    .REVERSE(REVERSE),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
lfsr_inst (
    .data_in({DATA_WIDTH{1'b0}}),
    .state_in(state_reg),
    .data_out(lfsr_data),
    .state_out(lfsr_state)
);

always @* begin
    if (INVERT) begin
        output_reg <= ~lfsr_data;
    end else begin
        output_reg <= lfsr_data;
    end
end

always @(posedge clk) begin
    if (rst) begin
        state_reg <= LFSR_INIT;
    end else begin
        if (enable) begin
            state_reg <= lfsr_state;
        end
    end
end

endmodule

`resetall


================================================
FILE: rtl/lfsr_scramble.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`resetall
`timescale 1ns / 1ps
`default_nettype none

/*
 * LFSR scrambler
 */
module lfsr_scramble #
(
    // width of LFSR
    parameter LFSR_WIDTH = 58,
    // LFSR polynomial
    parameter LFSR_POLY = 58'h8000000001,
    // Initial state
    parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},
    // LFSR configuration: "GALOIS", "FIBONACCI"
    parameter LFSR_CONFIG = "FIBONACCI",
    // bit-reverse input and output
    parameter REVERSE = 1,
    // width of data bus
    parameter DATA_WIDTH = 64,
    // implementation style: "AUTO", "LOOP", "REDUCTION"
    parameter STYLE = "AUTO"
)
(
    input  wire                  clk,
    input  wire                  rst,
    input  wire [DATA_WIDTH-1:0] data_in,
    input  wire                  data_in_valid,
    output wire [DATA_WIDTH-1:0] data_out
);

/*

Fully parametrizable combinatorial parallel LFSR CRC module.  Implements an unrolled LFSR
next state computation.  

Ports:

clk

Clock input

rst

Reset module, set state to LFSR_INIT

data_in

Unscrambled data input (DATA_WIDTH bits)

data_in_valid

Shift input data through CRC when asserted

data_out

Scrambled data output (DATA_WIDTH bits)

Parameters:

LFSR_WIDTH

Specify width of LFSR/CRC register

LFSR_POLY

Specify the LFSR/CRC polynomial in hex format.  For example, the polynomial

x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1

would be represented as

32'h04c11db7

Note that the largest term (x^32) is suppressed.  This term is generated automatically based
on LFSR_WIDTH.

LFSR_INIT

Initial state of LFSR.  Defaults to all 1s.

LFSR_CONFIG

Specify the LFSR configuration, either Fibonacci or Galois.  Fibonacci is generally used
for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,
scramblers, and descrambers, while Galois is generally used for cyclic redundancy check
generators and checkers.

Fibonacci style (example for 64b66b scrambler, 0x8000000001)

   DIN (LSB first)
    |
    V
   (+)<---------------------------(+)<-----------------------------.
    |                              ^                               |
    |  .----.  .----.       .----. |  .----.       .----.  .----.  |
    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'
    |  '----'  '----'       '----'    '----'       '----'  '----'
    V
   DOUT

Galois style (example for CRC16, 0x8005)

    ,-------------------+-------------------------+----------(+)<-- DIN (MSB first)
    |                   |                         |           ^
    |  .----.  .----.   V   .----.       .----.   V   .----.  |
    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |--+---> DOUT
       '----'  '----'       '----'       '----'       '----'

REVERSE

Bit-reverse LFSR input and output.

DATA_WIDTH

Specify width of the data bus.  The module will perform one shift per input data bit.

STYLE

Specify implementation style.  Can be "AUTO", "LOOP", or "REDUCTION".  When "AUTO"
is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate
directives.  "REDUCTION" and "LOOP" are functionally identical, however they simulate
and synthesize differently.  "REDUCTION" is implemented with a loop over a Verilog
reduction operator.  "LOOP" is implemented as a doubly-nested loop with no reduction
operator.  "REDUCTION" is very fast for simulation in iverilog and synthesizes well in
Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing
problems with the optimizer.  "LOOP" synthesizes will in both ISE and Quartus.  "AUTO"
will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey
synthesis translate directives.

Settings for common LFSR/CRC implementations:

Name        Configuration           Length  Polynomial      Initial value   Notes
CRC32       Galois, bit-reverse     32      32'h04c11db7    32'hffffffff    Ethernet FCS; invert final output
PRBS6       Fibonacci               6       6'h21           any
PRBS7       Fibonacci               7       7'h41           any
PRBS9       Fibonacci               9       9'h021          any             ITU V.52
PRBS10      Fibonacci               10      10'h081         any             ITU
PRBS11      Fibonacci               11      11'h201         any             ITU O.152
PRBS15      Fibonacci, inverted     15      15'h4001        any             ITU O.152
PRBS17      Fibonacci               17      17'h04001       any
PRBS20      Fibonacci               20      20'h00009       any             ITU V.57
PRBS23      Fibonacci, inverted     23      23'h040001      any             ITU O.151
PRBS29      Fibonacci, inverted     29      29'h08000001    any
PRBS31      Fibonacci, inverted     31      31'h10000001    any
64b66b      Fibonacci, bit-reverse  58      58'h8000000001  any             10G Ethernet
128b130b    Galois, bit-reverse     23      23'h210125      any             PCIe gen 3

*/

reg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;
reg [DATA_WIDTH-1:0] output_reg = 0;

wire [DATA_WIDTH-1:0] lfsr_data;
wire [LFSR_WIDTH-1:0] lfsr_state;

assign data_out = output_reg;

lfsr #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_CONFIG(LFSR_CONFIG),
    .LFSR_FEED_FORWARD(0),
    .REVERSE(REVERSE),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
lfsr_inst (
    .data_in(data_in),
    .state_in(state_reg),
    .data_out(lfsr_data),
    .state_out(lfsr_state)
);

always @(posedge clk) begin
    if (rst) begin
        state_reg <= LFSR_INIT;
        output_reg <= 0;
    end else begin
        if (data_in_valid) begin
            state_reg <= lfsr_state;
            output_reg <= lfsr_data;
        end
    end
end

endmodule

`resetall


================================================
FILE: tb/lfsr/Makefile
================================================
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

TOPLEVEL_LANG = verilog

SIM ?= icarus
WAVES ?= 0

COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps

DUT      = lfsr
TOPLEVEL = $(DUT)
MODULE   = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v

# module parameters
export PARAM_LFSR_WIDTH ?= 32
export PARAM_LFSR_POLY ?= "32'h4c11db7"
export PARAM_LFSR_CONFIG ?= "\"GALOIS\""
export PARAM_LFSR_FEED_FORWARD ?= 0
export PARAM_REVERSE ?= 1
export PARAM_DATA_WIDTH ?= 8
export PARAM_STYLE ?= "\"AUTO\""

ifeq ($(SIM), icarus)
	PLUSARGS += -fst

	COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))

	ifeq ($(WAVES), 1)
		VERILOG_SOURCES += iverilog_dump.v
		COMPILE_ARGS += -s iverilog_dump
	endif
else ifeq ($(SIM), verilator)
	COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH

	COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))

	ifeq ($(WAVES), 1)
		COMPILE_ARGS += --trace-fst
	endif
endif

include $(shell cocotb-config --makefiles)/Makefile.sim

iverilog_dump.v:
	echo 'module iverilog_dump();' > $@
	echo 'initial begin' >> $@
	echo '    $$dumpfile("$(TOPLEVEL).fst");' >> $@
	echo '    $$dumpvars(0, $(TOPLEVEL));' >> $@
	echo 'end' >> $@
	echo 'endmodule' >> $@

clean::
	@rm -rf iverilog_dump.v
	@rm -rf dump.fst $(TOPLEVEL).fst


================================================
FILE: tb/lfsr/test_lfsr.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2023 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

import itertools
import logging
import os
import zlib

import pytest
import cocotb_test.simulator

import cocotb
from cocotb.triggers import Timer
from cocotb.regression import TestFactory


class TB:
    def __init__(self, dut):
        self.dut = dut

        self.log = logging.getLogger("cocotb.tb")
        self.log.setLevel(logging.DEBUG)

        dut.data_in.setimmediatevalue(0)
        dut.state_in.setimmediatevalue(0)


def chunks(lst, n, padvalue=None):
    return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)


def crc32(data):
    return zlib.crc32(data) & 0xffffffff


def crc32c(data, crc=0xffffffff, poly=0x82f63b78):
    for d in data:
        crc = crc ^ d
        for bit in range(0, 8):
            if crc & 1:
                crc = (crc >> 1) ^ poly
            else:
                crc = crc >> 1
    return ~crc & 0xffffffff


async def run_test_crc(dut, ref_crc):

    data_width = len(dut.data_in)
    byte_lanes = data_width // 8

    state_width = len(dut.state_in)
    state_mask = 2**state_width-1

    tb = TB(dut)

    await Timer(10, 'ns')

    block = bytes([(x+1)*0x11 for x in range(byte_lanes)])

    dut.state_in.value = state_mask
    dut.data_in.value = int.from_bytes(block, 'little')
    await Timer(10, 'ns')

    val = ~dut.state_out.value.integer & state_mask
    ref = ref_crc(block)

    tb.log.info("CRC: 0x%x (ref: 0x%x)", val, ref)

    assert val == ref

    await Timer(10, 'ns')

    block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))

    dut.state_in.value = state_mask
    for b in chunks(block, byte_lanes):
        dut.data_in.value = int.from_bytes(b, 'little')
        await Timer(10, 'ns')
        dut.state_in.value = dut.state_out.value

    val = ~dut.state_out.value.integer & state_mask
    ref = ref_crc(block)

    tb.log.info("CRC: 0x%x (ref: 0x%x)", val, ref)

    assert val == ref

    await Timer(10, 'ns')


def prbs9(state=0x1ff):
    while True:
        for i in range(8):
            if bool(state & 0x10) ^ bool(state & 0x100):
                state = ((state & 0xff) << 1) | 1
            else:
                state = (state & 0xff) << 1
        yield ~state & 0xff


def prbs31(state=0x7fffffff):
    while True:
        for i in range(8):
            if bool(state & 0x08000000) ^ bool(state & 0x40000000):
                state = ((state & 0x3fffffff) << 1) | 1
            else:
                state = (state & 0x3fffffff) << 1
        yield ~state & 0xff


async def run_test_prbs(dut, ref_prbs):

    data_width = len(dut.data_in)
    byte_lanes = data_width // 8
    data_mask = 2**data_width-1

    state_width = len(dut.state_in)
    state_mask = 2**state_width-1

    tb = TB(dut)

    await Timer(10, 'ns')

    dut.state_in.value = state_mask
    dut.data_in.value = 0
    gen = chunks(ref_prbs(), byte_lanes)

    await Timer(10, 'ns')

    for i in range(512):
        ref = int.from_bytes(bytes(next(gen)), 'big')
        val = ~dut.data_out.value.integer & data_mask

        tb.log.info("PRBS: 0x%x (ref: 0x%x)", val, ref)

        assert ref == val

        dut.state_in.value = dut.state_out.value

        await Timer(10, 'ns')


if cocotb.SIM_NAME:

    if cocotb.top.LFSR_POLY.value == 0x4c11db7:
        factory = TestFactory(run_test_crc)
        factory.add_option("ref_crc", [crc32])
        factory.generate_tests()

    if cocotb.top.LFSR_POLY.value == 0x1edc6f41:
        factory = TestFactory(run_test_crc)
        factory.add_option("ref_crc", [crc32c])
        factory.generate_tests()

    if cocotb.top.LFSR_POLY.value == 0x021:
        factory = TestFactory(run_test_prbs)
        factory.add_option("ref_prbs", [prbs9])
        factory.generate_tests()

    if cocotb.top.LFSR_POLY.value == 0x10000001:
        factory = TestFactory(run_test_prbs)
        factory.add_option("ref_prbs", [prbs31])
        factory.generate_tests()


# cocotb-test

tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))


@pytest.mark.parametrize("style", ["AUTO", "LOOP"])
@pytest.mark.parametrize(("lfsr_width", "lfsr_poly", "lfsr_config", "reverse", "data_width"), [
            (32, "32'h4c11db7", "GALOIS", 1, 8),
            (32, "32'h4c11db7", "GALOIS", 1, 64),
            (32, "32'h1edc6f41", "GALOIS", 1, 8),
            (32, "32'h1edc6f41", "GALOIS", 1, 64),
            (9,  "9'h021", "FIBONACCI", 0, 8),
            (9,  "9'h021", "FIBONACCI", 0, 64),
            (31, "31'h10000001", "FIBONACCI", 0, 8),
            (31, "31'h10000001", "FIBONACCI", 0, 64),
        ])
def test_lfsr(request, lfsr_width, lfsr_poly, lfsr_config, reverse, data_width, style):
    dut = "lfsr"
    module = os.path.splitext(os.path.basename(__file__))[0]
    toplevel = dut

    verilog_sources = [
        os.path.join(rtl_dir, f"{dut}.v"),
    ]

    parameters = {}

    parameters['LFSR_WIDTH'] = lfsr_width
    parameters['LFSR_POLY'] = lfsr_poly
    parameters['LFSR_CONFIG'] = f'"{lfsr_config}"'
    parameters['LFSR_FEED_FORWARD'] = 0
    parameters['REVERSE'] = reverse
    parameters['DATA_WIDTH'] = data_width
    parameters['STYLE'] = f'"{style}"'

    extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}

    sim_build = os.path.join(tests_dir, "sim_build",
        request.node.name.replace('[', '-').replace(']', ''))

    cocotb_test.simulator.run(
        python_search=[tests_dir],
        verilog_sources=verilog_sources,
        toplevel=toplevel,
        module=module,
        parameters=parameters,
        sim_build=sim_build,
        extra_env=extra_env,
    )


================================================
FILE: tb/lfsr_crc/Makefile
================================================
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

TOPLEVEL_LANG = verilog

SIM ?= icarus
WAVES ?= 0

COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps

DUT      = lfsr_crc
TOPLEVEL = $(DUT)
MODULE   = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../rtl/lfsr.v

# module parameters
export PARAM_LFSR_WIDTH ?= 32
export PARAM_LFSR_POLY ?= "32'h4c11db7"
export PARAM_LFSR_INIT ?= "32'hffffffff"
export PARAM_LFSR_CONFIG ?= "\"GALOIS\""
export PARAM_REVERSE ?= 1
export PARAM_INVERT ?= 1
export PARAM_DATA_WIDTH ?= 8
export PARAM_STYLE ?= "\"AUTO\""

ifeq ($(SIM), icarus)
	PLUSARGS += -fst

	COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))

	ifeq ($(WAVES), 1)
		VERILOG_SOURCES += iverilog_dump.v
		COMPILE_ARGS += -s iverilog_dump
	endif
else ifeq ($(SIM), verilator)
	COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH

	COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))

	ifeq ($(WAVES), 1)
		COMPILE_ARGS += --trace-fst
	endif
endif

include $(shell cocotb-config --makefiles)/Makefile.sim

iverilog_dump.v:
	echo 'module iverilog_dump();' > $@
	echo 'initial begin' >> $@
	echo '    $$dumpfile("$(TOPLEVEL).fst");' >> $@
	echo '    $$dumpvars(0, $(TOPLEVEL));' >> $@
	echo 'end' >> $@
	echo 'endmodule' >> $@

clean::
	@rm -rf iverilog_dump.v
	@rm -rf dump.fst $(TOPLEVEL).fst


================================================
FILE: tb/lfsr_crc/test_lfsr_crc.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2023 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

import itertools
import logging
import os
import zlib

import pytest
import cocotb_test.simulator

import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.regression import TestFactory


class TB:
    def __init__(self, dut):
        self.dut = dut

        self.log = logging.getLogger("cocotb.tb")
        self.log.setLevel(logging.DEBUG)

        cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())

        dut.data_in.setimmediatevalue(0)
        dut.data_in_valid.setimmediatevalue(0)

    async def reset(self):
        self.dut.rst.setimmediatevalue(0)
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)
        self.dut.rst.value = 1
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)
        self.dut.rst.value = 0
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)


def chunks(lst, n, padvalue=None):
    return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)


def crc32(data):
    return zlib.crc32(data) & 0xffffffff


def crc32c(data, crc=0xffffffff, poly=0x82f63b78):
    for d in data:
        crc = crc ^ d
        for bit in range(0, 8):
            if crc & 1:
                crc = (crc >> 1) ^ poly
            else:
                crc = crc >> 1
    return ~crc & 0xffffffff


async def run_test_crc(dut, ref_crc):

    data_width = len(dut.data_in)
    byte_lanes = data_width // 8

    tb = TB(dut)

    await tb.reset()

    block = bytes([(x+1)*0x11 for x in range(byte_lanes)])

    dut.data_in.value = int.from_bytes(block, 'little')
    dut.data_in_valid.value = 1
    await RisingEdge(dut.clk)
    dut.data_in_valid.value = 0

    await RisingEdge(dut.clk)
    val = dut.crc_out.value.integer
    ref = ref_crc(block)

    tb.log.info("CRC: 0x%x (ref: 0x%x)", val, ref)

    assert val == ref

    await tb.reset()

    block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))

    for b in chunks(block, byte_lanes):
        dut.data_in.value = int.from_bytes(b, 'little')
        dut.data_in_valid.value = 1
        await RisingEdge(dut.clk)
    dut.data_in_valid.value = 0

    await RisingEdge(dut.clk)
    val = dut.crc_out.value.integer
    ref = ref_crc(block)

    tb.log.info("CRC: 0x%x (ref: 0x%x)", val, ref)

    assert val == ref

    await RisingEdge(dut.clk)
    await RisingEdge(dut.clk)


if cocotb.SIM_NAME:

    if cocotb.top.LFSR_POLY.value == 0x4c11db7:
        factory = TestFactory(run_test_crc)
        factory.add_option("ref_crc", [crc32])
        factory.generate_tests()

    if cocotb.top.LFSR_POLY.value == 0x1edc6f41:
        factory = TestFactory(run_test_crc)
        factory.add_option("ref_crc", [crc32c])
        factory.generate_tests()


# cocotb-test

tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))


@pytest.mark.parametrize("style", ["AUTO", "LOOP"])
@pytest.mark.parametrize(("lfsr_width", "lfsr_poly", "lfsr_init", "lfsr_config", "reverse", "invert", "data_width"), [
            (32, "32'h4c11db7", "32'hffffffff", "GALOIS", 1, 1, 8),
            (32, "32'h4c11db7", "32'hffffffff", "GALOIS", 1, 1, 64),
            (32, "32'h1edc6f41", "32'hffffffff", "GALOIS", 1, 1, 8),
            (32, "32'h1edc6f41", "32'hffffffff", "GALOIS", 1, 1, 64),
        ])
def test_lfsr_crc(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, invert, data_width, style):
    dut = "lfsr_crc"
    module = os.path.splitext(os.path.basename(__file__))[0]
    toplevel = dut

    verilog_sources = [
        os.path.join(rtl_dir, f"{dut}.v"),
        os.path.join(rtl_dir, "lfsr.v"),
    ]

    parameters = {}

    parameters['LFSR_WIDTH'] = lfsr_width
    parameters['LFSR_POLY'] = lfsr_poly
    parameters['LFSR_INIT'] = lfsr_init
    parameters['LFSR_CONFIG'] = f'"{lfsr_config}"'
    parameters['REVERSE'] = reverse
    parameters['INVERT'] = invert
    parameters['DATA_WIDTH'] = data_width
    parameters['STYLE'] = f'"{style}"'

    extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}

    sim_build = os.path.join(tests_dir, "sim_build",
        request.node.name.replace('[', '-').replace(']', ''))

    cocotb_test.simulator.run(
        python_search=[tests_dir],
        verilog_sources=verilog_sources,
        toplevel=toplevel,
        module=module,
        parameters=parameters,
        sim_build=sim_build,
        extra_env=extra_env,
    )


================================================
FILE: tb/lfsr_descramble/Makefile
================================================
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

TOPLEVEL_LANG = verilog

SIM ?= icarus
WAVES ?= 0

COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps

DUT      = lfsr_descramble
TOPLEVEL = $(DUT)
MODULE   = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../rtl/lfsr.v

# module parameters
export PARAM_LFSR_WIDTH ?= 58
export PARAM_LFSR_POLY ?= "58'h8000000001"
export PARAM_LFSR_INIT ?= "58'h3ffffffffffffff"
export PARAM_LFSR_CONFIG ?= "\"FIBONACCI\""
export PARAM_REVERSE ?= 1
export PARAM_DATA_WIDTH ?= 8
export PARAM_STYLE ?= "\"AUTO\""

ifeq ($(SIM), icarus)
	PLUSARGS += -fst

	COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))

	ifeq ($(WAVES), 1)
		VERILOG_SOURCES += iverilog_dump.v
		COMPILE_ARGS += -s iverilog_dump
	endif
else ifeq ($(SIM), verilator)
	COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH

	COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))

	ifeq ($(WAVES), 1)
		COMPILE_ARGS += --trace-fst
	endif
endif

include $(shell cocotb-config --makefiles)/Makefile.sim

iverilog_dump.v:
	echo 'module iverilog_dump();' > $@
	echo 'initial begin' >> $@
	echo '    $$dumpfile("$(TOPLEVEL).fst");' >> $@
	echo '    $$dumpvars(0, $(TOPLEVEL));' >> $@
	echo 'end' >> $@
	echo 'endmodule' >> $@

clean::
	@rm -rf iverilog_dump.v
	@rm -rf dump.fst $(TOPLEVEL).fst


================================================
FILE: tb/lfsr_descramble/test_lfsr_descramble.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2023 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

import itertools
import logging
import os

import pytest
import cocotb_test.simulator

import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.regression import TestFactory


class TB:
    def __init__(self, dut):
        self.dut = dut

        self.log = logging.getLogger("cocotb.tb")
        self.log.setLevel(logging.DEBUG)

        cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())

        dut.data_in.setimmediatevalue(0)
        dut.data_in_valid.setimmediatevalue(0)

    async def reset(self):
        self.dut.rst.setimmediatevalue(0)
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)
        self.dut.rst.value = 1
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)
        self.dut.rst.value = 0
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)


def chunks(lst, n, padvalue=None):
    return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)


def scramble_64b66b(data, state=0x3ffffffffffffff):
    data_out = bytearray()
    for d in data:
        b = 0
        for i in range(8):
            if bool(state & (1 << 38)) ^ bool(state & (1 << 57)) ^ bool(d & (1 << i)):
                state = ((state & 0x1ffffffffffffff) << 1) | 1
                b = b | (1 << i)
            else:
                state = (state & 0x1ffffffffffffff) << 1
        data_out.append(b)
    return data_out


def descramble_64b66b(data, state=0x3ffffffffffffff):
    data_out = bytearray()
    for d in data:
        b = 0
        for i in range(8):
            if bool(state & (1 << 38)) ^ bool(state & (1 << 57)) ^ bool(d & (1 << i)):
                b = b | (1 << i)
            state = (state & 0x1ffffffffffffff) << 1 | bool(d & (1 << i))
        data_out += bytearray([b])
    return data_out


async def run_test_descramble(dut, ref_scramble):

    data_width = len(dut.data_in)
    byte_lanes = data_width // 8

    tb = TB(dut)

    await tb.reset()

    block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))

    scr = scramble_64b66b(block)

    dscr = descramble_64b66b(scr)

    assert dscr == block

    ref_iter = iter(chunks(block, byte_lanes))

    first = True
    for b in chunks(scr, byte_lanes):
        dut.data_in.value = int.from_bytes(b, 'little')
        dut.data_in_valid.value = 1
        await RisingEdge(dut.clk)

        val = dut.data_out.value.integer

        if not first:
            ref = int.from_bytes(bytes(next(ref_iter)), 'little')

            tb.log.info("Descrambled: 0x%x (ref: 0x%x)", val, ref)

            assert ref == val

        first = False

    dut.data_in_valid.value = 0

    await RisingEdge(dut.clk)


if cocotb.SIM_NAME:

    # if cocotb.top.LFSR_POLY.value == 0x8000000001:
    if cocotb.top.LFSR_WIDTH == 58:
        factory = TestFactory(run_test_descramble)
        factory.add_option("ref_scramble", [scramble_64b66b])
        factory.generate_tests()


# cocotb-test

tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))


@pytest.mark.parametrize("style", ["AUTO", "LOOP"])
@pytest.mark.parametrize(("lfsr_width", "lfsr_poly", "lfsr_init", "lfsr_config", "reverse", "data_width"), [
            (58,  "58'h8000000001", "58'h3ffffffffffffff", "FIBONACCI", 1, 8),
            (58,  "58'h8000000001", "58'h3ffffffffffffff", "FIBONACCI", 1, 64),
        ])
def test_lfsr_descramble(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, data_width, style):
    dut = "lfsr_descramble"
    module = os.path.splitext(os.path.basename(__file__))[0]
    toplevel = dut

    verilog_sources = [
        os.path.join(rtl_dir, f"{dut}.v"),
        os.path.join(rtl_dir, "lfsr.v"),
    ]

    parameters = {}

    parameters['LFSR_WIDTH'] = lfsr_width
    parameters['LFSR_POLY'] = lfsr_poly
    parameters['LFSR_INIT'] = lfsr_init
    parameters['LFSR_CONFIG'] = f'"{lfsr_config}"'
    parameters['REVERSE'] = reverse
    parameters['DATA_WIDTH'] = data_width
    parameters['STYLE'] = f'"{style}"'

    extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}

    sim_build = os.path.join(tests_dir, "sim_build",
        request.node.name.replace('[', '-').replace(']', ''))

    cocotb_test.simulator.run(
        python_search=[tests_dir],
        verilog_sources=verilog_sources,
        toplevel=toplevel,
        module=module,
        parameters=parameters,
        sim_build=sim_build,
        extra_env=extra_env,
    )


================================================
FILE: tb/lfsr_prbs_check/Makefile
================================================
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

TOPLEVEL_LANG = verilog

SIM ?= icarus
WAVES ?= 0

COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps

DUT      = lfsr_prbs_check
TOPLEVEL = $(DUT)
MODULE   = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../rtl/lfsr.v

# module parameters
export PARAM_LFSR_WIDTH ?= 31
export PARAM_LFSR_POLY ?= "31'h10000001"
export PARAM_LFSR_INIT ?= "31'h7fffffff"
export PARAM_LFSR_CONFIG ?= "\"FIBONACCI\""
export PARAM_REVERSE ?= 0
export PARAM_INVERT ?= 1
export PARAM_DATA_WIDTH ?= 8
export PARAM_STYLE ?= "\"AUTO\""

ifeq ($(SIM), icarus)
	PLUSARGS += -fst

	COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))

	ifeq ($(WAVES), 1)
		VERILOG_SOURCES += iverilog_dump.v
		COMPILE_ARGS += -s iverilog_dump
	endif
else ifeq ($(SIM), verilator)
	COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH

	COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))

	ifeq ($(WAVES), 1)
		COMPILE_ARGS += --trace-fst
	endif
endif

include $(shell cocotb-config --makefiles)/Makefile.sim

iverilog_dump.v:
	echo 'module iverilog_dump();' > $@
	echo 'initial begin' >> $@
	echo '    $$dumpfile("$(TOPLEVEL).fst");' >> $@
	echo '    $$dumpvars(0, $(TOPLEVEL));' >> $@
	echo 'end' >> $@
	echo 'endmodule' >> $@

clean::
	@rm -rf iverilog_dump.v
	@rm -rf dump.fst $(TOPLEVEL).fst


================================================
FILE: tb/lfsr_prbs_check/test_lfsr_prbs_check.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2023 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

import itertools
import logging
import os

import pytest
import cocotb_test.simulator

import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.regression import TestFactory


class TB:
    def __init__(self, dut):
        self.dut = dut

        self.log = logging.getLogger("cocotb.tb")
        self.log.setLevel(logging.DEBUG)

        cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())

        dut.data_in.setimmediatevalue(0)
        dut.data_in_valid.setimmediatevalue(0)

    async def reset(self):
        self.dut.rst.setimmediatevalue(0)
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)
        self.dut.rst.value = 1
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)
        self.dut.rst.value = 0
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)


def chunks(lst, n, padvalue=None):
    return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)


def prbs9(state=0x1ff):
    while True:
        for i in range(8):
            if bool(state & 0x10) ^ bool(state & 0x100):
                state = ((state & 0xff) << 1) | 1
            else:
                state = (state & 0xff) << 1
        yield ~state & 0xff


def prbs31(state=0x7fffffff):
    while True:
        for i in range(8):
            if bool(state & 0x08000000) ^ bool(state & 0x40000000):
                state = ((state & 0x3fffffff) << 1) | 1
            else:
                state = (state & 0x3fffffff) << 1
        yield ~state & 0xff


def count_set_bits(n):
    cnt = 0
    while n:
        n &= n - 1
        cnt += 1
    return cnt


async def run_test_prbs(dut, ref_prbs):

    data_width = len(dut.data_out)
    byte_lanes = data_width // 8

    tb = TB(dut)

    await tb.reset()

    gen = chunks(ref_prbs(), byte_lanes)

    err_cnt = 0

    for i in range(512):

        dut.data_in.value = int.from_bytes(bytes(next(gen)), 'big')
        dut.data_in_valid.value = 1

        val = dut.data_out.value.integer

        tb.log.info("Error value: 0x%x", val)

        err_cnt += count_set_bits(val)

        assert val == 0

        await RisingEdge(dut.clk)

    dut.data_in_valid.value = 0

    tb.log.info("Error count: %d", err_cnt)

    assert err_cnt == 0

    await tb.reset()

    tb.log.info("Single error test")

    gen = chunks(ref_prbs(), byte_lanes)

    err_cnt = 0

    for i in range(64):

        val = int.from_bytes(bytes(next(gen)), 'big')

        if i == 32:
            val = val ^ (1 << (data_width // 2))

        dut.data_in.value = val
        dut.data_in_valid.value = 1

        val = dut.data_out.value.integer

        tb.log.info("Error value: 0x%x", val)

        err_cnt += count_set_bits(val)

        await RisingEdge(dut.clk)

    dut.data_in_valid.value = 0

    tb.log.info("Error count: %d", err_cnt)

    # one bit set per tap
    assert err_cnt == 3


if cocotb.SIM_NAME:

    if cocotb.top.LFSR_POLY.value == 0x021:
        factory = TestFactory(run_test_prbs)
        factory.add_option("ref_prbs", [prbs9])
        factory.generate_tests()

    if cocotb.top.LFSR_POLY.value == 0x10000001:
        factory = TestFactory(run_test_prbs)
        factory.add_option("ref_prbs", [prbs31])
        factory.generate_tests()


# cocotb-test

tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))


@pytest.mark.parametrize("style", ["AUTO", "LOOP"])
@pytest.mark.parametrize(("lfsr_width", "lfsr_poly", "lfsr_init", "lfsr_config", "reverse", "invert", "data_width"), [
            (9,  "9'h021", "9'h1ff", "FIBONACCI", 0, 1, 8),
            (9,  "9'h021", "9'h1ff", "FIBONACCI", 0, 1, 64),
            (31, "31'h10000001", "31'h7fffffff", "FIBONACCI", 0, 1, 8),
            (31, "31'h10000001", "31'h7fffffff", "FIBONACCI", 0, 1, 64),
        ])
def test_lfsr_prbs_check(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, invert, data_width, style):
    dut = "lfsr_prbs_check"
    module = os.path.splitext(os.path.basename(__file__))[0]
    toplevel = dut

    verilog_sources = [
        os.path.join(rtl_dir, f"{dut}.v"),
        os.path.join(rtl_dir, "lfsr.v"),
    ]

    parameters = {}

    parameters['LFSR_WIDTH'] = lfsr_width
    parameters['LFSR_POLY'] = lfsr_poly
    parameters['LFSR_INIT'] = lfsr_init
    parameters['LFSR_CONFIG'] = f'"{lfsr_config}"'
    parameters['REVERSE'] = reverse
    parameters['INVERT'] = invert
    parameters['DATA_WIDTH'] = data_width
    parameters['STYLE'] = f'"{style}"'

    extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}

    sim_build = os.path.join(tests_dir, "sim_build",
        request.node.name.replace('[', '-').replace(']', ''))

    cocotb_test.simulator.run(
        python_search=[tests_dir],
        verilog_sources=verilog_sources,
        toplevel=toplevel,
        module=module,
        parameters=parameters,
        sim_build=sim_build,
        extra_env=extra_env,
    )


================================================
FILE: tb/lfsr_prbs_gen/Makefile
================================================
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

TOPLEVEL_LANG = verilog

SIM ?= icarus
WAVES ?= 0

COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps

DUT      = lfsr_prbs_gen
TOPLEVEL = $(DUT)
MODULE   = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../rtl/lfsr.v

# module parameters
export PARAM_LFSR_WIDTH ?= 31
export PARAM_LFSR_POLY ?= "31'h10000001"
export PARAM_LFSR_INIT ?= "31'h7fffffff"
export PARAM_LFSR_CONFIG ?= "\"FIBONACCI\""
export PARAM_REVERSE ?= 0
export PARAM_INVERT ?= 1
export PARAM_DATA_WIDTH ?= 8
export PARAM_STYLE ?= "\"AUTO\""

ifeq ($(SIM), icarus)
	PLUSARGS += -fst

	COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))

	ifeq ($(WAVES), 1)
		VERILOG_SOURCES += iverilog_dump.v
		COMPILE_ARGS += -s iverilog_dump
	endif
else ifeq ($(SIM), verilator)
	COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH

	COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))

	ifeq ($(WAVES), 1)
		COMPILE_ARGS += --trace-fst
	endif
endif

include $(shell cocotb-config --makefiles)/Makefile.sim

iverilog_dump.v:
	echo 'module iverilog_dump();' > $@
	echo 'initial begin' >> $@
	echo '    $$dumpfile("$(TOPLEVEL).fst");' >> $@
	echo '    $$dumpvars(0, $(TOPLEVEL));' >> $@
	echo 'end' >> $@
	echo 'endmodule' >> $@

clean::
	@rm -rf iverilog_dump.v
	@rm -rf dump.fst $(TOPLEVEL).fst


================================================
FILE: tb/lfsr_prbs_gen/test_lfsr_prbs_gen.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2023 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

import itertools
import logging
import os

import pytest
import cocotb_test.simulator

import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.regression import TestFactory


class TB:
    def __init__(self, dut):
        self.dut = dut

        self.log = logging.getLogger("cocotb.tb")
        self.log.setLevel(logging.DEBUG)

        cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())

        dut.enable.setimmediatevalue(0)

    async def reset(self):
        self.dut.rst.setimmediatevalue(0)
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)
        self.dut.rst.value = 1
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)
        self.dut.rst.value = 0
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)


def chunks(lst, n, padvalue=None):
    return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)


def prbs9(state=0x1ff):
    while True:
        for i in range(8):
            if bool(state & 0x10) ^ bool(state & 0x100):
                state = ((state & 0xff) << 1) | 1
            else:
                state = (state & 0xff) << 1
        yield ~state & 0xff


def prbs31(state=0x7fffffff):
    while True:
        for i in range(8):
            if bool(state & 0x08000000) ^ bool(state & 0x40000000):
                state = ((state & 0x3fffffff) << 1) | 1
            else:
                state = (state & 0x3fffffff) << 1
        yield ~state & 0xff


async def run_test_prbs(dut, ref_prbs):

    data_width = len(dut.data_out)
    byte_lanes = data_width // 8

    tb = TB(dut)

    await tb.reset()

    gen = chunks(ref_prbs(), byte_lanes)

    dut.enable.value = 1
    await RisingEdge(dut.clk)

    for i in range(512):
        ref = int.from_bytes(bytes(next(gen)), 'big')
        val = dut.data_out.value.integer

        tb.log.info("PRBS: 0x%x (ref: 0x%x)", val, ref)

        assert ref == val

        await RisingEdge(dut.clk)


if cocotb.SIM_NAME:

    if cocotb.top.LFSR_POLY.value == 0x021:
        factory = TestFactory(run_test_prbs)
        factory.add_option("ref_prbs", [prbs9])
        factory.generate_tests()

    if cocotb.top.LFSR_POLY.value == 0x10000001:
        factory = TestFactory(run_test_prbs)
        factory.add_option("ref_prbs", [prbs31])
        factory.generate_tests()


# cocotb-test

tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))


@pytest.mark.parametrize("style", ["AUTO", "LOOP"])
@pytest.mark.parametrize(("lfsr_width", "lfsr_poly", "lfsr_init", "lfsr_config", "reverse", "invert", "data_width"), [
            (9,  "9'h021", "9'h1ff", "FIBONACCI", 0, 1, 8),
            (9,  "9'h021", "9'h1ff", "FIBONACCI", 0, 1, 64),
            (31, "31'h10000001", "31'h7fffffff", "FIBONACCI", 0, 1, 8),
            (31, "31'h10000001", "31'h7fffffff", "FIBONACCI", 0, 1, 64),
        ])
def test_lfsr_prbs_gen(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, invert, data_width, style):
    dut = "lfsr_prbs_gen"
    module = os.path.splitext(os.path.basename(__file__))[0]
    toplevel = dut

    verilog_sources = [
        os.path.join(rtl_dir, f"{dut}.v"),
        os.path.join(rtl_dir, "lfsr.v"),
    ]

    parameters = {}

    parameters['LFSR_WIDTH'] = lfsr_width
    parameters['LFSR_POLY'] = lfsr_poly
    parameters['LFSR_INIT'] = lfsr_init
    parameters['LFSR_CONFIG'] = f'"{lfsr_config}"'
    parameters['REVERSE'] = reverse
    parameters['INVERT'] = invert
    parameters['DATA_WIDTH'] = data_width
    parameters['STYLE'] = f'"{style}"'

    extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}

    sim_build = os.path.join(tests_dir, "sim_build",
        request.node.name.replace('[', '-').replace(']', ''))

    cocotb_test.simulator.run(
        python_search=[tests_dir],
        verilog_sources=verilog_sources,
        toplevel=toplevel,
        module=module,
        parameters=parameters,
        sim_build=sim_build,
        extra_env=extra_env,
    )


================================================
FILE: tb/lfsr_scramble/Makefile
================================================
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

TOPLEVEL_LANG = verilog

SIM ?= icarus
WAVES ?= 0

COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps

DUT      = lfsr_scramble
TOPLEVEL = $(DUT)
MODULE   = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../rtl/lfsr.v

# module parameters
export PARAM_LFSR_WIDTH ?= 58
export PARAM_LFSR_POLY ?= "58'h8000000001"
export PARAM_LFSR_INIT ?= "58'h3ffffffffffffff"
export PARAM_LFSR_CONFIG ?= "\"FIBONACCI\""
export PARAM_REVERSE ?= 1
export PARAM_DATA_WIDTH ?= 8
export PARAM_STYLE ?= "\"AUTO\""

ifeq ($(SIM), icarus)
	PLUSARGS += -fst

	COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))

	ifeq ($(WAVES), 1)
		VERILOG_SOURCES += iverilog_dump.v
		COMPILE_ARGS += -s iverilog_dump
	endif
else ifeq ($(SIM), verilator)
	COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH

	COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))

	ifeq ($(WAVES), 1)
		COMPILE_ARGS += --trace-fst
	endif
endif

include $(shell cocotb-config --makefiles)/Makefile.sim

iverilog_dump.v:
	echo 'module iverilog_dump();' > $@
	echo 'initial begin' >> $@
	echo '    $$dumpfile("$(TOPLEVEL).fst");' >> $@
	echo '    $$dumpvars(0, $(TOPLEVEL));' >> $@
	echo 'end' >> $@
	echo 'endmodule' >> $@

clean::
	@rm -rf iverilog_dump.v
	@rm -rf dump.fst $(TOPLEVEL).fst


================================================
FILE: tb/lfsr_scramble/test_lfsr_scramble.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2023 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

import itertools
import logging
import os

import pytest
import cocotb_test.simulator

import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.regression import TestFactory


class TB:
    def __init__(self, dut):
        self.dut = dut

        self.log = logging.getLogger("cocotb.tb")
        self.log.setLevel(logging.DEBUG)

        cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())

        dut.data_in.setimmediatevalue(0)
        dut.data_in_valid.setimmediatevalue(0)

    async def reset(self):
        self.dut.rst.setimmediatevalue(0)
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)
        self.dut.rst.value = 1
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)
        self.dut.rst.value = 0
        await RisingEdge(self.dut.clk)
        await RisingEdge(self.dut.clk)


def chunks(lst, n, padvalue=None):
    return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)


def scramble_64b66b(data, state=0x3ffffffffffffff):
    data_out = bytearray()
    for d in data:
        b = 0
        for i in range(8):
            if bool(state & (1 << 38)) ^ bool(state & (1 << 57)) ^ bool(d & (1 << i)):
                state = ((state & 0x1ffffffffffffff) << 1) | 1
                b = b | (1 << i)
            else:
                state = (state & 0x1ffffffffffffff) << 1
        data_out.append(b)
    return data_out


async def run_test_scramble(dut, ref_scramble):

    data_width = len(dut.data_in)
    byte_lanes = data_width // 8

    tb = TB(dut)

    await tb.reset()

    block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))

    scr = scramble_64b66b(block)
    scr_iter = iter(chunks(scr, byte_lanes))

    first = True
    for b in chunks(block, byte_lanes):
        dut.data_in.value = int.from_bytes(b, 'little')
        dut.data_in_valid.value = 1
        await RisingEdge(dut.clk)

        val = dut.data_out.value.integer

        if not first:
            ref = int.from_bytes(bytes(next(scr_iter)), 'little')

            tb.log.info("Scrambled: 0x%x (ref: 0x%x)", val, ref)

            assert ref == val

        first = False

    dut.data_in_valid.value = 0

    await RisingEdge(dut.clk)


if cocotb.SIM_NAME:

    # if cocotb.top.LFSR_POLY.value == 0x8000000001:
    if cocotb.top.LFSR_WIDTH == 58:
        factory = TestFactory(run_test_scramble)
        factory.add_option("ref_scramble", [scramble_64b66b])
        factory.generate_tests()


# cocotb-test

tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))


@pytest.mark.parametrize("style", ["AUTO", "LOOP"])
@pytest.mark.parametrize(("lfsr_width", "lfsr_poly", "lfsr_init", "lfsr_config", "reverse", "data_width"), [
            (58,  "58'h8000000001", "58'h3ffffffffffffff", "FIBONACCI", 1, 8),
            (58,  "58'h8000000001", "58'h3ffffffffffffff", "FIBONACCI", 1, 64),
        ])
def test_lfsr_scramble(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, data_width, style):
    dut = "lfsr_scramble"
    module = os.path.splitext(os.path.basename(__file__))[0]
    toplevel = dut

    verilog_sources = [
        os.path.join(rtl_dir, f"{dut}.v"),
        os.path.join(rtl_dir, "lfsr.v"),
    ]

    parameters = {}

    parameters['LFSR_WIDTH'] = lfsr_width
    parameters['LFSR_POLY'] = lfsr_poly
    parameters['LFSR_INIT'] = lfsr_init
    parameters['LFSR_CONFIG'] = f'"{lfsr_config}"'
    parameters['REVERSE'] = reverse
    parameters['DATA_WIDTH'] = data_width
    parameters['STYLE'] = f'"{style}"'

    extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}

    sim_build = os.path.join(tests_dir, "sim_build",
        request.node.name.replace('[', '-').replace(']', ''))

    cocotb_test.simulator.run(
        python_search=[tests_dir],
        verilog_sources=verilog_sources,
        toplevel=toplevel,
        module=module,
        parameters=parameters,
        sim_build=sim_build,
        extra_env=extra_env,
    )


================================================
FILE: tb/test_lfsr_crc32.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os
import zlib

module = 'lfsr'
testbench = 'test_%s_crc32' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def bench():

    # Parameters
    LFSR_WIDTH = 32
    LFSR_POLY = 0x4c11db7
    LFSR_CONFIG = "GALOIS"
    LFSR_FEED_FORWARD = 0
    REVERSE = 1
    DATA_WIDTH = 8
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    data_in = Signal(intbv(0)[DATA_WIDTH:])
    state_in = Signal(intbv(0)[LFSR_WIDTH:])

    # Outputs
    data_out = Signal(intbv(0)[DATA_WIDTH:])
    state_out = Signal(intbv(0)[LFSR_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        data_in=data_in,
        state_in=state_in,
        data_out=data_out,
        state_out=state_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: single word")
        current_test.next = 1

        state_in.next = 0xffffffff
        data_in.next = 0x12
        yield clk.posedge

        print(hex(~state_out.val))
        print(hex(zlib.crc32(b'\x12') & 0xffffffff))

        assert ~state_out.val == zlib.crc32(b'\x12') & 0xffffffff

        yield delay(100)

        yield clk.posedge
        print("test 2: block")
        current_test.next = 2

        block = b'\x11\x22\x33\x44'

        state_in.next = 0xffffffff
        for b in block:
            data_in.next = b
            yield clk.posedge
            state_in.next = state_out.val

        print(hex(~state_out.val))
        print(hex(zlib.crc32(block) & 0xffffffff))

        assert ~state_out.val == zlib.crc32(block) & 0xffffffff

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_crc32.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr_crc32
 */
module test_lfsr_crc32;

// Parameters
parameter LFSR_WIDTH = 32;
parameter LFSR_POLY = 32'h4c11db7;
parameter LFSR_CONFIG = "GALOIS";
parameter LFSR_FEED_FORWARD = 0;
parameter REVERSE = 1;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg [DATA_WIDTH-1:0] data_in = 0;
reg [LFSR_WIDTH-1:0] state_in = 0;

// Outputs
wire [DATA_WIDTH-1:0] data_out = 0;
wire [LFSR_WIDTH-1:0] state_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        data_in,
        state_in
    );
    $to_myhdl(
        data_out,
        state_out
    );

    // dump file
    $dumpfile("test_lfsr_crc32.lxt");
    $dumpvars(0, test_lfsr_crc32);
end

lfsr #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_CONFIG(LFSR_CONFIG),
    .LFSR_FEED_FORWARD(LFSR_FEED_FORWARD),
    .REVERSE(REVERSE),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .data_in(data_in),
    .state_in(state_in),
    .data_out(data_out),
    .state_out(state_out)
);

endmodule


================================================
FILE: tb/test_lfsr_crc_crc32.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os
import zlib

module = 'lfsr_crc'
testbench = 'test_%s_crc32' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def bench():

    # Parameters
    LFSR_WIDTH = 32
    LFSR_POLY = 0x04c11db7
    LFSR_INIT = 0xffffffff
    LFSR_CONFIG = "GALOIS"
    REVERSE = 1
    INVERT = 1
    DATA_WIDTH = 8
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    data_in = Signal(intbv(0)[DATA_WIDTH:])
    data_in_valid = Signal(bool(0))

    # Outputs
    crc_out = Signal(intbv(0)[LFSR_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        data_in=data_in,
        data_in_valid=data_in_valid,
        crc_out=crc_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        print("mark")
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: single word")
        current_test.next = 1

        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge

        data_in.next = 0x12
        data_in_valid.next = 1
        yield clk.posedge
        data_in_valid.next = 0
        yield clk.posedge

        print(hex(crc_out.val))
        print(hex(zlib.crc32(b'\x12') & 0xffffffff))

        assert crc_out.val == zlib.crc32(b'\x12') & 0xffffffff

        yield delay(100)

        yield clk.posedge
        print("test 2: block")
        current_test.next = 2

        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge

        block = b'\x11\x22\x33\x44'

        for b in block:
            data_in.next = b
            data_in_valid.next = 1
            yield clk.posedge
        data_in_valid.next = 0
        yield clk.posedge

        print(hex(crc_out.val))
        print(hex(zlib.crc32(block) & 0xffffffff))

        assert crc_out.val == zlib.crc32(block) & 0xffffffff

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_crc_crc32.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr_crc
 */
module test_lfsr_crc_crc32;

// Parameters
parameter LFSR_WIDTH = 32;
parameter LFSR_POLY = 32'h04c11db7;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "GALOIS";
parameter REVERSE = 1;
parameter INVERT = 1;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;

// Outputs
wire [LFSR_WIDTH-1:0] crc_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        data_in,
        data_in_valid
    );
    $to_myhdl(
        crc_out
    );

    // dump file
    $dumpfile("test_lfsr_crc_crc32.lxt");
    $dumpvars(0, test_lfsr_crc_crc32);
end

lfsr_crc #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_INIT(LFSR_INIT),
    .LFSR_CONFIG(LFSR_CONFIG),
    .REVERSE(REVERSE),
    .INVERT(INVERT),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .clk(clk),
    .rst(rst),
    .data_in(data_in),
    .data_in_valid(data_in_valid),
    .crc_out(crc_out)
);

endmodule


================================================
FILE: tb/test_lfsr_crc_crc32_64.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os
import zlib
import struct

module = 'lfsr_crc'
testbench = 'test_%s_crc32_64' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i+n]

def bench():

    # Parameters
    LFSR_WIDTH = 32
    LFSR_POLY = 0x04c11db7
    LFSR_INIT = 0xffffffff
    LFSR_CONFIG = "GALOIS"
    REVERSE = 1
    INVERT = 1
    DATA_WIDTH = 64
    OUTPUT_WIDTH = LFSR_WIDTH
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    data_in = Signal(intbv(0)[DATA_WIDTH:])
    data_in_valid = Signal(bool(0))

    # Outputs
    crc_out = Signal(intbv(0)[OUTPUT_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        data_in=data_in,
        data_in_valid=data_in_valid,
        crc_out=crc_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: single word")
        current_test.next = 1

        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge

        block = bytes(range(8))

        data_in.next = struct.unpack('<Q', block)[0]
        data_in_valid.next = 1
        yield clk.posedge
        data_in_valid.next = 0
        yield clk.posedge

        print(hex(crc_out.val))
        print(hex(zlib.crc32(block) & 0xffffffff))

        assert crc_out.val == zlib.crc32(block) & 0xffffffff

        yield delay(100)

        yield clk.posedge
        print("test 2: block")
        current_test.next = 2

        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge

        block = bytes(range(64))

        for b in chunks(block, 8):
            data_in.next = struct.unpack('<Q', b)[0]
            data_in_valid.next = 1
            yield clk.posedge
        data_in_valid.next = 0
        yield clk.posedge

        print(hex(crc_out.val))
        print(hex(zlib.crc32(block) & 0xffffffff))

        assert crc_out.val == zlib.crc32(block) & 0xffffffff

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_crc_crc32_64.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr_crc
 */
module test_lfsr_crc_crc32_64;

// Parameters
parameter LFSR_WIDTH = 32;
parameter LFSR_POLY = 32'h04c11db7;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "GALOIS";
parameter REVERSE = 1;
parameter INVERT = 1;
parameter DATA_WIDTH = 64;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;

// Outputs
wire [LFSR_WIDTH-1:0] crc_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        data_in,
        data_in_valid
    );
    $to_myhdl(
        crc_out
    );

    // dump file
    $dumpfile("test_lfsr_crc_crc32_64.lxt");
    $dumpvars(0, test_lfsr_crc_crc32_64);
end

lfsr_crc #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_INIT(LFSR_INIT),
    .LFSR_CONFIG(LFSR_CONFIG),
    .REVERSE(REVERSE),
    .INVERT(INVERT),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .clk(clk),
    .rst(rst),
    .data_in(data_in),
    .data_in_valid(data_in_valid),
    .crc_out(crc_out)
);

endmodule


================================================
FILE: tb/test_lfsr_descramble.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os
import struct

module = 'lfsr_descramble'
testbench = 'test_%s' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def scramble_64b66b(data, state=0x3ffffffffffffff):
    data_out = bytearray()
    for d in data:
        b = 0
        for i in range(8):
            if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):
                state = ((state & 0x1ffffffffffffff) << 1) | 1
                b = b | (1 << i)
            else:
                state = (state & 0x1ffffffffffffff) << 1
        data_out += bytearray([b])
    return data_out

def descramble_64b66b(data, state=0x3ffffffffffffff):
    data_out = bytearray()
    for d in data:
        b = 0
        for i in range(8):
            if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):
                b = b | (1 << i)
            state = (state & 0x1ffffffffffffff) << 1 | bool(d & (1 << i))
        data_out += bytearray([b])
    return data_out

def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i+n]

def bench():

    # Parameters
    LFSR_WIDTH = 58
    LFSR_POLY = 0x8000000001
    LFSR_INIT = 0x3ffffffffffffff
    LFSR_CONFIG = "FIBONACCI"
    REVERSE = 1
    DATA_WIDTH = 8
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    data_in = Signal(intbv(0)[DATA_WIDTH:])
    data_in_valid = Signal(bool(0))

    # Outputs
    data_out = Signal(intbv(0)[DATA_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")
    
    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        data_in=data_in,
        data_in_valid=data_in_valid,
        data_out=data_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: block")
        current_test.next = 1

        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge

        block = bytes(range(256))

        scr = scramble_64b66b(block)

        dscr = descramble_64b66b(scr)

        for i in range(len(scr)):
            data_in.next = scr[i]
            data_in_valid.next = 1
            yield clk.posedge
            if i > 0:
                ref = block[i-1]
                print(hex(data_out))
                print(hex(ref))
                assert data_out == ref
            i += 1
        data_in_valid.next = 0
        yield clk.posedge

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_descramble.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr_descramble
 */
module test_lfsr_descramble;

// Parameters
parameter LFSR_WIDTH = 58;
parameter LFSR_POLY = 58'h8000000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 1;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;

// Outputs
wire [DATA_WIDTH-1:0] data_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        data_in,
        data_in_valid
    );
    $to_myhdl(
        data_out
    );

    // dump file
    $dumpfile("test_lfsr_descramble.lxt");
    $dumpvars(0, test_lfsr_descramble);
end

lfsr_descramble #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_INIT(LFSR_INIT),
    .LFSR_CONFIG(LFSR_CONFIG),
    .REVERSE(REVERSE),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .clk(clk),
    .rst(rst),
    .data_in(data_in),
    .data_in_valid(data_in_valid),
    .data_out(data_out)
);

endmodule


================================================
FILE: tb/test_lfsr_descramble_64.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os
import struct

module = 'lfsr_descramble'
testbench = 'test_%s_64' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def scramble_64b66b(data, state=0x3ffffffffffffff):
    data_out = bytearray()
    for d in data:
        b = 0
        for i in range(8):
            if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):
                state = ((state & 0x1ffffffffffffff) << 1) | 1
                b = b | (1 << i)
            else:
                state = (state & 0x1ffffffffffffff) << 1
        data_out += bytearray([b])
    return data_out

def descramble_64b66b(data, state=0x3ffffffffffffff):
    data_out = bytearray()
    for d in data:
        b = 0
        for i in range(8):
            if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):
                b = b | (1 << i)
            state = (state & 0x1ffffffffffffff) << 1 | bool(d & (1 << i))
        data_out += bytearray([b])
        print(hex(d)+"    "+hex(b))
        print(hex(state))
    return data_out

def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i+n]

def bench():

    # Parameters
    LFSR_WIDTH = 58
    LFSR_POLY = 0x8000000001
    LFSR_INIT = 0x3ffffffffffffff
    LFSR_CONFIG = "FIBONACCI"
    REVERSE = 1
    DATA_WIDTH = 64
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    data_in = Signal(intbv(0)[DATA_WIDTH:])
    data_in_valid = Signal(bool(0))

    # Outputs
    data_out = Signal(intbv(0)[DATA_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")
    
    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        data_in=data_in,
        data_in_valid=data_in_valid,
        data_out=data_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: block")
        current_test.next = 1

        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge

        block = bytes(range(256))

        scr = scramble_64b66b(block)

        dscr = descramble_64b66b(scr)

        for i in range(0, len(scr), 8):
            data_in.next = struct.unpack('<Q', scr[i:i+8])[0]
            data_in_valid.next = 1
            yield clk.posedge
            if i > 0:
                ref = struct.unpack('<Q', block[i-8:i])[0]
                print(hex(data_out))
                print(hex(ref))
                assert data_out == ref
            i += 8
        data_in_valid.next = 0
        yield clk.posedge

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_descramble_64.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr_descramble
 */
module test_lfsr_descramble_64;

// Parameters
parameter LFSR_WIDTH = 58;
parameter LFSR_POLY = 58'h8000000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 1;
parameter DATA_WIDTH = 64;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;

// Outputs
wire [DATA_WIDTH-1:0] data_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        data_in,
        data_in_valid
    );
    $to_myhdl(
        data_out
    );

    // dump file
    $dumpfile("test_lfsr_descramble_64.lxt");
    $dumpvars(0, test_lfsr_descramble_64);
end

lfsr_descramble #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_INIT(LFSR_INIT),
    .LFSR_CONFIG(LFSR_CONFIG),
    .REVERSE(REVERSE),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .clk(clk),
    .rst(rst),
    .data_in(data_in),
    .data_in_valid(data_in_valid),
    .data_out(data_out)
);

endmodule


================================================
FILE: tb/test_lfsr_prbs31.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os

module = 'lfsr'
testbench = 'test_%s_prbs31' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def prbs31(state = 0x7fffffff):
    while True:
        for i in range(8):
            if bool(state & 0x08000000) ^ bool(state & 0x40000000):
                state = ((state & 0x3fffffff) << 1) | 1
            else:
                state = (state & 0x3fffffff) << 1
        yield state & 0xff

def bench():

    # Parameters
    LFSR_WIDTH = 31
    LFSR_POLY = 0x10000001
    LFSR_CONFIG = "FIBONACCI"
    LFSR_FEED_FORWARD = 0
    REVERSE = 0
    DATA_WIDTH = 8
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    data_in = Signal(intbv(0)[DATA_WIDTH:])
    state_in = Signal(intbv(0)[LFSR_WIDTH:])

    # Outputs
    data_out = Signal(intbv(0)[DATA_WIDTH:])
    state_out = Signal(intbv(0)[LFSR_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        data_in=data_in,
        state_in=state_in,
        data_out=data_out,
        state_out=state_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: test PRBS31")
        current_test.next = 1

        state_in.next = 0x7fffffff
        data_in.next = 0
        gen = prbs31()

        for i in range(512):

            yield clk.posedge

            ref = next(gen)
            val = data_out.val

            print((ref, val))

            assert ref == val

            state_in.next = state_out.val

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_prbs31.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr
 */
module test_lfsr_prbs31;

// Parameters
parameter LFSR_WIDTH = 31;
parameter LFSR_POLY = 31'h10000001;
parameter LFSR_CONFIG = "FIBONACCI";
parameter LFSR_FEED_FORWARD = 0;
parameter REVERSE = 0;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg [DATA_WIDTH-1:0] data_in = 0;
reg [LFSR_WIDTH-1:0] state_in = 0;

// Outputs
wire [DATA_WIDTH-1:0] data_out;
wire [LFSR_WIDTH-1:0] state_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        data_in,
        state_in
    );
    $to_myhdl(
        data_out,
        state_out
    );

    // dump file
    $dumpfile("test_lfsr_prbs31.lxt");
    $dumpvars(0, test_lfsr_prbs31);
end

lfsr #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_CONFIG(LFSR_CONFIG),
    .LFSR_FEED_FORWARD(LFSR_FEED_FORWARD),
    .REVERSE(REVERSE),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .data_in(data_in),
    .state_in(state_in),
    .data_out(data_out),
    .state_out(state_out)
);

endmodule


================================================
FILE: tb/test_lfsr_prbs9.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os

module = 'lfsr'
testbench = 'test_%s_prbs9' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def prbs9(state = 0x1ff):
    while True:
        for i in range(8):
            if bool(state & 0x10) ^ bool(state & 0x100):
                state = ((state & 0xff) << 1) | 1
            else:
                state = (state & 0xff) << 1
        yield state & 0xff

def bench():

    # Parameters
    LFSR_WIDTH = 9
    LFSR_POLY = 0x021
    LFSR_CONFIG = "FIBONACCI"
    LFSR_FEED_FORWARD = 0
    REVERSE = 0
    DATA_WIDTH = 8
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    data_in = Signal(intbv(0)[DATA_WIDTH:])
    state_in = Signal(intbv(0)[LFSR_WIDTH:])

    # Outputs
    data_out = Signal(intbv(0)[DATA_WIDTH:])
    state_out = Signal(intbv(0)[LFSR_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        data_in=data_in,
        state_in=state_in,
        data_out=data_out,
        state_out=state_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: test PRBS9")
        current_test.next = 1

        state_in.next = 0x1ff
        data_in.next = 0
        gen = prbs9()

        for i in range(512):

            yield clk.posedge

            ref = next(gen)
            val = data_out.val

            print((ref, val))

            assert ref == val

            state_in.next = state_out.val

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_prbs9.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr
 */
module test_lfsr_prbs9;

// Parameters
parameter LFSR_WIDTH = 9;
parameter LFSR_POLY = 9'h021;
parameter LFSR_CONFIG = "FIBONACCI";
parameter LFSR_FEED_FORWARD = 0;
parameter REVERSE = 0;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg [DATA_WIDTH-1:0] data_in = 0;
reg [LFSR_WIDTH-1:0] state_in = 0;

// Outputs
wire [DATA_WIDTH-1:0] data_out;
wire [LFSR_WIDTH-1:0] state_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        data_in,
        state_in
    );
    $to_myhdl(
        data_out,
        state_out
    );

    // dump file
    $dumpfile("test_lfsr_prbs9.lxt");
    $dumpvars(0, test_lfsr_prbs9);
end

lfsr #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_CONFIG(LFSR_CONFIG),
    .LFSR_FEED_FORWARD(LFSR_FEED_FORWARD),
    .REVERSE(REVERSE),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .data_in(data_in),
    .state_in(state_in),
    .data_out(data_out),
    .state_out(state_out)
);

endmodule


================================================
FILE: tb/test_lfsr_prbs_check_prbs31.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os

module = 'lfsr_prbs_check'
testbench = 'test_%s_prbs31' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def prbs31(state = 0x7fffffff):
    while True:
        for i in range(8):
            if bool(state & 0x08000000) ^ bool(state & 0x40000000):
                state = ((state & 0x3fffffff) << 1) | 1
            else:
                state = (state & 0x3fffffff) << 1
        yield ~state & 0xff

def bench():

    # Parameters
    LFSR_WIDTH = 9
    LFSR_POLY = 0x021
    LFSR_INIT = 0x1ff
    LFSR_CONFIG = "FIBONACCI"
    REVERSE = 0
    INVERT = 1
    DATA_WIDTH = 8
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    data_in = Signal(intbv(0)[DATA_WIDTH:])
    data_in_valid = Signal(bool(0))

    # Outputs
    data_out = Signal(intbv(0)[DATA_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")
    
    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        data_in=data_in,
        data_in_valid=data_in_valid,
        data_out=data_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: test PRBS31")
        current_test.next = 1

        gen = prbs31()

        data_in.next = next(gen)
        data_in_valid.next = 1
        yield clk.posedge

        for i in range(512):

            data_in.next = next(gen)
            data_in_valid.next = 1

            val = data_out.val

            print(val)

            assert val == 0

            yield clk.posedge

        data_in_valid.next = 0

        yield delay(100)

        yield clk.posedge
        print("test 2: single error")
        current_test.next = 2

        gen = prbs31()

        for i in range(16):
            data_in.next = next(gen)
            data_in_valid.next = 1
            yield clk.posedge

        data_in.next = next(gen) ^ 0x08
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x00

        data_in.next = next(gen)
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x08

        data_in.next = next(gen)
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x00

        data_in.next = next(gen)
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x00

        data_in.next = next(gen)
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x00

        data_in.next = next(gen)
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x90

        data_in.next = next(gen)
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x00

        yield clk.posedge

        data_in_valid.next = 0

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_prbs_check_prbs31.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr_prbs_check
 */
module test_lfsr_prbs_check_prbs31;

// Parameters
parameter LFSR_WIDTH = 31;
parameter LFSR_POLY = 31'h10000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 0;
parameter INVERT = 1;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;

// Outputs
wire [DATA_WIDTH-1:0] data_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        data_in,
        data_in_valid
    );
    $to_myhdl(
        data_out
    );

    // dump file
    $dumpfile("test_lfsr_prbs_check_prbs31.lxt");
    $dumpvars(0, test_lfsr_prbs_check_prbs31);
end

lfsr_prbs_check #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_INIT(LFSR_INIT),
    .LFSR_CONFIG(LFSR_CONFIG),
    .REVERSE(REVERSE),
    .INVERT(INVERT),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .clk(clk),
    .rst(rst),
    .data_in(data_in),
    .data_in_valid(data_in_valid),
    .data_out(data_out)
);

endmodule


================================================
FILE: tb/test_lfsr_prbs_check_prbs31_64.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os
import struct

module = 'lfsr_prbs_check'
testbench = 'test_%s_prbs31_64' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def prbs31(state = 0x7fffffff):
    while True:
        for i in range(8):
            if bool(state & 0x08000000) ^ bool(state & 0x40000000):
                state = ((state & 0x3fffffff) << 1) | 1
            else:
                state = (state & 0x3fffffff) << 1
        yield ~state & 0xff

def bench():

    # Parameters
    LFSR_WIDTH = 9
    LFSR_POLY = 0x021
    LFSR_INIT = 0x1ff
    LFSR_CONFIG = "FIBONACCI"
    REVERSE = 0
    INVERT = 1
    DATA_WIDTH = 64
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    data_in = Signal(intbv(0)[DATA_WIDTH:])
    data_in_valid = Signal(bool(0))

    # Outputs
    data_out = Signal(intbv(0)[DATA_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        data_in=data_in,
        data_in_valid=data_in_valid,
        data_out=data_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: test PRBS31")
        current_test.next = 1

        gen = prbs31()

        data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]
        data_in_valid.next = 1
        yield clk.posedge

        for i in range(512):

            data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]
            data_in_valid.next = 1

            val = data_out.val

            print(val)

            assert val == 0

            yield clk.posedge

        data_in_valid.next = 0

        yield delay(100)

        yield clk.posedge
        print("test 2: single error")
        current_test.next = 2

        gen = prbs31()

        for i in range(16):
            data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]
            data_in_valid.next = 1
            yield clk.posedge

        data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0] ^ 0x0001000000000000
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x0000000000000000

        data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x0001000000120000

        data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x0000000000000000

        data_in_valid.next = 0

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_prbs_check_prbs31_64.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr_prbs_check
 */
module test_lfsr_prbs_check_prbs31_64;

// Parameters
parameter LFSR_WIDTH = 31;
parameter LFSR_POLY = 31'h10000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 0;
parameter INVERT = 1;
parameter DATA_WIDTH = 64;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;

// Outputs
wire [DATA_WIDTH-1:0] data_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        data_in,
        data_in_valid
    );
    $to_myhdl(
        data_out
    );

    // dump file
    $dumpfile("test_lfsr_prbs_check_prbs31_64.lxt");
    $dumpvars(0, test_lfsr_prbs_check_prbs31_64);
end

lfsr_prbs_check #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_INIT(LFSR_INIT),
    .LFSR_CONFIG(LFSR_CONFIG),
    .REVERSE(REVERSE),
    .INVERT(INVERT),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .clk(clk),
    .rst(rst),
    .data_in(data_in),
    .data_in_valid(data_in_valid),
    .data_out(data_out)
);

endmodule


================================================
FILE: tb/test_lfsr_prbs_check_prbs9.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os

module = 'lfsr_prbs_check'
testbench = 'test_%s_prbs9' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def prbs9(state = 0x1ff):
    while True:
        for i in range(8):
            if bool(state & 0x10) ^ bool(state & 0x100):
                state = ((state & 0xff) << 1) | 1
            else:
                state = (state & 0xff) << 1
        yield state & 0xff

def bench():

    # Parameters
    LFSR_WIDTH = 9
    LFSR_POLY = 0x021
    LFSR_INIT = 0x1ff
    LFSR_CONFIG = "FIBONACCI"
    REVERSE = 0
    INVERT = 0
    DATA_WIDTH = 8
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    data_in = Signal(intbv(0)[DATA_WIDTH:])
    data_in_valid = Signal(bool(0))

    # Outputs
    data_out = Signal(intbv(0)[DATA_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        data_in=data_in,
        data_in_valid=data_in_valid,
        data_out=data_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: test PRBS9")
        current_test.next = 1

        gen = prbs9()

        data_in.next = next(gen)
        data_in_valid.next = 1
        yield clk.posedge

        for i in range(512):

            data_in.next = next(gen)
            data_in_valid.next = 1

            val = data_out.val

            print(val)

            assert val == 0

            yield clk.posedge

        data_in_valid.next = 0

        yield delay(100)

        yield clk.posedge
        print("test 2: single error")
        current_test.next = 2

        gen = prbs9()

        for i in range(16):
            data_in.next = next(gen)
            data_in_valid.next = 1
            yield clk.posedge

        data_in.next = next(gen) ^ 0x08
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x00

        data_in.next = next(gen)
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x08

        data_in.next = next(gen)
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x44

        data_in.next = next(gen)
        data_in_valid.next = 1
        yield clk.posedge

        val = data_out.val

        print(val)

        assert val == 0x00

        yield clk.posedge

        data_in_valid.next = 0

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_prbs_check_prbs9.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr_prbs_check
 */
module test_lfsr_prbs_check_prbs9;

// Parameters
parameter LFSR_WIDTH = 9;
parameter LFSR_POLY = 9'h021;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 0;
parameter INVERT = 0;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;

// Outputs
wire [DATA_WIDTH-1:0] data_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        data_in,
        data_in_valid
    );
    $to_myhdl(
        data_out
    );

    // dump file
    $dumpfile("test_lfsr_prbs_check_prbs9.lxt");
    $dumpvars(0, test_lfsr_prbs_check_prbs9);
end

lfsr_prbs_check #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_INIT(LFSR_INIT),
    .LFSR_CONFIG(LFSR_CONFIG),
    .REVERSE(REVERSE),
    .INVERT(INVERT),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .clk(clk),
    .rst(rst),
    .data_in(data_in),
    .data_in_valid(data_in_valid),
    .data_out(data_out)
);

endmodule


================================================
FILE: tb/test_lfsr_prbs_gen_prbs31.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os

module = 'lfsr_prbs_gen'
testbench = 'test_%s_prbs31' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def prbs31(state = 0x7fffffff):
    while True:
        for i in range(8):
            if bool(state & 0x08000000) ^ bool(state & 0x40000000):
                state = ((state & 0x3fffffff) << 1) | 1
            else:
                state = (state & 0x3fffffff) << 1
        yield ~state & 0xff

def bench():

    # Parameters
    LFSR_WIDTH = 31
    LFSR_POLY = 0x10000001
    LFSR_INIT = 0x7fffffff
    LFSR_CONFIG = "FIBONACCI"
    REVERSE = 0
    INVERT = 1
    DATA_WIDTH = 8
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    enable = Signal(bool(0))

    # Outputs
    data_out = Signal(intbv(0)[DATA_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        enable=enable,
        data_out=data_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: test PRBS31")
        current_test.next = 1

        gen = prbs31()

        enable.next = 1
        yield clk.posedge
        yield clk.posedge
        enable.next = 0

        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge

        enable.next = 1
        yield clk.posedge

        for i in range(512):

            ref = next(gen)
            val = data_out.val

            print((ref, val))

            assert ref == val

            yield clk.posedge

        enable.next = 0

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_prbs_gen_prbs31.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr_prbs_gen
 */
module test_lfsr_prbs_gen_prbs31;

// Parameters
parameter LFSR_WIDTH = 31;
parameter LFSR_POLY = 31'h10000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 0;
parameter INVERT = 1;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg enable = 0;

// Outputs
wire [DATA_WIDTH-1:0] data_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        enable
    );
    $to_myhdl(
        data_out
    );

    // dump file
    $dumpfile("test_lfsr_prbs_gen_prbs31.lxt");
    $dumpvars(0, test_lfsr_prbs_gen_prbs31);
end

lfsr_prbs_gen #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_INIT(LFSR_INIT),
    .LFSR_CONFIG(LFSR_CONFIG),
    .REVERSE(REVERSE),
    .INVERT(INVERT),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .clk(clk),
    .rst(rst),
    .enable(enable),
    .data_out(data_out)
);

endmodule


================================================
FILE: tb/test_lfsr_prbs_gen_prbs31_64.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os
import struct

module = 'lfsr_prbs_gen'
testbench = 'test_%s_prbs31_64' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def prbs31(state = 0x7fffffff):
    while True:
        for i in range(8):
            if bool(state & 0x08000000) ^ bool(state & 0x40000000):
                state = ((state & 0x3fffffff) << 1) | 1
            else:
                state = (state & 0x3fffffff) << 1
        yield ~state & 0xff

def bench():

    # Parameters
    LFSR_WIDTH = 31
    LFSR_POLY = 0x10000001
    LFSR_INIT = 0x7fffffff
    LFSR_CONFIG = "FIBONACCI"
    REVERSE = 0
    INVERT = 1
    DATA_WIDTH = 64
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    enable = Signal(bool(0))

    # Outputs
    data_out = Signal(intbv(0)[DATA_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        enable=enable,
        data_out=data_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: test PRBS31")
        current_test.next = 1

        gen = prbs31()

        enable.next = 1
        yield clk.posedge
        yield clk.posedge
        enable.next = 0

        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge

        enable.next = 1
        yield clk.posedge

        for i in range(512):

            #ref = next(gen)
            ref = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]
            val = data_out.val

            print((ref, val))

            assert ref == val

            yield clk.posedge

        enable.next = 0

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_prbs_gen_prbs31_64.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr_prbs_gen
 */
module test_lfsr_prbs_gen_prbs31_64;

// Parameters
parameter LFSR_WIDTH = 31;
parameter LFSR_POLY = 31'h10000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 0;
parameter INVERT = 1;
parameter DATA_WIDTH = 64;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg enable = 0;

// Outputs
wire [DATA_WIDTH-1:0] data_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        enable
    );
    $to_myhdl(
        data_out
    );

    // dump file
    $dumpfile("test_lfsr_prbs_gen_prbs31_64.lxt");
    $dumpvars(0, test_lfsr_prbs_gen_prbs31_64);
end

lfsr_prbs_gen #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_INIT(LFSR_INIT),
    .LFSR_CONFIG(LFSR_CONFIG),
    .REVERSE(REVERSE),
    .INVERT(INVERT),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .clk(clk),
    .rst(rst),
    .enable(enable),
    .data_out(data_out)
);

endmodule


================================================
FILE: tb/test_lfsr_prbs_gen_prbs9.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os

module = 'lfsr_prbs_gen'
testbench = 'test_%s_prbs9' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def prbs9(state = 0x1ff):
    while True:
        for i in range(8):
            if bool(state & 0x10) ^ bool(state & 0x100):
                state = ((state & 0xff) << 1) | 1
            else:
                state = (state & 0xff) << 1
        yield state & 0xff

def bench():

    # Parameters
    LFSR_WIDTH = 9
    LFSR_POLY = 0x021
    LFSR_INIT = 0x1ff
    LFSR_CONFIG = "FIBONACCI"
    REVERSE = 0
    INVERT = 0
    DATA_WIDTH = 8
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    enable = Signal(bool(0))

    # Outputs
    data_out = Signal(intbv(0)[DATA_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        enable=enable,
        data_out=data_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: test PRBS9")
        current_test.next = 1

        gen = prbs9()

        enable.next = 1
        yield clk.posedge
        yield clk.posedge
        enable.next = 0

        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge

        enable.next = 1
        yield clk.posedge

        for i in range(512):

            ref = next(gen)
            val = data_out.val

            print((ref, val))

            assert ref == val

            yield clk.posedge

        enable.next = 0

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_prbs_gen_prbs9.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr_prbs_gen
 */
module test_lfsr_prbs_gen_prbs9;

// Parameters
parameter LFSR_WIDTH = 9;
parameter LFSR_POLY = 9'h021;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 0;
parameter INVERT = 0;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg enable = 0;

// Outputs
wire [DATA_WIDTH-1:0] data_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        enable
    );
    $to_myhdl(
        data_out
    );

    // dump file
    $dumpfile("test_lfsr_prbs_gen_prbs9.lxt");
    $dumpvars(0, test_lfsr_prbs_gen_prbs9);
end

lfsr_prbs_gen #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_INIT(LFSR_INIT),
    .LFSR_CONFIG(LFSR_CONFIG),
    .REVERSE(REVERSE),
    .INVERT(INVERT),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .clk(clk),
    .rst(rst),
    .enable(enable),
    .data_out(data_out)
);

endmodule


================================================
FILE: tb/test_lfsr_scramble.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os
import struct

module = 'lfsr_scramble'
testbench = 'test_%s' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def scramble_64b66b(data, state=0x3ffffffffffffff):
    data_out = bytearray()
    for d in data:
        b = 0
        for i in range(8):
            if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):
                state = ((state & 0x1ffffffffffffff) << 1) | 1
                b = b | (1 << i)
            else:
                state = (state & 0x1ffffffffffffff) << 1
        data_out += bytearray([b])
    return data_out

def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i+n]

def bench():

    # Parameters
    LFSR_WIDTH = 58
    LFSR_POLY = 0x8000000001
    LFSR_INIT = 0x3ffffffffffffff
    LFSR_CONFIG = "FIBONACCI"
    REVERSE = 1
    DATA_WIDTH = 8
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    data_in = Signal(intbv(0)[DATA_WIDTH:])
    data_in_valid = Signal(bool(0))

    # Outputs
    data_out = Signal(intbv(0)[DATA_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        data_in=data_in,
        data_in_valid=data_in_valid,
        data_out=data_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: block")
        current_test.next = 1

        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge

        block = bytes(range(256))

        scr = scramble_64b66b(block)

        for i in range(len(block)):
            data_in.next = block[i]
            data_in_valid.next = 1
            yield clk.posedge
            if i > 0:
                ref = scr[i-1]
                print(hex(data_out))
                print(hex(ref))
                assert data_out == ref
            i += 1
        data_in_valid.next = 0
        yield clk.posedge

        yield delay(100)

        raise StopSimulation

    return instances()

def test_bench():
    sim = Simulation(bench())
    sim.run()

if __name__ == '__main__':
    print("Running test...")
    test_bench()


================================================
FILE: tb/test_lfsr_scramble.v
================================================
/*

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

// Language: Verilog 2001

`timescale 1ns / 1ps

/*
 * Testbench for lfsr_scramble
 */
module test_lfsr_scramble;

// Parameters
parameter LFSR_WIDTH = 58;
parameter LFSR_POLY = 58'h8000000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 1;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";

// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;

reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;

// Outputs
wire [DATA_WIDTH-1:0] data_out;

initial begin
    // myhdl integration
    $from_myhdl(
        clk,
        rst,
        current_test,
        data_in,
        data_in_valid
    );
    $to_myhdl(
        data_out
    );

    // dump file
    $dumpfile("test_lfsr_scramble.lxt");
    $dumpvars(0, test_lfsr_scramble);
end

lfsr_scramble #(
    .LFSR_WIDTH(LFSR_WIDTH),
    .LFSR_POLY(LFSR_POLY),
    .LFSR_INIT(LFSR_INIT),
    .LFSR_CONFIG(LFSR_CONFIG),
    .REVERSE(REVERSE),
    .DATA_WIDTH(DATA_WIDTH),
    .STYLE(STYLE)
)
UUT (
    .clk(clk),
    .rst(rst),
    .data_in(data_in),
    .data_in_valid(data_in_valid),
    .data_out(data_out)
);

endmodule


================================================
FILE: tb/test_lfsr_scramble_64.py
================================================
#!/usr/bin/env python
"""

Copyright (c) 2016 Alex Forencich

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

"""

from myhdl import *
import os
import struct

module = 'lfsr_scramble'
testbench = 'test_%s_64' % module

srcs = []

srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)

src = ' '.join(srcs)

build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)

def scramble_64b66b(data, state=0x3ffffffffffffff):
    data_out = bytearray()
    for d in data:
        b = 0
        for i in range(8):
            if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):
                state = ((state & 0x1ffffffffffffff) << 1) | 1
                b = b | (1 << i)
            else:
                state = (state & 0x1ffffffffffffff) << 1
        data_out += bytearray([b])
    return data_out

def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i+n]

def bench():

    # Parameters
    LFSR_WIDTH = 58
    LFSR_POLY = 0x8000000001
    LFSR_INIT = 0x3ffffffffffffff
    LFSR_CONFIG = "FIBONACCI"
    REVERSE = 1
    DATA_WIDTH = 64
    STYLE = "AUTO"

    # Inputs
    clk = Signal(bool(0))
    rst = Signal(bool(0))
    current_test = Signal(intbv(0)[8:])

    data_in = Signal(intbv(0)[DATA_WIDTH:])
    data_in_valid = Signal(bool(0))

    # Outputs
    data_out = Signal(intbv(0)[DATA_WIDTH:])

    # DUT
    if os.system(build_cmd):
        raise Exception("Error running build command")

    dut = Cosimulation(
        "vvp -m myhdl %s.vvp -lxt2" % testbench,
        clk=clk,
        rst=rst,
        current_test=current_test,
        data_in=data_in,
        data_in_valid=data_in_valid,
        data_out=data_out
    )

    @always(delay(4))
    def clkgen():
        clk.next = not clk

    @instance
    def check():
        yield delay(100)
        yield clk.posedge
        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge
        yield delay(100)
        yield clk.posedge

        # testbench stimulus

        yield clk.posedge
        print("test 1: block")
        current_test.next = 1

        rst.next = 1
        yield clk.posedge
        rst.next = 0
        yield clk.posedge

        block = bytes(range(256))

        scr = scramble_64b66b(block)

        for i in range(0, len(block), 8):
            data_in.next = struct.unpack('<Q', block[i:i+8])[0]
            data_in_valid.next = 1
            yield clk.posedge
            if i > 0:
                ref = struct.unpack('<Q', 
Download .txt
gitextract_d0iwnulu/

├── .github/
│   └── workflows/
│       └── regression-tests.yml
├── .gitignore
├── AUTHORS
├── COPYING
├── README.md
├── rtl/
│   ├── lfsr.v
│   ├── lfsr_crc.v
│   ├── lfsr_descramble.v
│   ├── lfsr_prbs_check.v
│   ├── lfsr_prbs_gen.v
│   └── lfsr_scramble.v
├── tb/
│   ├── lfsr/
│   │   ├── Makefile
│   │   └── test_lfsr.py
│   ├── lfsr_crc/
│   │   ├── Makefile
│   │   └── test_lfsr_crc.py
│   ├── lfsr_descramble/
│   │   ├── Makefile
│   │   └── test_lfsr_descramble.py
│   ├── lfsr_prbs_check/
│   │   ├── Makefile
│   │   └── test_lfsr_prbs_check.py
│   ├── lfsr_prbs_gen/
│   │   ├── Makefile
│   │   └── test_lfsr_prbs_gen.py
│   ├── lfsr_scramble/
│   │   ├── Makefile
│   │   └── test_lfsr_scramble.py
│   ├── test_lfsr_crc32.py
│   ├── test_lfsr_crc32.v
│   ├── test_lfsr_crc_crc32.py
│   ├── test_lfsr_crc_crc32.v
│   ├── test_lfsr_crc_crc32_64.py
│   ├── test_lfsr_crc_crc32_64.v
│   ├── test_lfsr_descramble.py
│   ├── test_lfsr_descramble.v
│   ├── test_lfsr_descramble_64.py
│   ├── test_lfsr_descramble_64.v
│   ├── test_lfsr_prbs31.py
│   ├── test_lfsr_prbs31.v
│   ├── test_lfsr_prbs9.py
│   ├── test_lfsr_prbs9.v
│   ├── test_lfsr_prbs_check_prbs31.py
│   ├── test_lfsr_prbs_check_prbs31.v
│   ├── test_lfsr_prbs_check_prbs31_64.py
│   ├── test_lfsr_prbs_check_prbs31_64.v
│   ├── test_lfsr_prbs_check_prbs9.py
│   ├── test_lfsr_prbs_check_prbs9.v
│   ├── test_lfsr_prbs_gen_prbs31.py
│   ├── test_lfsr_prbs_gen_prbs31.v
│   ├── test_lfsr_prbs_gen_prbs31_64.py
│   ├── test_lfsr_prbs_gen_prbs31_64.v
│   ├── test_lfsr_prbs_gen_prbs9.py
│   ├── test_lfsr_prbs_gen_prbs9.v
│   ├── test_lfsr_scramble.py
│   ├── test_lfsr_scramble.v
│   ├── test_lfsr_scramble_64.py
│   └── test_lfsr_scramble_64.v
└── tox.ini
Download .txt
SYMBOL INDEX (99 symbols across 21 files)

FILE: tb/lfsr/test_lfsr.py
  class TB (line 39) | class TB:
    method __init__ (line 40) | def __init__(self, dut):
  function chunks (line 50) | def chunks(lst, n, padvalue=None):
  function crc32 (line 54) | def crc32(data):
  function crc32c (line 58) | def crc32c(data, crc=0xffffffff, poly=0x82f63b78):
  function run_test_crc (line 69) | async def run_test_crc(dut, ref_crc):
  function prbs9 (line 114) | def prbs9(state=0x1ff):
  function prbs31 (line 124) | def prbs31(state=0x7fffffff):
  function run_test_prbs (line 134) | async def run_test_prbs(dut, ref_prbs):
  function test_lfsr (line 206) | def test_lfsr(request, lfsr_width, lfsr_poly, lfsr_config, reverse, data...

FILE: tb/lfsr_crc/test_lfsr_crc.py
  class TB (line 40) | class TB:
    method __init__ (line 41) | def __init__(self, dut):
    method reset (line 52) | async def reset(self):
  function chunks (line 64) | def chunks(lst, n, padvalue=None):
  function crc32 (line 68) | def crc32(data):
  function crc32c (line 72) | def crc32c(data, crc=0xffffffff, poly=0x82f63b78):
  function run_test_crc (line 83) | async def run_test_crc(dut, ref_crc):
  function test_lfsr_crc (line 155) | def test_lfsr_crc(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config...

FILE: tb/lfsr_descramble/test_lfsr_descramble.py
  class TB (line 39) | class TB:
    method __init__ (line 40) | def __init__(self, dut):
    method reset (line 51) | async def reset(self):
  function chunks (line 63) | def chunks(lst, n, padvalue=None):
  function scramble_64b66b (line 67) | def scramble_64b66b(data, state=0x3ffffffffffffff):
  function descramble_64b66b (line 81) | def descramble_64b66b(data, state=0x3ffffffffffffff):
  function run_test_descramble (line 93) | async def run_test_descramble(dut, ref_scramble):
  function test_lfsr_descramble (line 154) | def test_lfsr_descramble(request, lfsr_width, lfsr_poly, lfsr_init, lfsr...

FILE: tb/lfsr_prbs_check/test_lfsr_prbs_check.py
  class TB (line 39) | class TB:
    method __init__ (line 40) | def __init__(self, dut):
    method reset (line 51) | async def reset(self):
  function chunks (line 63) | def chunks(lst, n, padvalue=None):
  function prbs9 (line 67) | def prbs9(state=0x1ff):
  function prbs31 (line 77) | def prbs31(state=0x7fffffff):
  function count_set_bits (line 87) | def count_set_bits(n):
  function run_test_prbs (line 95) | async def run_test_prbs(dut, ref_prbs):
  function test_lfsr_prbs_check (line 189) | def test_lfsr_prbs_check(request, lfsr_width, lfsr_poly, lfsr_init, lfsr...

FILE: tb/lfsr_prbs_gen/test_lfsr_prbs_gen.py
  class TB (line 39) | class TB:
    method __init__ (line 40) | def __init__(self, dut):
    method reset (line 50) | async def reset(self):
  function chunks (line 62) | def chunks(lst, n, padvalue=None):
  function prbs9 (line 66) | def prbs9(state=0x1ff):
  function prbs31 (line 76) | def prbs31(state=0x7fffffff):
  function run_test_prbs (line 86) | async def run_test_prbs(dut, ref_prbs):
  function test_lfsr_prbs_gen (line 137) | def test_lfsr_prbs_gen(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_c...

FILE: tb/lfsr_scramble/test_lfsr_scramble.py
  class TB (line 39) | class TB:
    method __init__ (line 40) | def __init__(self, dut):
    method reset (line 51) | async def reset(self):
  function chunks (line 63) | def chunks(lst, n, padvalue=None):
  function scramble_64b66b (line 67) | def scramble_64b66b(data, state=0x3ffffffffffffff):
  function run_test_scramble (line 81) | async def run_test_scramble(dut, ref_scramble):
  function test_lfsr_scramble (line 137) | def test_lfsr_scramble(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_c...

FILE: tb/test_lfsr_crc32.py
  function bench (line 42) | def bench():
  function test_bench (line 135) | def test_bench():

FILE: tb/test_lfsr_crc_crc32.py
  function bench (line 43) | def bench():
  function test_bench (line 149) | def test_bench():

FILE: tb/test_lfsr_crc_crc32_64.py
  function chunks (line 44) | def chunks(l, n):
  function bench (line 49) | def bench():
  function test_bench (line 157) | def test_bench():

FILE: tb/test_lfsr_descramble.py
  function scramble_64b66b (line 43) | def scramble_64b66b(data, state=0x3ffffffffffffff):
  function descramble_64b66b (line 56) | def descramble_64b66b(data, state=0x3ffffffffffffff):
  function chunks (line 67) | def chunks(l, n):
  function bench (line 72) | def bench():
  function test_bench (line 159) | def test_bench():

FILE: tb/test_lfsr_descramble_64.py
  function scramble_64b66b (line 43) | def scramble_64b66b(data, state=0x3ffffffffffffff):
  function descramble_64b66b (line 56) | def descramble_64b66b(data, state=0x3ffffffffffffff):
  function chunks (line 69) | def chunks(l, n):
  function bench (line 74) | def bench():
  function test_bench (line 161) | def test_bench():

FILE: tb/test_lfsr_prbs31.py
  function prbs31 (line 41) | def prbs31(state = 0x7fffffff):
  function bench (line 50) | def bench():
  function test_bench (line 132) | def test_bench():

FILE: tb/test_lfsr_prbs9.py
  function prbs9 (line 41) | def prbs9(state = 0x1ff):
  function bench (line 50) | def bench():
  function test_bench (line 132) | def test_bench():

FILE: tb/test_lfsr_prbs_check_prbs31.py
  function prbs31 (line 42) | def prbs31(state = 0x7fffffff):
  function bench (line 51) | def bench():
  function test_bench (line 223) | def test_bench():

FILE: tb/test_lfsr_prbs_check_prbs31_64.py
  function prbs31 (line 43) | def prbs31(state = 0x7fffffff):
  function bench (line 52) | def bench():
  function test_bench (line 182) | def test_bench():

FILE: tb/test_lfsr_prbs_check_prbs9.py
  function prbs9 (line 42) | def prbs9(state = 0x1ff):
  function bench (line 51) | def bench():
  function test_bench (line 193) | def test_bench():

FILE: tb/test_lfsr_prbs_gen_prbs31.py
  function prbs31 (line 42) | def prbs31(state = 0x7fffffff):
  function bench (line 51) | def bench():
  function test_bench (line 141) | def test_bench():

FILE: tb/test_lfsr_prbs_gen_prbs31_64.py
  function prbs31 (line 43) | def prbs31(state = 0x7fffffff):
  function bench (line 52) | def bench():
  function test_bench (line 143) | def test_bench():

FILE: tb/test_lfsr_prbs_gen_prbs9.py
  function prbs9 (line 42) | def prbs9(state = 0x1ff):
  function bench (line 51) | def bench():
  function test_bench (line 141) | def test_bench():

FILE: tb/test_lfsr_scramble.py
  function scramble_64b66b (line 43) | def scramble_64b66b(data, state=0x3ffffffffffffff):
  function chunks (line 56) | def chunks(l, n):
  function bench (line 61) | def bench():
  function test_bench (line 146) | def test_bench():

FILE: tb/test_lfsr_scramble_64.py
  function scramble_64b66b (line 43) | def scramble_64b66b(data, state=0x3ffffffffffffff):
  function chunks (line 56) | def chunks(l, n):
  function bench (line 61) | def bench():
  function test_bench (line 146) | def test_bench():
Condensed preview — 54 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (208K chars).
[
  {
    "path": ".github/workflows/regression-tests.yml",
    "chars": 825,
    "preview": "name: Regression Tests\n\non: [push, pull_request]\n\njobs:\n  build:\n    name: Python ${{ matrix.python-version }} (${{ matr"
  },
  {
    "path": ".gitignore",
    "chars": 33,
    "preview": "*~\n*.lxt\n*.pyc\n*.vvp\n*.kate-swp\n\n"
  },
  {
    "path": "AUTHORS",
    "chars": 40,
    "preview": "Alex Forencich <alex@alexforencich.com>\n"
  },
  {
    "path": "COPYING",
    "chars": 1057,
    "preview": "Copyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this "
  },
  {
    "path": "README.md",
    "chars": 2094,
    "preview": "# Verilog LFSR Readme\n\n[![Build Status](https://github.com/alexforencich/verilog-lfsr/workflows/Regression%20Tests/badge"
  },
  {
    "path": "rtl/lfsr.v",
    "chars": 16327,
    "preview": "/*\n\nCopyright (c) 2016-2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
  },
  {
    "path": "rtl/lfsr_crc.v",
    "chars": 6390,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "rtl/lfsr_descramble.v",
    "chars": 6809,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "rtl/lfsr_prbs_check.v",
    "chars": 6903,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "rtl/lfsr_prbs_gen.v",
    "chars": 6833,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "rtl/lfsr_scramble.v",
    "chars": 6805,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/lfsr/Makefile",
    "chars": 2378,
    "preview": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# o"
  },
  {
    "path": "tb/lfsr/test_lfsr.py",
    "chars": 6687,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/lfsr_crc/Makefile",
    "chars": 2448,
    "preview": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# o"
  },
  {
    "path": "tb/lfsr_crc/test_lfsr_crc.py",
    "chars": 5563,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/lfsr_descramble/Makefile",
    "chars": 2443,
    "preview": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# o"
  },
  {
    "path": "tb/lfsr_descramble/test_lfsr_descramble.py",
    "chars": 5621,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/lfsr_prbs_check/Makefile",
    "chars": 2459,
    "preview": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# o"
  },
  {
    "path": "tb/lfsr_prbs_check/test_lfsr_prbs_check.py",
    "chars": 6102,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/lfsr_prbs_gen/Makefile",
    "chars": 2457,
    "preview": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# o"
  },
  {
    "path": "tb/lfsr_prbs_gen/test_lfsr_prbs_gen.py",
    "chars": 5174,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/lfsr_scramble/Makefile",
    "chars": 2441,
    "preview": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# o"
  },
  {
    "path": "tb/lfsr_scramble/test_lfsr_scramble.py",
    "chars": 5157,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_crc32.py",
    "chars": 3529,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_crc32.v",
    "chars": 2238,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_crc_crc32.py",
    "chars": 3770,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_crc_crc32.v",
    "chars": 2235,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_crc_crc32_64.py",
    "chars": 4010,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_crc_crc32_64.v",
    "chars": 2245,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_descramble.py",
    "chars": 4335,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_descramble.v",
    "chars": 2218,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_descramble_64.py",
    "chars": 4461,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_descramble_64.v",
    "chars": 2228,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_prbs31.py",
    "chars": 3417,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_prbs31.v",
    "chars": 2235,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_prbs9.py",
    "chars": 3374,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_prbs9.v",
    "chars": 2225,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_prbs_check_prbs31.py",
    "chars": 4960,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_prbs_check_prbs31.v",
    "chars": 2280,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_prbs_check_prbs31_64.py",
    "chars": 4671,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_prbs_check_prbs31_64.v",
    "chars": 2290,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_prbs_check_prbs9.py",
    "chars": 4421,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_prbs_check_prbs9.v",
    "chars": 2270,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_prbs_gen_prbs31.py",
    "chars": 3477,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_prbs_gen_prbs31.v",
    "chars": 2168,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_prbs_gen_prbs31_64.py",
    "chars": 3580,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_prbs_gen_prbs31_64.v",
    "chars": 2178,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_prbs_gen_prbs9.py",
    "chars": 3433,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_prbs_gen_prbs9.v",
    "chars": 2158,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_scramble.py",
    "chars": 3905,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_scramble.v",
    "chars": 2208,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tb/test_lfsr_scramble_64.py",
    "chars": 3969,
    "preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "tb/test_lfsr_scramble_64.v",
    "chars": 2218,
    "preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
  },
  {
    "path": "tox.ini",
    "chars": 439,
    "preview": "# tox configuration\n[tox]\nenvlist = py3\nskipsdist = True\nminversion = 3.2.0\nrequires = virtualenv >= 16.1\n\n[gh-actions]\n"
  }
]

About this extraction

This page contains the full source code of the alexforencich/verilog-lfsr GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 54 files (191.6 KB), approximately 55.8k tokens, and a symbol index with 99 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!