[
  {
    "path": ".github/workflows/regression-tests.yml",
    "content": "name: Regression Tests\n\non: [push, pull_request]\n\njobs:\n  build:\n    name: Python ${{ matrix.python-version }} (${{ matrix.group }}/10)\n    runs-on: ubuntu-20.04\n    \n    strategy:\n      matrix:\n        python-version: [3.9]\n        group: [1, 2, 3, 4, 5]\n\n    steps:\n    - uses: actions/checkout@v1\n\n    - name: Set up Python ${{ matrix.python-version }}\n      uses: actions/setup-python@v2\n      with:\n        python-version: ${{ matrix.python-version }}\n\n    - name: Install Icarus Verilog\n      run: |\n        sudo apt install -y --no-install-recommends iverilog\n\n    - name: Install Python dependencies\n      run: |\n        python -m pip install --upgrade pip\n        pip install tox tox-gh-actions\n\n    - name: Test with tox\n      run: tox -- --splits 5 --group ${{ matrix.group }} --splitting-algorithm least_duration\n"
  },
  {
    "path": ".gitignore",
    "content": "*~\n*.lxt\n*.pyc\n*.vvp\n*.kate-swp\n\n"
  },
  {
    "path": "AUTHORS",
    "content": "Alex Forencich <alex@alexforencich.com>\n"
  },
  {
    "path": "COPYING",
    "content": "Copyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Verilog LFSR Readme\n\n[![Build Status](https://github.com/alexforencich/verilog-lfsr/workflows/Regression%20Tests/badge.svg?branch=master)](https://github.com/alexforencich/verilog-lfsr/actions/)\n\nFor more information and updates: http://alexforencich.com/wiki/en/verilog/lfsr/start\n\nGitHub repository: https://github.com/alexforencich/verilog-lfsr\n\n## Deprecation Notice\n\nThis 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.\n\n## Introduction\n\nFully parametrizable combinatorial parallel LFSR/CRC module.  Implements an unrolled LFSR next state computation.  Includes full cocotb testbenches.\n\n## Documentation\n\n### lfsr module\n\nFully parametrizable combinatorial parallel LFSR/CRC module.  Implements an unrolled LFSR next state computation.\n\n### lfsr_crc module\n\nWrapper for lfsr module for standard CRC computation.\n\n### lfsr_descramble module\n\nWrapper for lfsr module for self-synchronizing descrambler.\n\n### lfsr_prbs_check module\n\nWrapper for lfsr module for standard PRBS check.\n\n### lfsr_prbs_gen module\n\nWrapper for lfsr module for standard PRBS computation.\n\n### lfsr_scramble module\n\nWrapper for lfsr module for self-synchronizing scrambler.\n\n### Source Files\n\n    lfsr.v             : Parametrizable combinatorial LFSR/CRC module\n    lfsr_crc.v         : Parametrizable CRC computation wrapper\n    lfsr_descramble.v  : Parametrizable LFSR self-synchronizing descrambler\n    lfsr_prbs_check.v  : Parametrizable PRBS checker wrapper\n    lfsr_prbs_gen.v    : Parametrizable PRBS generator wrapper\n    lfsr_scramble.v    : Parametrizable LFSR self-synchronizing scrambler\n\n## Testing\n\nRunning 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.\n"
  },
  {
    "path": "rtl/lfsr.v",
    "content": "/*\n\nCopyright (c) 2016-2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`resetall\n`timescale 1ns / 1ps\n`default_nettype none\n\n/*\n * Parametrizable combinatorial parallel LFSR/CRC\n */\nmodule lfsr #\n(\n    // width of LFSR\n    parameter LFSR_WIDTH = 31,\n    // LFSR polynomial\n    parameter LFSR_POLY = 31'h10000001,\n    // LFSR configuration: \"GALOIS\", \"FIBONACCI\"\n    parameter LFSR_CONFIG = \"FIBONACCI\",\n    // LFSR feed forward enable\n    parameter LFSR_FEED_FORWARD = 0,\n    // bit-reverse input and output\n    parameter REVERSE = 0,\n    // width of data input\n    parameter DATA_WIDTH = 8,\n    // implementation style: \"AUTO\", \"LOOP\", \"REDUCTION\"\n    parameter STYLE = \"AUTO\"\n)\n(\n    input  wire [DATA_WIDTH-1:0] data_in,\n    input  wire [LFSR_WIDTH-1:0] state_in,\n    output wire [DATA_WIDTH-1:0] data_out,\n    output wire [LFSR_WIDTH-1:0] state_out\n);\n\n/*\n\nFully parametrizable combinatorial parallel LFSR/CRC module.  Implements an unrolled LFSR\nnext state computation, shifting DATA_WIDTH bits per pass through the module.  Input data\nis XORed with LFSR feedback path, tie data_in to zero if this is not required.\n\nWorks in two parts: statically computes a set of bit masks, then uses these bit masks to\nselect bits for XORing to compute the next state.  \n\nPorts:\n\ndata_in\n\nData bits to be shifted through the LFSR (DATA_WIDTH bits)\n\nstate_in\n\nLFSR/CRC current state input (LFSR_WIDTH bits)\n\ndata_out\n\nData bits shifted out of LFSR (DATA_WIDTH bits)\n\nstate_out\n\nLFSR/CRC next state output (LFSR_WIDTH bits)\n\nParameters:\n\nLFSR_WIDTH\n\nSpecify width of LFSR/CRC register\n\nLFSR_POLY\n\nSpecify the LFSR/CRC polynomial in hex format.  For example, the polynomial\n\nx^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\n\nwould be represented as\n\n32'h04c11db7\n\nNote that the largest term (x^32) is suppressed.  This term is generated automatically based\non LFSR_WIDTH.\n\nLFSR_CONFIG\n\nSpecify the LFSR configuration, either Fibonacci or Galois.  Fibonacci is generally used\nfor linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,\nscramblers, and descrambers, while Galois is generally used for cyclic redundancy check\ngenerators and checkers.\n\nFibonacci style (example for 64b66b scrambler, 0x8000000001)\n\n   DIN (LSB first)\n    |\n    V\n   (+)<---------------------------(+)<-----------------------------.\n    |                              ^                               |\n    |  .----.  .----.       .----. |  .----.       .----.  .----.  |\n    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'\n    |  '----'  '----'       '----'    '----'       '----'  '----'\n    V\n   DOUT\n\nGalois style (example for CRC16, 0x8005)\n\n    ,-------------------+-------------------------+----------(+)<-- DIN (MSB first)\n    |                   |                         |           ^\n    |  .----.  .----.   V   .----.       .----.   V   .----.  |\n    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |--+---> DOUT\n       '----'  '----'       '----'       '----'       '----'\n\nLFSR_FEED_FORWARD\n\nGenerate feed forward instead of feed back LFSR.  Enable this for PRBS checking and self-\nsynchronous descrambling.\n\nFibonacci feed-forward style (example for 64b66b descrambler, 0x8000000001)\n\n   DIN (LSB first)\n    |\n    |  .----.  .----.       .----.    .----.       .----.  .----.\n    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--.\n    |  '----'  '----'       '----' |  '----'       '----'  '----'  |\n    |                              V                               |\n   (+)<---------------------------(+)------------------------------'\n    |\n    V\n   DOUT\n\nGalois feed-forward style\n\n    ,-------------------+-------------------------+------------+--- DIN (MSB first)\n    |                   |                         |            |\n    |  .----.  .----.   V   .----.       .----.   V   .----.   V\n    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |->(+)-> DOUT\n       '----'  '----'       '----'       '----'       '----'\n\nREVERSE\n\nBit-reverse LFSR input and output.  Shifts MSB first by default, set REVERSE for LSB first.\n\nDATA_WIDTH\n\nSpecify width of input and output data bus.  The module will perform one shift per input\ndata bit, so if the input data bus is not required tie data_in to zero and set DATA_WIDTH\nto the required number of shifts per clock cycle.  \n\nSTYLE\n\nSpecify implementation style.  Can be \"AUTO\", \"LOOP\", or \"REDUCTION\".  When \"AUTO\"\nis selected, implemenation will be \"LOOP\" or \"REDUCTION\" based on synthesis translate\ndirectives.  \"REDUCTION\" and \"LOOP\" are functionally identical, however they simulate\nand synthesize differently.  \"REDUCTION\" is implemented with a loop over a Verilog\nreduction operator.  \"LOOP\" is implemented as a doubly-nested loop with no reduction\noperator.  \"REDUCTION\" is very fast for simulation in iverilog and synthesizes well in\nQuartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing\nproblems with the optimizer.  \"LOOP\" synthesizes will in both ISE and Quartus.  \"AUTO\"\nwill default to \"REDUCTION\" when simulating and \"LOOP\" for synthesizers that obey\nsynthesis translate directives.\n\nSettings for common LFSR/CRC implementations:\n\nName        Configuration           Length  Polynomial      Initial value   Notes\nCRC16-IBM   Galois, bit-reverse     16      16'h8005        16'hffff\nCRC16-CCITT Galois                  16      16'h1021        16'h1d0f\nCRC32       Galois, bit-reverse     32      32'h04c11db7    32'hffffffff    Ethernet FCS; invert final output\nCRC32C      Galois, bit-reverse     32      32'h1edc6f41    32'hffffffff    iSCSI, Intel CRC32 instruction; invert final output\nPRBS6       Fibonacci               6       6'h21           any\nPRBS7       Fibonacci               7       7'h41           any\nPRBS9       Fibonacci               9       9'h021          any             ITU V.52\nPRBS10      Fibonacci               10      10'h081         any             ITU\nPRBS11      Fibonacci               11      11'h201         any             ITU O.152\nPRBS15      Fibonacci, inverted     15      15'h4001        any             ITU O.152\nPRBS17      Fibonacci               17      17'h04001       any\nPRBS20      Fibonacci               20      20'h00009       any             ITU V.57\nPRBS23      Fibonacci, inverted     23      23'h040001      any             ITU O.151\nPRBS29      Fibonacci, inverted     29      29'h08000001    any\nPRBS31      Fibonacci, inverted     31      31'h10000001    any\n64b66b      Fibonacci, bit-reverse  58      58'h8000000001  any             10G Ethernet\n128b130b    Galois, bit-reverse     23      23'h210125      any             PCIe gen 3\n\n*/\n\nfunction [LFSR_WIDTH+DATA_WIDTH-1:0] lfsr_mask(input [31:0] index);\n    reg [LFSR_WIDTH-1:0] lfsr_mask_state[LFSR_WIDTH-1:0];\n    reg [DATA_WIDTH-1:0] lfsr_mask_data[LFSR_WIDTH-1:0];\n    reg [LFSR_WIDTH-1:0] output_mask_state[DATA_WIDTH-1:0];\n    reg [DATA_WIDTH-1:0] output_mask_data[DATA_WIDTH-1:0];\n\n    reg [LFSR_WIDTH-1:0] state_val;\n    reg [DATA_WIDTH-1:0] data_val;\n\n    reg [DATA_WIDTH-1:0] data_mask;\n\n    integer i, j;\n\n    begin\n        // init bit masks\n        for (i = 0; i < LFSR_WIDTH; i = i + 1) begin\n            lfsr_mask_state[i] = 0;\n            lfsr_mask_state[i][i] = 1'b1;\n            lfsr_mask_data[i] = 0;\n        end\n        for (i = 0; i < DATA_WIDTH; i = i + 1) begin\n            output_mask_state[i] = 0;\n            if (i < LFSR_WIDTH) begin\n                output_mask_state[i][i] = 1'b1;\n            end\n            output_mask_data[i] = 0;\n        end\n\n        // simulate shift register\n        if (LFSR_CONFIG == \"FIBONACCI\") begin\n            // Fibonacci configuration\n            for (data_mask = {1'b1, {DATA_WIDTH-1{1'b0}}}; data_mask != 0; data_mask = data_mask >> 1) begin\n                // determine shift in value\n                // current value in last FF, XOR with input data bit (MSB first)\n                state_val = lfsr_mask_state[LFSR_WIDTH-1];\n                data_val = lfsr_mask_data[LFSR_WIDTH-1];\n                data_val = data_val ^ data_mask;\n\n                // add XOR inputs from correct indicies\n                for (j = 1; j < LFSR_WIDTH; j = j + 1) begin\n                    if ((LFSR_POLY >> j) & 1) begin\n                        state_val = lfsr_mask_state[j-1] ^ state_val;\n                        data_val = lfsr_mask_data[j-1] ^ data_val;\n                    end\n                end\n\n                // shift\n                for (j = LFSR_WIDTH-1; j > 0; j = j - 1) begin\n                    lfsr_mask_state[j] = lfsr_mask_state[j-1];\n                    lfsr_mask_data[j] = lfsr_mask_data[j-1];\n                end\n                for (j = DATA_WIDTH-1; j > 0; j = j - 1) begin\n                    output_mask_state[j] = output_mask_state[j-1];\n                    output_mask_data[j] = output_mask_data[j-1];\n                end\n                output_mask_state[0] = state_val;\n                output_mask_data[0] = data_val;\n                if (LFSR_FEED_FORWARD) begin\n                    // only shift in new input data\n                    state_val = {LFSR_WIDTH{1'b0}};\n                    data_val = data_mask;\n                end\n                lfsr_mask_state[0] = state_val;\n                lfsr_mask_data[0] = data_val;\n            end\n        end else if (LFSR_CONFIG == \"GALOIS\") begin\n            // Galois configuration\n            for (data_mask = {1'b1, {DATA_WIDTH-1{1'b0}}}; data_mask != 0; data_mask = data_mask >> 1) begin\n                // determine shift in value\n                // current value in last FF, XOR with input data bit (MSB first)\n                state_val = lfsr_mask_state[LFSR_WIDTH-1];\n                data_val = lfsr_mask_data[LFSR_WIDTH-1];\n                data_val = data_val ^ data_mask;\n\n                // shift\n                for (j = LFSR_WIDTH-1; j > 0; j = j - 1) begin\n                    lfsr_mask_state[j] = lfsr_mask_state[j-1];\n                    lfsr_mask_data[j] = lfsr_mask_data[j-1];\n                end\n                for (j = DATA_WIDTH-1; j > 0; j = j - 1) begin\n                    output_mask_state[j] = output_mask_state[j-1];\n                    output_mask_data[j] = output_mask_data[j-1];\n                end\n                output_mask_state[0] = state_val;\n                output_mask_data[0] = data_val;\n                if (LFSR_FEED_FORWARD) begin\n                    // only shift in new input data\n                    state_val = {LFSR_WIDTH{1'b0}};\n                    data_val = data_mask;\n                end\n                lfsr_mask_state[0] = state_val;\n                lfsr_mask_data[0] = data_val;\n\n                // add XOR inputs at correct indicies\n                for (j = 1; j < LFSR_WIDTH; j = j + 1) begin\n                    if ((LFSR_POLY >> j) & 1) begin\n                        lfsr_mask_state[j] = lfsr_mask_state[j] ^ state_val;\n                        lfsr_mask_data[j] = lfsr_mask_data[j] ^ data_val;\n                    end\n                end\n            end\n        end else begin\n            $error(\"Error: unknown configuration setting!\");\n            $finish;\n        end\n\n        // reverse bits if selected\n        if (REVERSE) begin\n            if (index < LFSR_WIDTH) begin\n                state_val = 0;\n                for (i = 0; i < LFSR_WIDTH; i = i + 1) begin\n                    state_val[i] = lfsr_mask_state[LFSR_WIDTH-index-1][LFSR_WIDTH-i-1];\n                end\n\n                data_val = 0;\n                for (i = 0; i < DATA_WIDTH; i = i + 1) begin\n                    data_val[i] = lfsr_mask_data[LFSR_WIDTH-index-1][DATA_WIDTH-i-1];\n                end\n            end else begin\n                state_val = 0;\n                for (i = 0; i < LFSR_WIDTH; i = i + 1) begin\n                    state_val[i] = output_mask_state[DATA_WIDTH-(index-LFSR_WIDTH)-1][LFSR_WIDTH-i-1];\n                end\n\n                data_val = 0;\n                for (i = 0; i < DATA_WIDTH; i = i + 1) begin\n                    data_val[i] = output_mask_data[DATA_WIDTH-(index-LFSR_WIDTH)-1][DATA_WIDTH-i-1];\n                end\n            end\n        end else begin\n            if (index < LFSR_WIDTH) begin\n                state_val = lfsr_mask_state[index];\n                data_val = lfsr_mask_data[index];\n            end else begin\n                state_val = output_mask_state[index-LFSR_WIDTH];\n                data_val = output_mask_data[index-LFSR_WIDTH];\n            end\n        end\n        lfsr_mask = {data_val, state_val};\n    end\nendfunction\n\n// synthesis translate_off\n`define SIMULATION\n// synthesis translate_on\n\n`ifdef SIMULATION\n// \"AUTO\" style is \"REDUCTION\" for faster simulation\nparameter STYLE_INT = (STYLE == \"AUTO\") ? \"REDUCTION\" : STYLE;\n`else\n// \"AUTO\" style is \"LOOP\" for better synthesis result\nparameter STYLE_INT = (STYLE == \"AUTO\") ? \"LOOP\" : STYLE;\n`endif\n\ngenvar n;\n\ngenerate\n\nif (STYLE_INT == \"REDUCTION\") begin\n\n    // use Verilog reduction operator\n    // fast in iverilog\n    // significantly larger than generated code with ISE (inferred wide XORs may be tripping up optimizer)\n    // slightly smaller than generated code with Quartus\n    // --> better for simulation\n\n    for (n = 0; n < LFSR_WIDTH; n = n + 1) begin : lfsr_state\n        wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n);\n        assign state_out[n] = ^({data_in, state_in} & mask);\n    end\n    for (n = 0; n < DATA_WIDTH; n = n + 1) begin : lfsr_data\n        wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n+LFSR_WIDTH);\n        assign data_out[n] = ^({data_in, state_in} & mask);\n    end\n\nend else if (STYLE_INT == \"LOOP\") begin\n\n    // use nested loops\n    // very slow in iverilog\n    // slightly smaller than generated code with ISE\n    // same size as generated code with Quartus\n    // --> better for synthesis\n\n    for (n = 0; n < LFSR_WIDTH; n = n + 1) begin : lfsr_state\n        wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n);\n\n        reg state_reg;\n\n        assign state_out[n] = state_reg;\n\n        integer i;\n\n        always @* begin\n            state_reg = 1'b0;\n            for (i = 0; i < LFSR_WIDTH; i = i + 1) begin\n                if (mask[i]) begin\n                    state_reg = state_reg ^ state_in[i];\n                end\n            end\n            for (i = 0; i < DATA_WIDTH; i = i + 1) begin\n                if (mask[i+LFSR_WIDTH]) begin\n                    state_reg = state_reg ^ data_in[i];\n                end\n            end\n        end\n    end\n    for (n = 0; n < DATA_WIDTH; n = n + 1) begin : lfsr_data\n        wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n+LFSR_WIDTH);\n\n        reg data_reg;\n\n        assign data_out[n] = data_reg;\n\n        integer i;\n\n        always @* begin\n            data_reg = 1'b0;\n            for (i = 0; i < LFSR_WIDTH; i = i + 1) begin\n                if (mask[i]) begin\n                    data_reg = data_reg ^ state_in[i];\n                end\n            end\n            for (i = 0; i < DATA_WIDTH; i = i + 1) begin\n                if (mask[i+LFSR_WIDTH]) begin\n                    data_reg = data_reg ^ data_in[i];\n                end\n            end\n        end\n    end\n\nend else begin\n\n    initial begin\n        $error(\"Error: unknown style setting!\");\n        $finish;\n    end\n\nend\n\nendgenerate\n\nendmodule\n\n`resetall\n"
  },
  {
    "path": "rtl/lfsr_crc.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`resetall\n`timescale 1ns / 1ps\n`default_nettype none\n\n/*\n * LFSR CRC generator\n */\nmodule lfsr_crc #\n(\n    // width of LFSR\n    parameter LFSR_WIDTH = 32,\n    // LFSR polynomial\n    parameter LFSR_POLY = 32'h04c11db7,\n    // Initial state\n    parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},\n    // LFSR configuration: \"GALOIS\", \"FIBONACCI\"\n    parameter LFSR_CONFIG = \"GALOIS\",\n    // bit-reverse input and output\n    parameter REVERSE = 1,\n    // invert output\n    parameter INVERT = 1,\n    // width of data input and output\n    parameter DATA_WIDTH = 8,\n    // implementation style: \"AUTO\", \"LOOP\", \"REDUCTION\"\n    parameter STYLE = \"AUTO\"\n)\n(\n    input  wire                  clk,\n    input  wire                  rst,\n    input  wire [DATA_WIDTH-1:0] data_in,\n    input  wire                  data_in_valid,\n    output wire [LFSR_WIDTH-1:0] crc_out\n);\n\n/*\n\nFully parametrizable combinatorial parallel LFSR CRC module.  Implements an unrolled LFSR\nnext state computation.  \n\nPorts:\n\nclk\n\nClock input\n\nrst\n\nReset module, set state to LFSR_INIT\n\ndata_in\n\nCRC data input\n\ndata_in_valid\n\nShift input data through CRC when asserted\n\ndata_out\n\nLFSR output (OUTPUT_WIDTH bits)\n\nParameters:\n\nLFSR_WIDTH\n\nSpecify width of LFSR/CRC register\n\nLFSR_POLY\n\nSpecify the LFSR/CRC polynomial in hex format.  For example, the polynomial\n\nx^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\n\nwould be represented as\n\n32'h04c11db7\n\nNote that the largest term (x^32) is suppressed.  This term is generated automatically based\non LFSR_WIDTH.\n\nLFSR_INIT\n\nInitial state of LFSR.  Defaults to all 1s.\n\nLFSR_CONFIG\n\nSpecify the LFSR configuration, either Fibonacci or Galois.  Fibonacci is generally used\nfor linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,\nscramblers, and descrambers, while Galois is generally used for cyclic redundancy check\ngenerators and checkers.\n\nFibonacci style (example for 64b66b scrambler, 0x8000000001)\n\n   DIN (LSB first)\n    |\n    V\n   (+)<---------------------------(+)<-----------------------------.\n    |                              ^                               |\n    |  .----.  .----.       .----. |  .----.       .----.  .----.  |\n    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'\n    |  '----'  '----'       '----'    '----'       '----'  '----'\n    V\n   DOUT\n\nGalois style (example for CRC16, 0x8005)\n\n    ,-------------------+-------------------------+----------(+)<-- DIN (MSB first)\n    |                   |                         |           ^\n    |  .----.  .----.   V   .----.       .----.   V   .----.  |\n    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |--+---> DOUT\n       '----'  '----'       '----'       '----'       '----'\n\nREVERSE\n\nBit-reverse LFSR input and output.  Shifts MSB first by default, set REVERSE for LSB first.\n\nINVERT\n\nBitwise invert CRC output.\n\nDATA_WIDTH\n\nSpecify width of input data bus.  The module will perform one shift per input data bit,\nso if the input data bus is not required tie data_in to zero and set DATA_WIDTH to the\nrequired number of shifts per clock cycle.  \n\nSTYLE\n\nSpecify implementation style.  Can be \"AUTO\", \"LOOP\", or \"REDUCTION\".  When \"AUTO\"\nis selected, implemenation will be \"LOOP\" or \"REDUCTION\" based on synthesis translate\ndirectives.  \"REDUCTION\" and \"LOOP\" are functionally identical, however they simulate\nand synthesize differently.  \"REDUCTION\" is implemented with a loop over a Verilog\nreduction operator.  \"LOOP\" is implemented as a doubly-nested loop with no reduction\noperator.  \"REDUCTION\" is very fast for simulation in iverilog and synthesizes well in\nQuartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing\nproblems with the optimizer.  \"LOOP\" synthesizes will in both ISE and Quartus.  \"AUTO\"\nwill default to \"REDUCTION\" when simulating and \"LOOP\" for synthesizers that obey\nsynthesis translate directives.\n\nSettings for common LFSR/CRC implementations:\n\nName        Configuration           Length  Polynomial      Initial value   Notes\nCRC16-IBM   Galois, bit-reverse     16      16'h8005        16'hffff\nCRC16-CCITT Galois                  16      16'h1021        16'h1d0f\nCRC32       Galois, bit-reverse     32      32'h04c11db7    32'hffffffff    Ethernet FCS; invert final output\nCRC32C      Galois, bit-reverse     32      32'h1edc6f41    32'hffffffff    iSCSI, Intel CRC32 instruction; invert final output\n\n*/\n\nreg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;\nreg [LFSR_WIDTH-1:0] output_reg = 0;\n\nwire [LFSR_WIDTH-1:0] lfsr_state;\n\nassign crc_out = output_reg;\n\nlfsr #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .LFSR_FEED_FORWARD(0),\n    .REVERSE(REVERSE),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nlfsr_inst (\n    .data_in(data_in),\n    .state_in(state_reg),\n    .data_out(),\n    .state_out(lfsr_state)\n);\n\nalways @(posedge clk) begin\n    if (rst) begin\n        state_reg <= LFSR_INIT;\n        output_reg <= 0;\n    end else begin\n        if (data_in_valid) begin\n            state_reg <= lfsr_state;\n            if (INVERT) begin\n                output_reg <= ~lfsr_state;\n            end else begin\n                output_reg <= lfsr_state;\n            end\n        end\n    end\nend\n\nendmodule\n\n`resetall\n"
  },
  {
    "path": "rtl/lfsr_descramble.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`resetall\n`timescale 1ns / 1ps\n`default_nettype none\n\n/*\n * LFSR descrambler\n */\nmodule lfsr_descramble #\n(\n    // width of LFSR\n    parameter LFSR_WIDTH = 58,\n    // LFSR polynomial\n    parameter LFSR_POLY = 58'h8000000001,\n    // Initial state\n    parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},\n    // LFSR configuration: \"GALOIS\", \"FIBONACCI\"\n    parameter LFSR_CONFIG = \"FIBONACCI\",\n    // bit-reverse input and output\n    parameter REVERSE = 1,\n    // width of data bus\n    parameter DATA_WIDTH = 64,\n    // implementation style: \"AUTO\", \"LOOP\", \"REDUCTION\"\n    parameter STYLE = \"AUTO\"\n)\n(\n    input  wire                  clk,\n    input  wire                  rst,\n    input  wire [DATA_WIDTH-1:0] data_in,\n    input  wire                  data_in_valid,\n    output wire [DATA_WIDTH-1:0] data_out\n);\n\n/*\n\nFully parametrizable combinatorial parallel LFSR CRC module.  Implements an unrolled LFSR\nnext state computation.  \n\nPorts:\n\nclk\n\nClock input\n\nrst\n\nReset module, set state to LFSR_INIT\n\ndata_in\n\nScrambled data input (DATA_WIDTH bits)\n\ndata_in_valid\n\nShift input data through CRC when asserted\n\ndata_out\n\nDescrambled data output (DATA_WIDTH bits)\n\nParameters:\n\nLFSR_WIDTH\n\nSpecify width of LFSR/CRC register\n\nLFSR_POLY\n\nSpecify the LFSR/CRC polynomial in hex format.  For example, the polynomial\n\nx^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\n\nwould be represented as\n\n32'h04c11db7\n\nNote that the largest term (x^32) is suppressed.  This term is generated automatically based\non LFSR_WIDTH.\n\nLFSR_INIT\n\nInitial state of LFSR.  Defaults to all 1s.\n\nLFSR_CONFIG\n\nSpecify the LFSR configuration, either Fibonacci or Galois.  Fibonacci is generally used\nfor linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,\nscramblers, and descrambers, while Galois is generally used for cyclic redundancy check\ngenerators and checkers.\n\nFibonacci style (example for 64b66b scrambler, 0x8000000001)\n\n   DIN (LSB first)\n    |\n    V\n   (+)<---------------------------(+)<-----------------------------.\n    |                              ^                               |\n    |  .----.  .----.       .----. |  .----.       .----.  .----.  |\n    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'\n    |  '----'  '----'       '----'    '----'       '----'  '----'\n    V\n   DOUT\n\nGalois style (example for CRC16, 0x8005)\n\n    ,-------------------+-------------------------+----------(+)<-- DIN (MSB first)\n    |                   |                         |           ^\n    |  .----.  .----.   V   .----.       .----.   V   .----.  |\n    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |--+---> DOUT\n       '----'  '----'       '----'       '----'       '----'\n\nREVERSE\n\nBit-reverse LFSR input and output.\n\nDATA_WIDTH\n\nSpecify width of the data bus.  The module will perform one shift per input data bit.\n\nSTYLE\n\nSpecify implementation style.  Can be \"AUTO\", \"LOOP\", or \"REDUCTION\".  When \"AUTO\"\nis selected, implemenation will be \"LOOP\" or \"REDUCTION\" based on synthesis translate\ndirectives.  \"REDUCTION\" and \"LOOP\" are functionally identical, however they simulate\nand synthesize differently.  \"REDUCTION\" is implemented with a loop over a Verilog\nreduction operator.  \"LOOP\" is implemented as a doubly-nested loop with no reduction\noperator.  \"REDUCTION\" is very fast for simulation in iverilog and synthesizes well in\nQuartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing\nproblems with the optimizer.  \"LOOP\" synthesizes will in both ISE and Quartus.  \"AUTO\"\nwill default to \"REDUCTION\" when simulating and \"LOOP\" for synthesizers that obey\nsynthesis translate directives.\n\nSettings for common LFSR/CRC implementations:\n\nName        Configuration           Length  Polynomial      Initial value   Notes\nCRC32       Galois, bit-reverse     32      32'h04c11db7    32'hffffffff    Ethernet FCS; invert final output\nPRBS6       Fibonacci               6       6'h21           any\nPRBS7       Fibonacci               7       7'h41           any\nPRBS9       Fibonacci               9       9'h021          any             ITU V.52\nPRBS10      Fibonacci               10      10'h081         any             ITU\nPRBS11      Fibonacci               11      11'h201         any             ITU O.152\nPRBS15      Fibonacci, inverted     15      15'h4001        any             ITU O.152\nPRBS17      Fibonacci               17      17'h04001       any\nPRBS20      Fibonacci               20      20'h00009       any             ITU V.57\nPRBS23      Fibonacci, inverted     23      23'h040001      any             ITU O.151\nPRBS29      Fibonacci, inverted     29      29'h08000001    any\nPRBS31      Fibonacci, inverted     31      31'h10000001    any\n64b66b      Fibonacci, bit-reverse  58      58'h8000000001  any             10G Ethernet\n128b130b    Galois, bit-reverse     23      23'h210125      any             PCIe gen 3\n\n*/\n\nreg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;\nreg [DATA_WIDTH-1:0] output_reg = 0;\n\nwire [DATA_WIDTH-1:0] lfsr_data;\nwire [LFSR_WIDTH-1:0] lfsr_state;\n\nassign data_out = output_reg;\n\nlfsr #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .LFSR_FEED_FORWARD(1),\n    .REVERSE(REVERSE),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nlfsr_inst (\n    .data_in(data_in),\n    .state_in(state_reg),\n    .data_out(lfsr_data),\n    .state_out(lfsr_state)\n);\n\nalways @(posedge clk) begin\n    if (rst) begin\n        state_reg <= LFSR_INIT;\n        output_reg <= 0;\n    end else begin\n        if (data_in_valid) begin\n            state_reg <= lfsr_state;\n            output_reg <= lfsr_data;\n        end\n    end\nend\n\nendmodule\n\n`resetall\n"
  },
  {
    "path": "rtl/lfsr_prbs_check.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`resetall\n`timescale 1ns / 1ps\n`default_nettype none\n\n/*\n * LFSR PRBS checker\n */\nmodule lfsr_prbs_check #\n(\n    // width of LFSR\n    parameter LFSR_WIDTH = 31,\n    // LFSR polynomial\n    parameter LFSR_POLY = 31'h10000001,\n    // Initial state\n    parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},\n    // LFSR configuration: \"GALOIS\", \"FIBONACCI\"\n    parameter LFSR_CONFIG = \"FIBONACCI\",\n    // bit-reverse input and output\n    parameter REVERSE = 0,\n    // invert input\n    parameter INVERT = 1,\n    // width of data input and output\n    parameter DATA_WIDTH = 8,\n    // implementation style: \"AUTO\", \"LOOP\", \"REDUCTION\"\n    parameter STYLE = \"AUTO\"\n)\n(\n    input  wire                    clk,\n    input  wire                    rst,\n    input  wire [DATA_WIDTH-1:0]   data_in,\n    input  wire                    data_in_valid,\n    output wire [DATA_WIDTH-1:0]   data_out\n);\n\n/*\n\nFully parametrizable combinatorial parallel LFSR PRBS checker.  Implements an unrolled LFSR\nPRBS checker.  \n\nPorts:\n\nclk\n\nClock input\n\nrst\n\nReset input, set state to LFSR_INIT\n\ndata_in\n\nPRBS data input (DATA_WIDTH bits)\n\ndata_in_valid\n\nShift input data through LFSR when asserted\n\ndata_out\n\nError output (DATA_WIDTH bits)\n\nParameters:\n\nLFSR_WIDTH\n\nSpecify width of LFSR/CRC register\n\nLFSR_POLY\n\nSpecify the LFSR/CRC polynomial in hex format.  For example, the polynomial\n\nx^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\n\nwould be represented as\n\n32'h04c11db7\n\nNote that the largest term (x^32) is suppressed.  This term is generated automatically based\non LFSR_WIDTH.\n\nLFSR_INIT\n\nInitial state of LFSR.  Defaults to all 1s.\n\nLFSR_CONFIG\n\nSpecify the LFSR configuration, either Fibonacci or Galois.  Fibonacci is generally used\nfor linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,\nscramblers, and descrambers, while Galois is generally used for cyclic redundancy check\ngenerators and checkers.\n\nFibonacci style (example for 64b66b scrambler, 0x8000000001)\n\n   DIN (LSB first)\n    |\n    V\n   (+)<---------------------------(+)<-----------------------------.\n    |                              ^                               |\n    |  .----.  .----.       .----. |  .----.       .----.  .----.  |\n    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'\n    |  '----'  '----'       '----'    '----'       '----'  '----'\n    V\n   DOUT\n\nGalois style (example for CRC16, 0x8005)\n\n    ,-------------------+-------------------------+----------(+)<-- DIN (MSB first)\n    |                   |                         |           ^\n    |  .----.  .----.   V   .----.       .----.   V   .----.  |\n    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |--+---> DOUT\n       '----'  '----'       '----'       '----'       '----'\n\nREVERSE\n\nBit-reverse LFSR output.  Shifts MSB first by default, set REVERSE for LSB first.\n\nINVERT\n\nBitwise invert PRBS input.\n\nDATA_WIDTH\n\nSpecify width of output data bus.\n\nSTYLE\n\nSpecify implementation style.  Can be \"AUTO\", \"LOOP\", or \"REDUCTION\".  When \"AUTO\"\nis selected, implemenation will be \"LOOP\" or \"REDUCTION\" based on synthesis translate\ndirectives.  \"REDUCTION\" and \"LOOP\" are functionally identical, however they simulate\nand synthesize differently.  \"REDUCTION\" is implemented with a loop over a Verilog\nreduction operator.  \"LOOP\" is implemented as a doubly-nested loop with no reduction\noperator.  \"REDUCTION\" is very fast for simulation in iverilog and synthesizes well in\nQuartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing\nproblems with the optimizer.  \"LOOP\" synthesizes will in both ISE and Quartus.  \"AUTO\"\nwill default to \"REDUCTION\" when simulating and \"LOOP\" for synthesizers that obey\nsynthesis translate directives.\n\nSettings for common LFSR/CRC implementations:\n\nName        Configuration           Length  Polynomial      Initial value   Notes\nCRC32       Galois, bit-reverse     32      32'h04c11db7    32'hffffffff    Ethernet FCS; invert final output\nPRBS6       Fibonacci               6       6'h21           any\nPRBS7       Fibonacci               7       7'h41           any\nPRBS9       Fibonacci               9       9'h021          any             ITU V.52\nPRBS10      Fibonacci               10      10'h081         any             ITU\nPRBS11      Fibonacci               11      11'h201         any             ITU O.152\nPRBS15      Fibonacci, inverted     15      15'h4001        any             ITU O.152\nPRBS17      Fibonacci               17      17'h04001       any\nPRBS20      Fibonacci               20      20'h00009       any             ITU V.57\nPRBS23      Fibonacci, inverted     23      23'h040001      any             ITU O.151\nPRBS29      Fibonacci, inverted     29      29'h08000001    any\nPRBS31      Fibonacci, inverted     31      31'h10000001    any\n64b66b      Fibonacci, bit-reverse  58      58'h8000000001  any             10G Ethernet\n128b130b    Galois, bit-reverse     23      23'h210125      any             PCIe gen 3\n\n*/\n\nreg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;\nreg [DATA_WIDTH-1:0] output_reg = 0;\n\nwire [DATA_WIDTH-1:0] lfsr_data;\nwire [LFSR_WIDTH-1:0] lfsr_state;\n\nassign data_out = output_reg;\n\nlfsr #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .LFSR_FEED_FORWARD(1),\n    .REVERSE(REVERSE),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nlfsr_inst (\n    .data_in(INVERT ? ~data_in : data_in),\n    .state_in(state_reg),\n    .data_out(lfsr_data),\n    .state_out(lfsr_state)\n);\n\nalways @(posedge clk) begin\n    if (rst) begin\n        state_reg <= LFSR_INIT;\n        output_reg <= 0;\n    end else begin\n        if (data_in_valid) begin\n            state_reg <= lfsr_state;\n            output_reg <= lfsr_data;\n        end\n    end\nend\n\nendmodule\n\n`resetall\n"
  },
  {
    "path": "rtl/lfsr_prbs_gen.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`resetall\n`timescale 1ns / 1ps\n`default_nettype none\n\n/*\n * LFSR PRBS generator\n */\nmodule lfsr_prbs_gen #\n(\n    // width of LFSR\n    parameter LFSR_WIDTH = 31,\n    // LFSR polynomial\n    parameter LFSR_POLY = 31'h10000001,\n    // Initial state\n    parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},\n    // LFSR configuration: \"GALOIS\", \"FIBONACCI\"\n    parameter LFSR_CONFIG = \"FIBONACCI\",\n    // bit-reverse input and output\n    parameter REVERSE = 0,\n    // invert output\n    parameter INVERT = 1,\n    // width of data output\n    parameter DATA_WIDTH = 8,\n    // implementation style: \"AUTO\", \"LOOP\", \"REDUCTION\"\n    parameter STYLE = \"AUTO\"\n)\n(\n    input  wire                  clk,\n    input  wire                  rst,\n    input  wire                  enable,\n    output wire [DATA_WIDTH-1:0] data_out\n);\n\n/*\n\nFully parametrizable combinatorial parallel LFSR PRBS module.  Implements an unrolled LFSR\nnext state computation.  \n\nPorts:\n\nclk\n\nClock input\n\nrst\n\nReset input, set state to LFSR_INIT\n\nenable\n\nGenerate new output data\n\ndata_out\n\nLFSR output (DATA_WIDTH bits)\n\nParameters:\n\nLFSR_WIDTH\n\nSpecify width of LFSR/CRC register\n\nLFSR_POLY\n\nSpecify the LFSR/CRC polynomial in hex format.  For example, the polynomial\n\nx^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\n\nwould be represented as\n\n32'h04c11db7\n\nNote that the largest term (x^32) is suppressed.  This term is generated automatically based\non LFSR_WIDTH.\n\nLFSR_INIT\n\nInitial state of LFSR.  Defaults to all 1s.\n\nLFSR_CONFIG\n\nSpecify the LFSR configuration, either Fibonacci or Galois.  Fibonacci is generally used\nfor linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,\nscramblers, and descrambers, while Galois is generally used for cyclic redundancy check\ngenerators and checkers.\n\nFibonacci style (example for 64b66b scrambler, 0x8000000001)\n\n   DIN (LSB first)\n    |\n    V\n   (+)<---------------------------(+)<-----------------------------.\n    |                              ^                               |\n    |  .----.  .----.       .----. |  .----.       .----.  .----.  |\n    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'\n    |  '----'  '----'       '----'    '----'       '----'  '----'\n    V\n   DOUT\n\nGalois style (example for CRC16, 0x8005)\n\n    ,-------------------+-------------------------+----------(+)<-- DIN (MSB first)\n    |                   |                         |           ^\n    |  .----.  .----.   V   .----.       .----.   V   .----.  |\n    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |--+---> DOUT\n       '----'  '----'       '----'       '----'       '----'\n\nREVERSE\n\nBit-reverse LFSR output.  Shifts MSB first by default, set REVERSE for LSB first.\n\nINVERT\n\nBitwise invert PRBS output.\n\nDATA_WIDTH\n\nSpecify width of output data bus.\n\nSTYLE\n\nSpecify implementation style.  Can be \"AUTO\", \"LOOP\", or \"REDUCTION\".  When \"AUTO\"\nis selected, implemenation will be \"LOOP\" or \"REDUCTION\" based on synthesis translate\ndirectives.  \"REDUCTION\" and \"LOOP\" are functionally identical, however they simulate\nand synthesize differently.  \"REDUCTION\" is implemented with a loop over a Verilog\nreduction operator.  \"LOOP\" is implemented as a doubly-nested loop with no reduction\noperator.  \"REDUCTION\" is very fast for simulation in iverilog and synthesizes well in\nQuartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing\nproblems with the optimizer.  \"LOOP\" synthesizes will in both ISE and Quartus.  \"AUTO\"\nwill default to \"REDUCTION\" when simulating and \"LOOP\" for synthesizers that obey\nsynthesis translate directives.\n\nSettings for common LFSR/CRC implementations:\n\nName        Configuration           Length  Polynomial      Initial value   Notes\nCRC32       Galois, bit-reverse     32      32'h04c11db7    32'hffffffff    Ethernet FCS; invert final output\nPRBS6       Fibonacci               6       6'h21           any\nPRBS7       Fibonacci               7       7'h41           any\nPRBS9       Fibonacci               9       9'h021          any             ITU V.52\nPRBS10      Fibonacci               10      10'h081         any             ITU\nPRBS11      Fibonacci               11      11'h201         any             ITU O.152\nPRBS15      Fibonacci, inverted     15      15'h4001        any             ITU O.152\nPRBS17      Fibonacci               17      17'h04001       any\nPRBS20      Fibonacci               20      20'h00009       any             ITU V.57\nPRBS23      Fibonacci, inverted     23      23'h040001      any             ITU O.151\nPRBS29      Fibonacci, inverted     29      29'h08000001    any\nPRBS31      Fibonacci, inverted     31      31'h10000001    any\n64b66b      Fibonacci, bit-reverse  58      58'h8000000001  any             10G Ethernet\n128b130b    Galois, bit-reverse     23      23'h210125      any             PCIe gen 3\n\n*/\n\nreg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;\nreg [DATA_WIDTH-1:0] output_reg = 0;\n\nwire [DATA_WIDTH-1:0] lfsr_data;\nwire [LFSR_WIDTH-1:0] lfsr_state;\n\nassign data_out = output_reg;\n\nlfsr #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .LFSR_FEED_FORWARD(0),\n    .REVERSE(REVERSE),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nlfsr_inst (\n    .data_in({DATA_WIDTH{1'b0}}),\n    .state_in(state_reg),\n    .data_out(lfsr_data),\n    .state_out(lfsr_state)\n);\n\nalways @* begin\n    if (INVERT) begin\n        output_reg <= ~lfsr_data;\n    end else begin\n        output_reg <= lfsr_data;\n    end\nend\n\nalways @(posedge clk) begin\n    if (rst) begin\n        state_reg <= LFSR_INIT;\n    end else begin\n        if (enable) begin\n            state_reg <= lfsr_state;\n        end\n    end\nend\n\nendmodule\n\n`resetall\n"
  },
  {
    "path": "rtl/lfsr_scramble.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`resetall\n`timescale 1ns / 1ps\n`default_nettype none\n\n/*\n * LFSR scrambler\n */\nmodule lfsr_scramble #\n(\n    // width of LFSR\n    parameter LFSR_WIDTH = 58,\n    // LFSR polynomial\n    parameter LFSR_POLY = 58'h8000000001,\n    // Initial state\n    parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},\n    // LFSR configuration: \"GALOIS\", \"FIBONACCI\"\n    parameter LFSR_CONFIG = \"FIBONACCI\",\n    // bit-reverse input and output\n    parameter REVERSE = 1,\n    // width of data bus\n    parameter DATA_WIDTH = 64,\n    // implementation style: \"AUTO\", \"LOOP\", \"REDUCTION\"\n    parameter STYLE = \"AUTO\"\n)\n(\n    input  wire                  clk,\n    input  wire                  rst,\n    input  wire [DATA_WIDTH-1:0] data_in,\n    input  wire                  data_in_valid,\n    output wire [DATA_WIDTH-1:0] data_out\n);\n\n/*\n\nFully parametrizable combinatorial parallel LFSR CRC module.  Implements an unrolled LFSR\nnext state computation.  \n\nPorts:\n\nclk\n\nClock input\n\nrst\n\nReset module, set state to LFSR_INIT\n\ndata_in\n\nUnscrambled data input (DATA_WIDTH bits)\n\ndata_in_valid\n\nShift input data through CRC when asserted\n\ndata_out\n\nScrambled data output (DATA_WIDTH bits)\n\nParameters:\n\nLFSR_WIDTH\n\nSpecify width of LFSR/CRC register\n\nLFSR_POLY\n\nSpecify the LFSR/CRC polynomial in hex format.  For example, the polynomial\n\nx^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\n\nwould be represented as\n\n32'h04c11db7\n\nNote that the largest term (x^32) is suppressed.  This term is generated automatically based\non LFSR_WIDTH.\n\nLFSR_INIT\n\nInitial state of LFSR.  Defaults to all 1s.\n\nLFSR_CONFIG\n\nSpecify the LFSR configuration, either Fibonacci or Galois.  Fibonacci is generally used\nfor linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,\nscramblers, and descrambers, while Galois is generally used for cyclic redundancy check\ngenerators and checkers.\n\nFibonacci style (example for 64b66b scrambler, 0x8000000001)\n\n   DIN (LSB first)\n    |\n    V\n   (+)<---------------------------(+)<-----------------------------.\n    |                              ^                               |\n    |  .----.  .----.       .----. |  .----.       .----.  .----.  |\n    +->|  0 |->|  1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'\n    |  '----'  '----'       '----'    '----'       '----'  '----'\n    V\n   DOUT\n\nGalois style (example for CRC16, 0x8005)\n\n    ,-------------------+-------------------------+----------(+)<-- DIN (MSB first)\n    |                   |                         |           ^\n    |  .----.  .----.   V   .----.       .----.   V   .----.  |\n    `->|  0 |->|  1 |->(+)->|  2 |->...->| 14 |->(+)->| 15 |--+---> DOUT\n       '----'  '----'       '----'       '----'       '----'\n\nREVERSE\n\nBit-reverse LFSR input and output.\n\nDATA_WIDTH\n\nSpecify width of the data bus.  The module will perform one shift per input data bit.\n\nSTYLE\n\nSpecify implementation style.  Can be \"AUTO\", \"LOOP\", or \"REDUCTION\".  When \"AUTO\"\nis selected, implemenation will be \"LOOP\" or \"REDUCTION\" based on synthesis translate\ndirectives.  \"REDUCTION\" and \"LOOP\" are functionally identical, however they simulate\nand synthesize differently.  \"REDUCTION\" is implemented with a loop over a Verilog\nreduction operator.  \"LOOP\" is implemented as a doubly-nested loop with no reduction\noperator.  \"REDUCTION\" is very fast for simulation in iverilog and synthesizes well in\nQuartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing\nproblems with the optimizer.  \"LOOP\" synthesizes will in both ISE and Quartus.  \"AUTO\"\nwill default to \"REDUCTION\" when simulating and \"LOOP\" for synthesizers that obey\nsynthesis translate directives.\n\nSettings for common LFSR/CRC implementations:\n\nName        Configuration           Length  Polynomial      Initial value   Notes\nCRC32       Galois, bit-reverse     32      32'h04c11db7    32'hffffffff    Ethernet FCS; invert final output\nPRBS6       Fibonacci               6       6'h21           any\nPRBS7       Fibonacci               7       7'h41           any\nPRBS9       Fibonacci               9       9'h021          any             ITU V.52\nPRBS10      Fibonacci               10      10'h081         any             ITU\nPRBS11      Fibonacci               11      11'h201         any             ITU O.152\nPRBS15      Fibonacci, inverted     15      15'h4001        any             ITU O.152\nPRBS17      Fibonacci               17      17'h04001       any\nPRBS20      Fibonacci               20      20'h00009       any             ITU V.57\nPRBS23      Fibonacci, inverted     23      23'h040001      any             ITU O.151\nPRBS29      Fibonacci, inverted     29      29'h08000001    any\nPRBS31      Fibonacci, inverted     31      31'h10000001    any\n64b66b      Fibonacci, bit-reverse  58      58'h8000000001  any             10G Ethernet\n128b130b    Galois, bit-reverse     23      23'h210125      any             PCIe gen 3\n\n*/\n\nreg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;\nreg [DATA_WIDTH-1:0] output_reg = 0;\n\nwire [DATA_WIDTH-1:0] lfsr_data;\nwire [LFSR_WIDTH-1:0] lfsr_state;\n\nassign data_out = output_reg;\n\nlfsr #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .LFSR_FEED_FORWARD(0),\n    .REVERSE(REVERSE),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nlfsr_inst (\n    .data_in(data_in),\n    .state_in(state_reg),\n    .data_out(lfsr_data),\n    .state_out(lfsr_state)\n);\n\nalways @(posedge clk) begin\n    if (rst) begin\n        state_reg <= LFSR_INIT;\n        output_reg <= 0;\n    end else begin\n        if (data_in_valid) begin\n            state_reg <= lfsr_state;\n            output_reg <= lfsr_data;\n        end\n    end\nend\n\nendmodule\n\n`resetall\n"
  },
  {
    "path": "tb/lfsr/Makefile",
    "content": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n\nTOPLEVEL_LANG = verilog\n\nSIM ?= icarus\nWAVES ?= 0\n\nCOCOTB_HDL_TIMEUNIT = 1ns\nCOCOTB_HDL_TIMEPRECISION = 1ps\n\nDUT      = lfsr\nTOPLEVEL = $(DUT)\nMODULE   = test_$(DUT)\nVERILOG_SOURCES += ../../rtl/$(DUT).v\n\n# module parameters\nexport PARAM_LFSR_WIDTH ?= 32\nexport PARAM_LFSR_POLY ?= \"32'h4c11db7\"\nexport PARAM_LFSR_CONFIG ?= \"\\\"GALOIS\\\"\"\nexport PARAM_LFSR_FEED_FORWARD ?= 0\nexport PARAM_REVERSE ?= 1\nexport PARAM_DATA_WIDTH ?= 8\nexport PARAM_STYLE ?= \"\\\"AUTO\\\"\"\n\nifeq ($(SIM), icarus)\n\tPLUSARGS += -fst\n\n\tCOMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))\n\n\tifeq ($(WAVES), 1)\n\t\tVERILOG_SOURCES += iverilog_dump.v\n\t\tCOMPILE_ARGS += -s iverilog_dump\n\tendif\nelse ifeq ($(SIM), verilator)\n\tCOMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH\n\n\tCOMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))\n\n\tifeq ($(WAVES), 1)\n\t\tCOMPILE_ARGS += --trace-fst\n\tendif\nendif\n\ninclude $(shell cocotb-config --makefiles)/Makefile.sim\n\niverilog_dump.v:\n\techo 'module iverilog_dump();' > $@\n\techo 'initial begin' >> $@\n\techo '    $$dumpfile(\"$(TOPLEVEL).fst\");' >> $@\n\techo '    $$dumpvars(0, $(TOPLEVEL));' >> $@\n\techo 'end' >> $@\n\techo 'endmodule' >> $@\n\nclean::\n\t@rm -rf iverilog_dump.v\n\t@rm -rf dump.fst $(TOPLEVEL).fst\n"
  },
  {
    "path": "tb/lfsr/test_lfsr.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nimport itertools\nimport logging\nimport os\nimport zlib\n\nimport pytest\nimport cocotb_test.simulator\n\nimport cocotb\nfrom cocotb.triggers import Timer\nfrom cocotb.regression import TestFactory\n\n\nclass TB:\n    def __init__(self, dut):\n        self.dut = dut\n\n        self.log = logging.getLogger(\"cocotb.tb\")\n        self.log.setLevel(logging.DEBUG)\n\n        dut.data_in.setimmediatevalue(0)\n        dut.state_in.setimmediatevalue(0)\n\n\ndef chunks(lst, n, padvalue=None):\n    return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)\n\n\ndef crc32(data):\n    return zlib.crc32(data) & 0xffffffff\n\n\ndef crc32c(data, crc=0xffffffff, poly=0x82f63b78):\n    for d in data:\n        crc = crc ^ d\n        for bit in range(0, 8):\n            if crc & 1:\n                crc = (crc >> 1) ^ poly\n            else:\n                crc = crc >> 1\n    return ~crc & 0xffffffff\n\n\nasync def run_test_crc(dut, ref_crc):\n\n    data_width = len(dut.data_in)\n    byte_lanes = data_width // 8\n\n    state_width = len(dut.state_in)\n    state_mask = 2**state_width-1\n\n    tb = TB(dut)\n\n    await Timer(10, 'ns')\n\n    block = bytes([(x+1)*0x11 for x in range(byte_lanes)])\n\n    dut.state_in.value = state_mask\n    dut.data_in.value = int.from_bytes(block, 'little')\n    await Timer(10, 'ns')\n\n    val = ~dut.state_out.value.integer & state_mask\n    ref = ref_crc(block)\n\n    tb.log.info(\"CRC: 0x%x (ref: 0x%x)\", val, ref)\n\n    assert val == ref\n\n    await Timer(10, 'ns')\n\n    block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))\n\n    dut.state_in.value = state_mask\n    for b in chunks(block, byte_lanes):\n        dut.data_in.value = int.from_bytes(b, 'little')\n        await Timer(10, 'ns')\n        dut.state_in.value = dut.state_out.value\n\n    val = ~dut.state_out.value.integer & state_mask\n    ref = ref_crc(block)\n\n    tb.log.info(\"CRC: 0x%x (ref: 0x%x)\", val, ref)\n\n    assert val == ref\n\n    await Timer(10, 'ns')\n\n\ndef prbs9(state=0x1ff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x10) ^ bool(state & 0x100):\n                state = ((state & 0xff) << 1) | 1\n            else:\n                state = (state & 0xff) << 1\n        yield ~state & 0xff\n\n\ndef prbs31(state=0x7fffffff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x08000000) ^ bool(state & 0x40000000):\n                state = ((state & 0x3fffffff) << 1) | 1\n            else:\n                state = (state & 0x3fffffff) << 1\n        yield ~state & 0xff\n\n\nasync def run_test_prbs(dut, ref_prbs):\n\n    data_width = len(dut.data_in)\n    byte_lanes = data_width // 8\n    data_mask = 2**data_width-1\n\n    state_width = len(dut.state_in)\n    state_mask = 2**state_width-1\n\n    tb = TB(dut)\n\n    await Timer(10, 'ns')\n\n    dut.state_in.value = state_mask\n    dut.data_in.value = 0\n    gen = chunks(ref_prbs(), byte_lanes)\n\n    await Timer(10, 'ns')\n\n    for i in range(512):\n        ref = int.from_bytes(bytes(next(gen)), 'big')\n        val = ~dut.data_out.value.integer & data_mask\n\n        tb.log.info(\"PRBS: 0x%x (ref: 0x%x)\", val, ref)\n\n        assert ref == val\n\n        dut.state_in.value = dut.state_out.value\n\n        await Timer(10, 'ns')\n\n\nif cocotb.SIM_NAME:\n\n    if cocotb.top.LFSR_POLY.value == 0x4c11db7:\n        factory = TestFactory(run_test_crc)\n        factory.add_option(\"ref_crc\", [crc32])\n        factory.generate_tests()\n\n    if cocotb.top.LFSR_POLY.value == 0x1edc6f41:\n        factory = TestFactory(run_test_crc)\n        factory.add_option(\"ref_crc\", [crc32c])\n        factory.generate_tests()\n\n    if cocotb.top.LFSR_POLY.value == 0x021:\n        factory = TestFactory(run_test_prbs)\n        factory.add_option(\"ref_prbs\", [prbs9])\n        factory.generate_tests()\n\n    if cocotb.top.LFSR_POLY.value == 0x10000001:\n        factory = TestFactory(run_test_prbs)\n        factory.add_option(\"ref_prbs\", [prbs31])\n        factory.generate_tests()\n\n\n# cocotb-test\n\ntests_dir = os.path.abspath(os.path.dirname(__file__))\nrtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))\n\n\n@pytest.mark.parametrize(\"style\", [\"AUTO\", \"LOOP\"])\n@pytest.mark.parametrize((\"lfsr_width\", \"lfsr_poly\", \"lfsr_config\", \"reverse\", \"data_width\"), [\n            (32, \"32'h4c11db7\", \"GALOIS\", 1, 8),\n            (32, \"32'h4c11db7\", \"GALOIS\", 1, 64),\n            (32, \"32'h1edc6f41\", \"GALOIS\", 1, 8),\n            (32, \"32'h1edc6f41\", \"GALOIS\", 1, 64),\n            (9,  \"9'h021\", \"FIBONACCI\", 0, 8),\n            (9,  \"9'h021\", \"FIBONACCI\", 0, 64),\n            (31, \"31'h10000001\", \"FIBONACCI\", 0, 8),\n            (31, \"31'h10000001\", \"FIBONACCI\", 0, 64),\n        ])\ndef test_lfsr(request, lfsr_width, lfsr_poly, lfsr_config, reverse, data_width, style):\n    dut = \"lfsr\"\n    module = os.path.splitext(os.path.basename(__file__))[0]\n    toplevel = dut\n\n    verilog_sources = [\n        os.path.join(rtl_dir, f\"{dut}.v\"),\n    ]\n\n    parameters = {}\n\n    parameters['LFSR_WIDTH'] = lfsr_width\n    parameters['LFSR_POLY'] = lfsr_poly\n    parameters['LFSR_CONFIG'] = f'\"{lfsr_config}\"'\n    parameters['LFSR_FEED_FORWARD'] = 0\n    parameters['REVERSE'] = reverse\n    parameters['DATA_WIDTH'] = data_width\n    parameters['STYLE'] = f'\"{style}\"'\n\n    extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}\n\n    sim_build = os.path.join(tests_dir, \"sim_build\",\n        request.node.name.replace('[', '-').replace(']', ''))\n\n    cocotb_test.simulator.run(\n        python_search=[tests_dir],\n        verilog_sources=verilog_sources,\n        toplevel=toplevel,\n        module=module,\n        parameters=parameters,\n        sim_build=sim_build,\n        extra_env=extra_env,\n    )\n"
  },
  {
    "path": "tb/lfsr_crc/Makefile",
    "content": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n\nTOPLEVEL_LANG = verilog\n\nSIM ?= icarus\nWAVES ?= 0\n\nCOCOTB_HDL_TIMEUNIT = 1ns\nCOCOTB_HDL_TIMEPRECISION = 1ps\n\nDUT      = lfsr_crc\nTOPLEVEL = $(DUT)\nMODULE   = test_$(DUT)\nVERILOG_SOURCES += ../../rtl/$(DUT).v\nVERILOG_SOURCES += ../../rtl/lfsr.v\n\n# module parameters\nexport PARAM_LFSR_WIDTH ?= 32\nexport PARAM_LFSR_POLY ?= \"32'h4c11db7\"\nexport PARAM_LFSR_INIT ?= \"32'hffffffff\"\nexport PARAM_LFSR_CONFIG ?= \"\\\"GALOIS\\\"\"\nexport PARAM_REVERSE ?= 1\nexport PARAM_INVERT ?= 1\nexport PARAM_DATA_WIDTH ?= 8\nexport PARAM_STYLE ?= \"\\\"AUTO\\\"\"\n\nifeq ($(SIM), icarus)\n\tPLUSARGS += -fst\n\n\tCOMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))\n\n\tifeq ($(WAVES), 1)\n\t\tVERILOG_SOURCES += iverilog_dump.v\n\t\tCOMPILE_ARGS += -s iverilog_dump\n\tendif\nelse ifeq ($(SIM), verilator)\n\tCOMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH\n\n\tCOMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))\n\n\tifeq ($(WAVES), 1)\n\t\tCOMPILE_ARGS += --trace-fst\n\tendif\nendif\n\ninclude $(shell cocotb-config --makefiles)/Makefile.sim\n\niverilog_dump.v:\n\techo 'module iverilog_dump();' > $@\n\techo 'initial begin' >> $@\n\techo '    $$dumpfile(\"$(TOPLEVEL).fst\");' >> $@\n\techo '    $$dumpvars(0, $(TOPLEVEL));' >> $@\n\techo 'end' >> $@\n\techo 'endmodule' >> $@\n\nclean::\n\t@rm -rf iverilog_dump.v\n\t@rm -rf dump.fst $(TOPLEVEL).fst\n"
  },
  {
    "path": "tb/lfsr_crc/test_lfsr_crc.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nimport itertools\nimport logging\nimport os\nimport zlib\n\nimport pytest\nimport cocotb_test.simulator\n\nimport cocotb\nfrom cocotb.clock import Clock\nfrom cocotb.triggers import RisingEdge\nfrom cocotb.regression import TestFactory\n\n\nclass TB:\n    def __init__(self, dut):\n        self.dut = dut\n\n        self.log = logging.getLogger(\"cocotb.tb\")\n        self.log.setLevel(logging.DEBUG)\n\n        cocotb.start_soon(Clock(dut.clk, 10, units=\"ns\").start())\n\n        dut.data_in.setimmediatevalue(0)\n        dut.data_in_valid.setimmediatevalue(0)\n\n    async def reset(self):\n        self.dut.rst.setimmediatevalue(0)\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n        self.dut.rst.value = 1\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n        self.dut.rst.value = 0\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n\n\ndef chunks(lst, n, padvalue=None):\n    return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)\n\n\ndef crc32(data):\n    return zlib.crc32(data) & 0xffffffff\n\n\ndef crc32c(data, crc=0xffffffff, poly=0x82f63b78):\n    for d in data:\n        crc = crc ^ d\n        for bit in range(0, 8):\n            if crc & 1:\n                crc = (crc >> 1) ^ poly\n            else:\n                crc = crc >> 1\n    return ~crc & 0xffffffff\n\n\nasync def run_test_crc(dut, ref_crc):\n\n    data_width = len(dut.data_in)\n    byte_lanes = data_width // 8\n\n    tb = TB(dut)\n\n    await tb.reset()\n\n    block = bytes([(x+1)*0x11 for x in range(byte_lanes)])\n\n    dut.data_in.value = int.from_bytes(block, 'little')\n    dut.data_in_valid.value = 1\n    await RisingEdge(dut.clk)\n    dut.data_in_valid.value = 0\n\n    await RisingEdge(dut.clk)\n    val = dut.crc_out.value.integer\n    ref = ref_crc(block)\n\n    tb.log.info(\"CRC: 0x%x (ref: 0x%x)\", val, ref)\n\n    assert val == ref\n\n    await tb.reset()\n\n    block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))\n\n    for b in chunks(block, byte_lanes):\n        dut.data_in.value = int.from_bytes(b, 'little')\n        dut.data_in_valid.value = 1\n        await RisingEdge(dut.clk)\n    dut.data_in_valid.value = 0\n\n    await RisingEdge(dut.clk)\n    val = dut.crc_out.value.integer\n    ref = ref_crc(block)\n\n    tb.log.info(\"CRC: 0x%x (ref: 0x%x)\", val, ref)\n\n    assert val == ref\n\n    await RisingEdge(dut.clk)\n    await RisingEdge(dut.clk)\n\n\nif cocotb.SIM_NAME:\n\n    if cocotb.top.LFSR_POLY.value == 0x4c11db7:\n        factory = TestFactory(run_test_crc)\n        factory.add_option(\"ref_crc\", [crc32])\n        factory.generate_tests()\n\n    if cocotb.top.LFSR_POLY.value == 0x1edc6f41:\n        factory = TestFactory(run_test_crc)\n        factory.add_option(\"ref_crc\", [crc32c])\n        factory.generate_tests()\n\n\n# cocotb-test\n\ntests_dir = os.path.abspath(os.path.dirname(__file__))\nrtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))\n\n\n@pytest.mark.parametrize(\"style\", [\"AUTO\", \"LOOP\"])\n@pytest.mark.parametrize((\"lfsr_width\", \"lfsr_poly\", \"lfsr_init\", \"lfsr_config\", \"reverse\", \"invert\", \"data_width\"), [\n            (32, \"32'h4c11db7\", \"32'hffffffff\", \"GALOIS\", 1, 1, 8),\n            (32, \"32'h4c11db7\", \"32'hffffffff\", \"GALOIS\", 1, 1, 64),\n            (32, \"32'h1edc6f41\", \"32'hffffffff\", \"GALOIS\", 1, 1, 8),\n            (32, \"32'h1edc6f41\", \"32'hffffffff\", \"GALOIS\", 1, 1, 64),\n        ])\ndef test_lfsr_crc(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, invert, data_width, style):\n    dut = \"lfsr_crc\"\n    module = os.path.splitext(os.path.basename(__file__))[0]\n    toplevel = dut\n\n    verilog_sources = [\n        os.path.join(rtl_dir, f\"{dut}.v\"),\n        os.path.join(rtl_dir, \"lfsr.v\"),\n    ]\n\n    parameters = {}\n\n    parameters['LFSR_WIDTH'] = lfsr_width\n    parameters['LFSR_POLY'] = lfsr_poly\n    parameters['LFSR_INIT'] = lfsr_init\n    parameters['LFSR_CONFIG'] = f'\"{lfsr_config}\"'\n    parameters['REVERSE'] = reverse\n    parameters['INVERT'] = invert\n    parameters['DATA_WIDTH'] = data_width\n    parameters['STYLE'] = f'\"{style}\"'\n\n    extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}\n\n    sim_build = os.path.join(tests_dir, \"sim_build\",\n        request.node.name.replace('[', '-').replace(']', ''))\n\n    cocotb_test.simulator.run(\n        python_search=[tests_dir],\n        verilog_sources=verilog_sources,\n        toplevel=toplevel,\n        module=module,\n        parameters=parameters,\n        sim_build=sim_build,\n        extra_env=extra_env,\n    )\n"
  },
  {
    "path": "tb/lfsr_descramble/Makefile",
    "content": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n\nTOPLEVEL_LANG = verilog\n\nSIM ?= icarus\nWAVES ?= 0\n\nCOCOTB_HDL_TIMEUNIT = 1ns\nCOCOTB_HDL_TIMEPRECISION = 1ps\n\nDUT      = lfsr_descramble\nTOPLEVEL = $(DUT)\nMODULE   = test_$(DUT)\nVERILOG_SOURCES += ../../rtl/$(DUT).v\nVERILOG_SOURCES += ../../rtl/lfsr.v\n\n# module parameters\nexport PARAM_LFSR_WIDTH ?= 58\nexport PARAM_LFSR_POLY ?= \"58'h8000000001\"\nexport PARAM_LFSR_INIT ?= \"58'h3ffffffffffffff\"\nexport PARAM_LFSR_CONFIG ?= \"\\\"FIBONACCI\\\"\"\nexport PARAM_REVERSE ?= 1\nexport PARAM_DATA_WIDTH ?= 8\nexport PARAM_STYLE ?= \"\\\"AUTO\\\"\"\n\nifeq ($(SIM), icarus)\n\tPLUSARGS += -fst\n\n\tCOMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))\n\n\tifeq ($(WAVES), 1)\n\t\tVERILOG_SOURCES += iverilog_dump.v\n\t\tCOMPILE_ARGS += -s iverilog_dump\n\tendif\nelse ifeq ($(SIM), verilator)\n\tCOMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH\n\n\tCOMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))\n\n\tifeq ($(WAVES), 1)\n\t\tCOMPILE_ARGS += --trace-fst\n\tendif\nendif\n\ninclude $(shell cocotb-config --makefiles)/Makefile.sim\n\niverilog_dump.v:\n\techo 'module iverilog_dump();' > $@\n\techo 'initial begin' >> $@\n\techo '    $$dumpfile(\"$(TOPLEVEL).fst\");' >> $@\n\techo '    $$dumpvars(0, $(TOPLEVEL));' >> $@\n\techo 'end' >> $@\n\techo 'endmodule' >> $@\n\nclean::\n\t@rm -rf iverilog_dump.v\n\t@rm -rf dump.fst $(TOPLEVEL).fst\n"
  },
  {
    "path": "tb/lfsr_descramble/test_lfsr_descramble.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nimport itertools\nimport logging\nimport os\n\nimport pytest\nimport cocotb_test.simulator\n\nimport cocotb\nfrom cocotb.clock import Clock\nfrom cocotb.triggers import RisingEdge\nfrom cocotb.regression import TestFactory\n\n\nclass TB:\n    def __init__(self, dut):\n        self.dut = dut\n\n        self.log = logging.getLogger(\"cocotb.tb\")\n        self.log.setLevel(logging.DEBUG)\n\n        cocotb.start_soon(Clock(dut.clk, 10, units=\"ns\").start())\n\n        dut.data_in.setimmediatevalue(0)\n        dut.data_in_valid.setimmediatevalue(0)\n\n    async def reset(self):\n        self.dut.rst.setimmediatevalue(0)\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n        self.dut.rst.value = 1\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n        self.dut.rst.value = 0\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n\n\ndef chunks(lst, n, padvalue=None):\n    return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)\n\n\ndef scramble_64b66b(data, state=0x3ffffffffffffff):\n    data_out = bytearray()\n    for d in data:\n        b = 0\n        for i in range(8):\n            if bool(state & (1 << 38)) ^ bool(state & (1 << 57)) ^ bool(d & (1 << i)):\n                state = ((state & 0x1ffffffffffffff) << 1) | 1\n                b = b | (1 << i)\n            else:\n                state = (state & 0x1ffffffffffffff) << 1\n        data_out.append(b)\n    return data_out\n\n\ndef descramble_64b66b(data, state=0x3ffffffffffffff):\n    data_out = bytearray()\n    for d in data:\n        b = 0\n        for i in range(8):\n            if bool(state & (1 << 38)) ^ bool(state & (1 << 57)) ^ bool(d & (1 << i)):\n                b = b | (1 << i)\n            state = (state & 0x1ffffffffffffff) << 1 | bool(d & (1 << i))\n        data_out += bytearray([b])\n    return data_out\n\n\nasync def run_test_descramble(dut, ref_scramble):\n\n    data_width = len(dut.data_in)\n    byte_lanes = data_width // 8\n\n    tb = TB(dut)\n\n    await tb.reset()\n\n    block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))\n\n    scr = scramble_64b66b(block)\n\n    dscr = descramble_64b66b(scr)\n\n    assert dscr == block\n\n    ref_iter = iter(chunks(block, byte_lanes))\n\n    first = True\n    for b in chunks(scr, byte_lanes):\n        dut.data_in.value = int.from_bytes(b, 'little')\n        dut.data_in_valid.value = 1\n        await RisingEdge(dut.clk)\n\n        val = dut.data_out.value.integer\n\n        if not first:\n            ref = int.from_bytes(bytes(next(ref_iter)), 'little')\n\n            tb.log.info(\"Descrambled: 0x%x (ref: 0x%x)\", val, ref)\n\n            assert ref == val\n\n        first = False\n\n    dut.data_in_valid.value = 0\n\n    await RisingEdge(dut.clk)\n\n\nif cocotb.SIM_NAME:\n\n    # if cocotb.top.LFSR_POLY.value == 0x8000000001:\n    if cocotb.top.LFSR_WIDTH == 58:\n        factory = TestFactory(run_test_descramble)\n        factory.add_option(\"ref_scramble\", [scramble_64b66b])\n        factory.generate_tests()\n\n\n# cocotb-test\n\ntests_dir = os.path.abspath(os.path.dirname(__file__))\nrtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))\n\n\n@pytest.mark.parametrize(\"style\", [\"AUTO\", \"LOOP\"])\n@pytest.mark.parametrize((\"lfsr_width\", \"lfsr_poly\", \"lfsr_init\", \"lfsr_config\", \"reverse\", \"data_width\"), [\n            (58,  \"58'h8000000001\", \"58'h3ffffffffffffff\", \"FIBONACCI\", 1, 8),\n            (58,  \"58'h8000000001\", \"58'h3ffffffffffffff\", \"FIBONACCI\", 1, 64),\n        ])\ndef test_lfsr_descramble(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, data_width, style):\n    dut = \"lfsr_descramble\"\n    module = os.path.splitext(os.path.basename(__file__))[0]\n    toplevel = dut\n\n    verilog_sources = [\n        os.path.join(rtl_dir, f\"{dut}.v\"),\n        os.path.join(rtl_dir, \"lfsr.v\"),\n    ]\n\n    parameters = {}\n\n    parameters['LFSR_WIDTH'] = lfsr_width\n    parameters['LFSR_POLY'] = lfsr_poly\n    parameters['LFSR_INIT'] = lfsr_init\n    parameters['LFSR_CONFIG'] = f'\"{lfsr_config}\"'\n    parameters['REVERSE'] = reverse\n    parameters['DATA_WIDTH'] = data_width\n    parameters['STYLE'] = f'\"{style}\"'\n\n    extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}\n\n    sim_build = os.path.join(tests_dir, \"sim_build\",\n        request.node.name.replace('[', '-').replace(']', ''))\n\n    cocotb_test.simulator.run(\n        python_search=[tests_dir],\n        verilog_sources=verilog_sources,\n        toplevel=toplevel,\n        module=module,\n        parameters=parameters,\n        sim_build=sim_build,\n        extra_env=extra_env,\n    )\n"
  },
  {
    "path": "tb/lfsr_prbs_check/Makefile",
    "content": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n\nTOPLEVEL_LANG = verilog\n\nSIM ?= icarus\nWAVES ?= 0\n\nCOCOTB_HDL_TIMEUNIT = 1ns\nCOCOTB_HDL_TIMEPRECISION = 1ps\n\nDUT      = lfsr_prbs_check\nTOPLEVEL = $(DUT)\nMODULE   = test_$(DUT)\nVERILOG_SOURCES += ../../rtl/$(DUT).v\nVERILOG_SOURCES += ../../rtl/lfsr.v\n\n# module parameters\nexport PARAM_LFSR_WIDTH ?= 31\nexport PARAM_LFSR_POLY ?= \"31'h10000001\"\nexport PARAM_LFSR_INIT ?= \"31'h7fffffff\"\nexport PARAM_LFSR_CONFIG ?= \"\\\"FIBONACCI\\\"\"\nexport PARAM_REVERSE ?= 0\nexport PARAM_INVERT ?= 1\nexport PARAM_DATA_WIDTH ?= 8\nexport PARAM_STYLE ?= \"\\\"AUTO\\\"\"\n\nifeq ($(SIM), icarus)\n\tPLUSARGS += -fst\n\n\tCOMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))\n\n\tifeq ($(WAVES), 1)\n\t\tVERILOG_SOURCES += iverilog_dump.v\n\t\tCOMPILE_ARGS += -s iverilog_dump\n\tendif\nelse ifeq ($(SIM), verilator)\n\tCOMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH\n\n\tCOMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))\n\n\tifeq ($(WAVES), 1)\n\t\tCOMPILE_ARGS += --trace-fst\n\tendif\nendif\n\ninclude $(shell cocotb-config --makefiles)/Makefile.sim\n\niverilog_dump.v:\n\techo 'module iverilog_dump();' > $@\n\techo 'initial begin' >> $@\n\techo '    $$dumpfile(\"$(TOPLEVEL).fst\");' >> $@\n\techo '    $$dumpvars(0, $(TOPLEVEL));' >> $@\n\techo 'end' >> $@\n\techo 'endmodule' >> $@\n\nclean::\n\t@rm -rf iverilog_dump.v\n\t@rm -rf dump.fst $(TOPLEVEL).fst\n"
  },
  {
    "path": "tb/lfsr_prbs_check/test_lfsr_prbs_check.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nimport itertools\nimport logging\nimport os\n\nimport pytest\nimport cocotb_test.simulator\n\nimport cocotb\nfrom cocotb.clock import Clock\nfrom cocotb.triggers import RisingEdge\nfrom cocotb.regression import TestFactory\n\n\nclass TB:\n    def __init__(self, dut):\n        self.dut = dut\n\n        self.log = logging.getLogger(\"cocotb.tb\")\n        self.log.setLevel(logging.DEBUG)\n\n        cocotb.start_soon(Clock(dut.clk, 10, units=\"ns\").start())\n\n        dut.data_in.setimmediatevalue(0)\n        dut.data_in_valid.setimmediatevalue(0)\n\n    async def reset(self):\n        self.dut.rst.setimmediatevalue(0)\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n        self.dut.rst.value = 1\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n        self.dut.rst.value = 0\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n\n\ndef chunks(lst, n, padvalue=None):\n    return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)\n\n\ndef prbs9(state=0x1ff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x10) ^ bool(state & 0x100):\n                state = ((state & 0xff) << 1) | 1\n            else:\n                state = (state & 0xff) << 1\n        yield ~state & 0xff\n\n\ndef prbs31(state=0x7fffffff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x08000000) ^ bool(state & 0x40000000):\n                state = ((state & 0x3fffffff) << 1) | 1\n            else:\n                state = (state & 0x3fffffff) << 1\n        yield ~state & 0xff\n\n\ndef count_set_bits(n):\n    cnt = 0\n    while n:\n        n &= n - 1\n        cnt += 1\n    return cnt\n\n\nasync def run_test_prbs(dut, ref_prbs):\n\n    data_width = len(dut.data_out)\n    byte_lanes = data_width // 8\n\n    tb = TB(dut)\n\n    await tb.reset()\n\n    gen = chunks(ref_prbs(), byte_lanes)\n\n    err_cnt = 0\n\n    for i in range(512):\n\n        dut.data_in.value = int.from_bytes(bytes(next(gen)), 'big')\n        dut.data_in_valid.value = 1\n\n        val = dut.data_out.value.integer\n\n        tb.log.info(\"Error value: 0x%x\", val)\n\n        err_cnt += count_set_bits(val)\n\n        assert val == 0\n\n        await RisingEdge(dut.clk)\n\n    dut.data_in_valid.value = 0\n\n    tb.log.info(\"Error count: %d\", err_cnt)\n\n    assert err_cnt == 0\n\n    await tb.reset()\n\n    tb.log.info(\"Single error test\")\n\n    gen = chunks(ref_prbs(), byte_lanes)\n\n    err_cnt = 0\n\n    for i in range(64):\n\n        val = int.from_bytes(bytes(next(gen)), 'big')\n\n        if i == 32:\n            val = val ^ (1 << (data_width // 2))\n\n        dut.data_in.value = val\n        dut.data_in_valid.value = 1\n\n        val = dut.data_out.value.integer\n\n        tb.log.info(\"Error value: 0x%x\", val)\n\n        err_cnt += count_set_bits(val)\n\n        await RisingEdge(dut.clk)\n\n    dut.data_in_valid.value = 0\n\n    tb.log.info(\"Error count: %d\", err_cnt)\n\n    # one bit set per tap\n    assert err_cnt == 3\n\n\nif cocotb.SIM_NAME:\n\n    if cocotb.top.LFSR_POLY.value == 0x021:\n        factory = TestFactory(run_test_prbs)\n        factory.add_option(\"ref_prbs\", [prbs9])\n        factory.generate_tests()\n\n    if cocotb.top.LFSR_POLY.value == 0x10000001:\n        factory = TestFactory(run_test_prbs)\n        factory.add_option(\"ref_prbs\", [prbs31])\n        factory.generate_tests()\n\n\n# cocotb-test\n\ntests_dir = os.path.abspath(os.path.dirname(__file__))\nrtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))\n\n\n@pytest.mark.parametrize(\"style\", [\"AUTO\", \"LOOP\"])\n@pytest.mark.parametrize((\"lfsr_width\", \"lfsr_poly\", \"lfsr_init\", \"lfsr_config\", \"reverse\", \"invert\", \"data_width\"), [\n            (9,  \"9'h021\", \"9'h1ff\", \"FIBONACCI\", 0, 1, 8),\n            (9,  \"9'h021\", \"9'h1ff\", \"FIBONACCI\", 0, 1, 64),\n            (31, \"31'h10000001\", \"31'h7fffffff\", \"FIBONACCI\", 0, 1, 8),\n            (31, \"31'h10000001\", \"31'h7fffffff\", \"FIBONACCI\", 0, 1, 64),\n        ])\ndef test_lfsr_prbs_check(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, invert, data_width, style):\n    dut = \"lfsr_prbs_check\"\n    module = os.path.splitext(os.path.basename(__file__))[0]\n    toplevel = dut\n\n    verilog_sources = [\n        os.path.join(rtl_dir, f\"{dut}.v\"),\n        os.path.join(rtl_dir, \"lfsr.v\"),\n    ]\n\n    parameters = {}\n\n    parameters['LFSR_WIDTH'] = lfsr_width\n    parameters['LFSR_POLY'] = lfsr_poly\n    parameters['LFSR_INIT'] = lfsr_init\n    parameters['LFSR_CONFIG'] = f'\"{lfsr_config}\"'\n    parameters['REVERSE'] = reverse\n    parameters['INVERT'] = invert\n    parameters['DATA_WIDTH'] = data_width\n    parameters['STYLE'] = f'\"{style}\"'\n\n    extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}\n\n    sim_build = os.path.join(tests_dir, \"sim_build\",\n        request.node.name.replace('[', '-').replace(']', ''))\n\n    cocotb_test.simulator.run(\n        python_search=[tests_dir],\n        verilog_sources=verilog_sources,\n        toplevel=toplevel,\n        module=module,\n        parameters=parameters,\n        sim_build=sim_build,\n        extra_env=extra_env,\n    )\n"
  },
  {
    "path": "tb/lfsr_prbs_gen/Makefile",
    "content": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n\nTOPLEVEL_LANG = verilog\n\nSIM ?= icarus\nWAVES ?= 0\n\nCOCOTB_HDL_TIMEUNIT = 1ns\nCOCOTB_HDL_TIMEPRECISION = 1ps\n\nDUT      = lfsr_prbs_gen\nTOPLEVEL = $(DUT)\nMODULE   = test_$(DUT)\nVERILOG_SOURCES += ../../rtl/$(DUT).v\nVERILOG_SOURCES += ../../rtl/lfsr.v\n\n# module parameters\nexport PARAM_LFSR_WIDTH ?= 31\nexport PARAM_LFSR_POLY ?= \"31'h10000001\"\nexport PARAM_LFSR_INIT ?= \"31'h7fffffff\"\nexport PARAM_LFSR_CONFIG ?= \"\\\"FIBONACCI\\\"\"\nexport PARAM_REVERSE ?= 0\nexport PARAM_INVERT ?= 1\nexport PARAM_DATA_WIDTH ?= 8\nexport PARAM_STYLE ?= \"\\\"AUTO\\\"\"\n\nifeq ($(SIM), icarus)\n\tPLUSARGS += -fst\n\n\tCOMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))\n\n\tifeq ($(WAVES), 1)\n\t\tVERILOG_SOURCES += iverilog_dump.v\n\t\tCOMPILE_ARGS += -s iverilog_dump\n\tendif\nelse ifeq ($(SIM), verilator)\n\tCOMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH\n\n\tCOMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))\n\n\tifeq ($(WAVES), 1)\n\t\tCOMPILE_ARGS += --trace-fst\n\tendif\nendif\n\ninclude $(shell cocotb-config --makefiles)/Makefile.sim\n\niverilog_dump.v:\n\techo 'module iverilog_dump();' > $@\n\techo 'initial begin' >> $@\n\techo '    $$dumpfile(\"$(TOPLEVEL).fst\");' >> $@\n\techo '    $$dumpvars(0, $(TOPLEVEL));' >> $@\n\techo 'end' >> $@\n\techo 'endmodule' >> $@\n\nclean::\n\t@rm -rf iverilog_dump.v\n\t@rm -rf dump.fst $(TOPLEVEL).fst\n"
  },
  {
    "path": "tb/lfsr_prbs_gen/test_lfsr_prbs_gen.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nimport itertools\nimport logging\nimport os\n\nimport pytest\nimport cocotb_test.simulator\n\nimport cocotb\nfrom cocotb.clock import Clock\nfrom cocotb.triggers import RisingEdge\nfrom cocotb.regression import TestFactory\n\n\nclass TB:\n    def __init__(self, dut):\n        self.dut = dut\n\n        self.log = logging.getLogger(\"cocotb.tb\")\n        self.log.setLevel(logging.DEBUG)\n\n        cocotb.start_soon(Clock(dut.clk, 10, units=\"ns\").start())\n\n        dut.enable.setimmediatevalue(0)\n\n    async def reset(self):\n        self.dut.rst.setimmediatevalue(0)\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n        self.dut.rst.value = 1\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n        self.dut.rst.value = 0\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n\n\ndef chunks(lst, n, padvalue=None):\n    return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)\n\n\ndef prbs9(state=0x1ff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x10) ^ bool(state & 0x100):\n                state = ((state & 0xff) << 1) | 1\n            else:\n                state = (state & 0xff) << 1\n        yield ~state & 0xff\n\n\ndef prbs31(state=0x7fffffff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x08000000) ^ bool(state & 0x40000000):\n                state = ((state & 0x3fffffff) << 1) | 1\n            else:\n                state = (state & 0x3fffffff) << 1\n        yield ~state & 0xff\n\n\nasync def run_test_prbs(dut, ref_prbs):\n\n    data_width = len(dut.data_out)\n    byte_lanes = data_width // 8\n\n    tb = TB(dut)\n\n    await tb.reset()\n\n    gen = chunks(ref_prbs(), byte_lanes)\n\n    dut.enable.value = 1\n    await RisingEdge(dut.clk)\n\n    for i in range(512):\n        ref = int.from_bytes(bytes(next(gen)), 'big')\n        val = dut.data_out.value.integer\n\n        tb.log.info(\"PRBS: 0x%x (ref: 0x%x)\", val, ref)\n\n        assert ref == val\n\n        await RisingEdge(dut.clk)\n\n\nif cocotb.SIM_NAME:\n\n    if cocotb.top.LFSR_POLY.value == 0x021:\n        factory = TestFactory(run_test_prbs)\n        factory.add_option(\"ref_prbs\", [prbs9])\n        factory.generate_tests()\n\n    if cocotb.top.LFSR_POLY.value == 0x10000001:\n        factory = TestFactory(run_test_prbs)\n        factory.add_option(\"ref_prbs\", [prbs31])\n        factory.generate_tests()\n\n\n# cocotb-test\n\ntests_dir = os.path.abspath(os.path.dirname(__file__))\nrtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))\n\n\n@pytest.mark.parametrize(\"style\", [\"AUTO\", \"LOOP\"])\n@pytest.mark.parametrize((\"lfsr_width\", \"lfsr_poly\", \"lfsr_init\", \"lfsr_config\", \"reverse\", \"invert\", \"data_width\"), [\n            (9,  \"9'h021\", \"9'h1ff\", \"FIBONACCI\", 0, 1, 8),\n            (9,  \"9'h021\", \"9'h1ff\", \"FIBONACCI\", 0, 1, 64),\n            (31, \"31'h10000001\", \"31'h7fffffff\", \"FIBONACCI\", 0, 1, 8),\n            (31, \"31'h10000001\", \"31'h7fffffff\", \"FIBONACCI\", 0, 1, 64),\n        ])\ndef test_lfsr_prbs_gen(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, invert, data_width, style):\n    dut = \"lfsr_prbs_gen\"\n    module = os.path.splitext(os.path.basename(__file__))[0]\n    toplevel = dut\n\n    verilog_sources = [\n        os.path.join(rtl_dir, f\"{dut}.v\"),\n        os.path.join(rtl_dir, \"lfsr.v\"),\n    ]\n\n    parameters = {}\n\n    parameters['LFSR_WIDTH'] = lfsr_width\n    parameters['LFSR_POLY'] = lfsr_poly\n    parameters['LFSR_INIT'] = lfsr_init\n    parameters['LFSR_CONFIG'] = f'\"{lfsr_config}\"'\n    parameters['REVERSE'] = reverse\n    parameters['INVERT'] = invert\n    parameters['DATA_WIDTH'] = data_width\n    parameters['STYLE'] = f'\"{style}\"'\n\n    extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}\n\n    sim_build = os.path.join(tests_dir, \"sim_build\",\n        request.node.name.replace('[', '-').replace(']', ''))\n\n    cocotb_test.simulator.run(\n        python_search=[tests_dir],\n        verilog_sources=verilog_sources,\n        toplevel=toplevel,\n        module=module,\n        parameters=parameters,\n        sim_build=sim_build,\n        extra_env=extra_env,\n    )\n"
  },
  {
    "path": "tb/lfsr_scramble/Makefile",
    "content": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n# THE SOFTWARE.\n\nTOPLEVEL_LANG = verilog\n\nSIM ?= icarus\nWAVES ?= 0\n\nCOCOTB_HDL_TIMEUNIT = 1ns\nCOCOTB_HDL_TIMEPRECISION = 1ps\n\nDUT      = lfsr_scramble\nTOPLEVEL = $(DUT)\nMODULE   = test_$(DUT)\nVERILOG_SOURCES += ../../rtl/$(DUT).v\nVERILOG_SOURCES += ../../rtl/lfsr.v\n\n# module parameters\nexport PARAM_LFSR_WIDTH ?= 58\nexport PARAM_LFSR_POLY ?= \"58'h8000000001\"\nexport PARAM_LFSR_INIT ?= \"58'h3ffffffffffffff\"\nexport PARAM_LFSR_CONFIG ?= \"\\\"FIBONACCI\\\"\"\nexport PARAM_REVERSE ?= 1\nexport PARAM_DATA_WIDTH ?= 8\nexport PARAM_STYLE ?= \"\\\"AUTO\\\"\"\n\nifeq ($(SIM), icarus)\n\tPLUSARGS += -fst\n\n\tCOMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))\n\n\tifeq ($(WAVES), 1)\n\t\tVERILOG_SOURCES += iverilog_dump.v\n\t\tCOMPILE_ARGS += -s iverilog_dump\n\tendif\nelse ifeq ($(SIM), verilator)\n\tCOMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH\n\n\tCOMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))\n\n\tifeq ($(WAVES), 1)\n\t\tCOMPILE_ARGS += --trace-fst\n\tendif\nendif\n\ninclude $(shell cocotb-config --makefiles)/Makefile.sim\n\niverilog_dump.v:\n\techo 'module iverilog_dump();' > $@\n\techo 'initial begin' >> $@\n\techo '    $$dumpfile(\"$(TOPLEVEL).fst\");' >> $@\n\techo '    $$dumpvars(0, $(TOPLEVEL));' >> $@\n\techo 'end' >> $@\n\techo 'endmodule' >> $@\n\nclean::\n\t@rm -rf iverilog_dump.v\n\t@rm -rf dump.fst $(TOPLEVEL).fst\n"
  },
  {
    "path": "tb/lfsr_scramble/test_lfsr_scramble.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nimport itertools\nimport logging\nimport os\n\nimport pytest\nimport cocotb_test.simulator\n\nimport cocotb\nfrom cocotb.clock import Clock\nfrom cocotb.triggers import RisingEdge\nfrom cocotb.regression import TestFactory\n\n\nclass TB:\n    def __init__(self, dut):\n        self.dut = dut\n\n        self.log = logging.getLogger(\"cocotb.tb\")\n        self.log.setLevel(logging.DEBUG)\n\n        cocotb.start_soon(Clock(dut.clk, 10, units=\"ns\").start())\n\n        dut.data_in.setimmediatevalue(0)\n        dut.data_in_valid.setimmediatevalue(0)\n\n    async def reset(self):\n        self.dut.rst.setimmediatevalue(0)\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n        self.dut.rst.value = 1\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n        self.dut.rst.value = 0\n        await RisingEdge(self.dut.clk)\n        await RisingEdge(self.dut.clk)\n\n\ndef chunks(lst, n, padvalue=None):\n    return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)\n\n\ndef scramble_64b66b(data, state=0x3ffffffffffffff):\n    data_out = bytearray()\n    for d in data:\n        b = 0\n        for i in range(8):\n            if bool(state & (1 << 38)) ^ bool(state & (1 << 57)) ^ bool(d & (1 << i)):\n                state = ((state & 0x1ffffffffffffff) << 1) | 1\n                b = b | (1 << i)\n            else:\n                state = (state & 0x1ffffffffffffff) << 1\n        data_out.append(b)\n    return data_out\n\n\nasync def run_test_scramble(dut, ref_scramble):\n\n    data_width = len(dut.data_in)\n    byte_lanes = data_width // 8\n\n    tb = TB(dut)\n\n    await tb.reset()\n\n    block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))\n\n    scr = scramble_64b66b(block)\n    scr_iter = iter(chunks(scr, byte_lanes))\n\n    first = True\n    for b in chunks(block, byte_lanes):\n        dut.data_in.value = int.from_bytes(b, 'little')\n        dut.data_in_valid.value = 1\n        await RisingEdge(dut.clk)\n\n        val = dut.data_out.value.integer\n\n        if not first:\n            ref = int.from_bytes(bytes(next(scr_iter)), 'little')\n\n            tb.log.info(\"Scrambled: 0x%x (ref: 0x%x)\", val, ref)\n\n            assert ref == val\n\n        first = False\n\n    dut.data_in_valid.value = 0\n\n    await RisingEdge(dut.clk)\n\n\nif cocotb.SIM_NAME:\n\n    # if cocotb.top.LFSR_POLY.value == 0x8000000001:\n    if cocotb.top.LFSR_WIDTH == 58:\n        factory = TestFactory(run_test_scramble)\n        factory.add_option(\"ref_scramble\", [scramble_64b66b])\n        factory.generate_tests()\n\n\n# cocotb-test\n\ntests_dir = os.path.abspath(os.path.dirname(__file__))\nrtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))\n\n\n@pytest.mark.parametrize(\"style\", [\"AUTO\", \"LOOP\"])\n@pytest.mark.parametrize((\"lfsr_width\", \"lfsr_poly\", \"lfsr_init\", \"lfsr_config\", \"reverse\", \"data_width\"), [\n            (58,  \"58'h8000000001\", \"58'h3ffffffffffffff\", \"FIBONACCI\", 1, 8),\n            (58,  \"58'h8000000001\", \"58'h3ffffffffffffff\", \"FIBONACCI\", 1, 64),\n        ])\ndef test_lfsr_scramble(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, data_width, style):\n    dut = \"lfsr_scramble\"\n    module = os.path.splitext(os.path.basename(__file__))[0]\n    toplevel = dut\n\n    verilog_sources = [\n        os.path.join(rtl_dir, f\"{dut}.v\"),\n        os.path.join(rtl_dir, \"lfsr.v\"),\n    ]\n\n    parameters = {}\n\n    parameters['LFSR_WIDTH'] = lfsr_width\n    parameters['LFSR_POLY'] = lfsr_poly\n    parameters['LFSR_INIT'] = lfsr_init\n    parameters['LFSR_CONFIG'] = f'\"{lfsr_config}\"'\n    parameters['REVERSE'] = reverse\n    parameters['DATA_WIDTH'] = data_width\n    parameters['STYLE'] = f'\"{style}\"'\n\n    extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}\n\n    sim_build = os.path.join(tests_dir, \"sim_build\",\n        request.node.name.replace('[', '-').replace(']', ''))\n\n    cocotb_test.simulator.run(\n        python_search=[tests_dir],\n        verilog_sources=verilog_sources,\n        toplevel=toplevel,\n        module=module,\n        parameters=parameters,\n        sim_build=sim_build,\n        extra_env=extra_env,\n    )\n"
  },
  {
    "path": "tb/test_lfsr_crc32.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\nimport zlib\n\nmodule = 'lfsr'\ntestbench = 'test_%s_crc32' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 32\n    LFSR_POLY = 0x4c11db7\n    LFSR_CONFIG = \"GALOIS\"\n    LFSR_FEED_FORWARD = 0\n    REVERSE = 1\n    DATA_WIDTH = 8\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    data_in = Signal(intbv(0)[DATA_WIDTH:])\n    state_in = Signal(intbv(0)[LFSR_WIDTH:])\n\n    # Outputs\n    data_out = Signal(intbv(0)[DATA_WIDTH:])\n    state_out = Signal(intbv(0)[LFSR_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n\n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        data_in=data_in,\n        state_in=state_in,\n        data_out=data_out,\n        state_out=state_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: single word\")\n        current_test.next = 1\n\n        state_in.next = 0xffffffff\n        data_in.next = 0x12\n        yield clk.posedge\n\n        print(hex(~state_out.val))\n        print(hex(zlib.crc32(b'\\x12') & 0xffffffff))\n\n        assert ~state_out.val == zlib.crc32(b'\\x12') & 0xffffffff\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: block\")\n        current_test.next = 2\n\n        block = b'\\x11\\x22\\x33\\x44'\n\n        state_in.next = 0xffffffff\n        for b in block:\n            data_in.next = b\n            yield clk.posedge\n            state_in.next = state_out.val\n\n        print(hex(~state_out.val))\n        print(hex(zlib.crc32(block) & 0xffffffff))\n\n        assert ~state_out.val == zlib.crc32(block) & 0xffffffff\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_crc32.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr_crc32\n */\nmodule test_lfsr_crc32;\n\n// Parameters\nparameter LFSR_WIDTH = 32;\nparameter LFSR_POLY = 32'h4c11db7;\nparameter LFSR_CONFIG = \"GALOIS\";\nparameter LFSR_FEED_FORWARD = 0;\nparameter REVERSE = 1;\nparameter DATA_WIDTH = 8;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [DATA_WIDTH-1:0] data_in = 0;\nreg [LFSR_WIDTH-1:0] state_in = 0;\n\n// Outputs\nwire [DATA_WIDTH-1:0] data_out = 0;\nwire [LFSR_WIDTH-1:0] state_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        data_in,\n        state_in\n    );\n    $to_myhdl(\n        data_out,\n        state_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_crc32.lxt\");\n    $dumpvars(0, test_lfsr_crc32);\nend\n\nlfsr #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .LFSR_FEED_FORWARD(LFSR_FEED_FORWARD),\n    .REVERSE(REVERSE),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .data_in(data_in),\n    .state_in(state_in),\n    .data_out(data_out),\n    .state_out(state_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_crc_crc32.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\nimport zlib\n\nmodule = 'lfsr_crc'\ntestbench = 'test_%s_crc32' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"../rtl/lfsr.v\")\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 32\n    LFSR_POLY = 0x04c11db7\n    LFSR_INIT = 0xffffffff\n    LFSR_CONFIG = \"GALOIS\"\n    REVERSE = 1\n    INVERT = 1\n    DATA_WIDTH = 8\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    data_in = Signal(intbv(0)[DATA_WIDTH:])\n    data_in_valid = Signal(bool(0))\n\n    # Outputs\n    crc_out = Signal(intbv(0)[LFSR_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n\n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        data_in=data_in,\n        data_in_valid=data_in_valid,\n        crc_out=crc_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        print(\"mark\")\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: single word\")\n        current_test.next = 1\n\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        data_in.next = 0x12\n        data_in_valid.next = 1\n        yield clk.posedge\n        data_in_valid.next = 0\n        yield clk.posedge\n\n        print(hex(crc_out.val))\n        print(hex(zlib.crc32(b'\\x12') & 0xffffffff))\n\n        assert crc_out.val == zlib.crc32(b'\\x12') & 0xffffffff\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: block\")\n        current_test.next = 2\n\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        block = b'\\x11\\x22\\x33\\x44'\n\n        for b in block:\n            data_in.next = b\n            data_in_valid.next = 1\n            yield clk.posedge\n        data_in_valid.next = 0\n        yield clk.posedge\n\n        print(hex(crc_out.val))\n        print(hex(zlib.crc32(block) & 0xffffffff))\n\n        assert crc_out.val == zlib.crc32(block) & 0xffffffff\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_crc_crc32.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr_crc\n */\nmodule test_lfsr_crc_crc32;\n\n// Parameters\nparameter LFSR_WIDTH = 32;\nparameter LFSR_POLY = 32'h04c11db7;\nparameter LFSR_INIT = {LFSR_WIDTH{1'b1}};\nparameter LFSR_CONFIG = \"GALOIS\";\nparameter REVERSE = 1;\nparameter INVERT = 1;\nparameter DATA_WIDTH = 8;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [DATA_WIDTH-1:0] data_in = 0;\nreg data_in_valid = 0;\n\n// Outputs\nwire [LFSR_WIDTH-1:0] crc_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        data_in,\n        data_in_valid\n    );\n    $to_myhdl(\n        crc_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_crc_crc32.lxt\");\n    $dumpvars(0, test_lfsr_crc_crc32);\nend\n\nlfsr_crc #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_INIT(LFSR_INIT),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .REVERSE(REVERSE),\n    .INVERT(INVERT),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .data_in(data_in),\n    .data_in_valid(data_in_valid),\n    .crc_out(crc_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_crc_crc32_64.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\nimport zlib\nimport struct\n\nmodule = 'lfsr_crc'\ntestbench = 'test_%s_crc32_64' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"../rtl/lfsr.v\")\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef chunks(l, n):\n    \"\"\"Yield successive n-sized chunks from l.\"\"\"\n    for i in range(0, len(l), n):\n        yield l[i:i+n]\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 32\n    LFSR_POLY = 0x04c11db7\n    LFSR_INIT = 0xffffffff\n    LFSR_CONFIG = \"GALOIS\"\n    REVERSE = 1\n    INVERT = 1\n    DATA_WIDTH = 64\n    OUTPUT_WIDTH = LFSR_WIDTH\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    data_in = Signal(intbv(0)[DATA_WIDTH:])\n    data_in_valid = Signal(bool(0))\n\n    # Outputs\n    crc_out = Signal(intbv(0)[OUTPUT_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n\n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        data_in=data_in,\n        data_in_valid=data_in_valid,\n        crc_out=crc_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: single word\")\n        current_test.next = 1\n\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        block = bytes(range(8))\n\n        data_in.next = struct.unpack('<Q', block)[0]\n        data_in_valid.next = 1\n        yield clk.posedge\n        data_in_valid.next = 0\n        yield clk.posedge\n\n        print(hex(crc_out.val))\n        print(hex(zlib.crc32(block) & 0xffffffff))\n\n        assert crc_out.val == zlib.crc32(block) & 0xffffffff\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: block\")\n        current_test.next = 2\n\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        block = bytes(range(64))\n\n        for b in chunks(block, 8):\n            data_in.next = struct.unpack('<Q', b)[0]\n            data_in_valid.next = 1\n            yield clk.posedge\n        data_in_valid.next = 0\n        yield clk.posedge\n\n        print(hex(crc_out.val))\n        print(hex(zlib.crc32(block) & 0xffffffff))\n\n        assert crc_out.val == zlib.crc32(block) & 0xffffffff\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_crc_crc32_64.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr_crc\n */\nmodule test_lfsr_crc_crc32_64;\n\n// Parameters\nparameter LFSR_WIDTH = 32;\nparameter LFSR_POLY = 32'h04c11db7;\nparameter LFSR_INIT = {LFSR_WIDTH{1'b1}};\nparameter LFSR_CONFIG = \"GALOIS\";\nparameter REVERSE = 1;\nparameter INVERT = 1;\nparameter DATA_WIDTH = 64;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [DATA_WIDTH-1:0] data_in = 0;\nreg data_in_valid = 0;\n\n// Outputs\nwire [LFSR_WIDTH-1:0] crc_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        data_in,\n        data_in_valid\n    );\n    $to_myhdl(\n        crc_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_crc_crc32_64.lxt\");\n    $dumpvars(0, test_lfsr_crc_crc32_64);\nend\n\nlfsr_crc #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_INIT(LFSR_INIT),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .REVERSE(REVERSE),\n    .INVERT(INVERT),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .data_in(data_in),\n    .data_in_valid(data_in_valid),\n    .crc_out(crc_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_descramble.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\nimport struct\n\nmodule = 'lfsr_descramble'\ntestbench = 'test_%s' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"../rtl/lfsr.v\")\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef scramble_64b66b(data, state=0x3ffffffffffffff):\n    data_out = bytearray()\n    for d in data:\n        b = 0\n        for i in range(8):\n            if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):\n                state = ((state & 0x1ffffffffffffff) << 1) | 1\n                b = b | (1 << i)\n            else:\n                state = (state & 0x1ffffffffffffff) << 1\n        data_out += bytearray([b])\n    return data_out\n\ndef descramble_64b66b(data, state=0x3ffffffffffffff):\n    data_out = bytearray()\n    for d in data:\n        b = 0\n        for i in range(8):\n            if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):\n                b = b | (1 << i)\n            state = (state & 0x1ffffffffffffff) << 1 | bool(d & (1 << i))\n        data_out += bytearray([b])\n    return data_out\n\ndef chunks(l, n):\n    \"\"\"Yield successive n-sized chunks from l.\"\"\"\n    for i in range(0, len(l), n):\n        yield l[i:i+n]\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 58\n    LFSR_POLY = 0x8000000001\n    LFSR_INIT = 0x3ffffffffffffff\n    LFSR_CONFIG = \"FIBONACCI\"\n    REVERSE = 1\n    DATA_WIDTH = 8\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    data_in = Signal(intbv(0)[DATA_WIDTH:])\n    data_in_valid = Signal(bool(0))\n\n    # Outputs\n    data_out = Signal(intbv(0)[DATA_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    \n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        data_in=data_in,\n        data_in_valid=data_in_valid,\n        data_out=data_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: block\")\n        current_test.next = 1\n\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        block = bytes(range(256))\n\n        scr = scramble_64b66b(block)\n\n        dscr = descramble_64b66b(scr)\n\n        for i in range(len(scr)):\n            data_in.next = scr[i]\n            data_in_valid.next = 1\n            yield clk.posedge\n            if i > 0:\n                ref = block[i-1]\n                print(hex(data_out))\n                print(hex(ref))\n                assert data_out == ref\n            i += 1\n        data_in_valid.next = 0\n        yield clk.posedge\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_descramble.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr_descramble\n */\nmodule test_lfsr_descramble;\n\n// Parameters\nparameter LFSR_WIDTH = 58;\nparameter LFSR_POLY = 58'h8000000001;\nparameter LFSR_INIT = {LFSR_WIDTH{1'b1}};\nparameter LFSR_CONFIG = \"FIBONACCI\";\nparameter REVERSE = 1;\nparameter DATA_WIDTH = 8;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [DATA_WIDTH-1:0] data_in = 0;\nreg data_in_valid = 0;\n\n// Outputs\nwire [DATA_WIDTH-1:0] data_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        data_in,\n        data_in_valid\n    );\n    $to_myhdl(\n        data_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_descramble.lxt\");\n    $dumpvars(0, test_lfsr_descramble);\nend\n\nlfsr_descramble #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_INIT(LFSR_INIT),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .REVERSE(REVERSE),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .data_in(data_in),\n    .data_in_valid(data_in_valid),\n    .data_out(data_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_descramble_64.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\nimport struct\n\nmodule = 'lfsr_descramble'\ntestbench = 'test_%s_64' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"../rtl/lfsr.v\")\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef scramble_64b66b(data, state=0x3ffffffffffffff):\n    data_out = bytearray()\n    for d in data:\n        b = 0\n        for i in range(8):\n            if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):\n                state = ((state & 0x1ffffffffffffff) << 1) | 1\n                b = b | (1 << i)\n            else:\n                state = (state & 0x1ffffffffffffff) << 1\n        data_out += bytearray([b])\n    return data_out\n\ndef descramble_64b66b(data, state=0x3ffffffffffffff):\n    data_out = bytearray()\n    for d in data:\n        b = 0\n        for i in range(8):\n            if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):\n                b = b | (1 << i)\n            state = (state & 0x1ffffffffffffff) << 1 | bool(d & (1 << i))\n        data_out += bytearray([b])\n        print(hex(d)+\"    \"+hex(b))\n        print(hex(state))\n    return data_out\n\ndef chunks(l, n):\n    \"\"\"Yield successive n-sized chunks from l.\"\"\"\n    for i in range(0, len(l), n):\n        yield l[i:i+n]\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 58\n    LFSR_POLY = 0x8000000001\n    LFSR_INIT = 0x3ffffffffffffff\n    LFSR_CONFIG = \"FIBONACCI\"\n    REVERSE = 1\n    DATA_WIDTH = 64\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    data_in = Signal(intbv(0)[DATA_WIDTH:])\n    data_in_valid = Signal(bool(0))\n\n    # Outputs\n    data_out = Signal(intbv(0)[DATA_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    \n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        data_in=data_in,\n        data_in_valid=data_in_valid,\n        data_out=data_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: block\")\n        current_test.next = 1\n\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        block = bytes(range(256))\n\n        scr = scramble_64b66b(block)\n\n        dscr = descramble_64b66b(scr)\n\n        for i in range(0, len(scr), 8):\n            data_in.next = struct.unpack('<Q', scr[i:i+8])[0]\n            data_in_valid.next = 1\n            yield clk.posedge\n            if i > 0:\n                ref = struct.unpack('<Q', block[i-8:i])[0]\n                print(hex(data_out))\n                print(hex(ref))\n                assert data_out == ref\n            i += 8\n        data_in_valid.next = 0\n        yield clk.posedge\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_descramble_64.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr_descramble\n */\nmodule test_lfsr_descramble_64;\n\n// Parameters\nparameter LFSR_WIDTH = 58;\nparameter LFSR_POLY = 58'h8000000001;\nparameter LFSR_INIT = {LFSR_WIDTH{1'b1}};\nparameter LFSR_CONFIG = \"FIBONACCI\";\nparameter REVERSE = 1;\nparameter DATA_WIDTH = 64;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [DATA_WIDTH-1:0] data_in = 0;\nreg data_in_valid = 0;\n\n// Outputs\nwire [DATA_WIDTH-1:0] data_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        data_in,\n        data_in_valid\n    );\n    $to_myhdl(\n        data_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_descramble_64.lxt\");\n    $dumpvars(0, test_lfsr_descramble_64);\nend\n\nlfsr_descramble #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_INIT(LFSR_INIT),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .REVERSE(REVERSE),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .data_in(data_in),\n    .data_in_valid(data_in_valid),\n    .data_out(data_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_prbs31.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\nmodule = 'lfsr'\ntestbench = 'test_%s_prbs31' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef prbs31(state = 0x7fffffff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x08000000) ^ bool(state & 0x40000000):\n                state = ((state & 0x3fffffff) << 1) | 1\n            else:\n                state = (state & 0x3fffffff) << 1\n        yield state & 0xff\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 31\n    LFSR_POLY = 0x10000001\n    LFSR_CONFIG = \"FIBONACCI\"\n    LFSR_FEED_FORWARD = 0\n    REVERSE = 0\n    DATA_WIDTH = 8\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    data_in = Signal(intbv(0)[DATA_WIDTH:])\n    state_in = Signal(intbv(0)[LFSR_WIDTH:])\n\n    # Outputs\n    data_out = Signal(intbv(0)[DATA_WIDTH:])\n    state_out = Signal(intbv(0)[LFSR_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n\n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        data_in=data_in,\n        state_in=state_in,\n        data_out=data_out,\n        state_out=state_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test PRBS31\")\n        current_test.next = 1\n\n        state_in.next = 0x7fffffff\n        data_in.next = 0\n        gen = prbs31()\n\n        for i in range(512):\n\n            yield clk.posedge\n\n            ref = next(gen)\n            val = data_out.val\n\n            print((ref, val))\n\n            assert ref == val\n\n            state_in.next = state_out.val\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_prbs31.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr\n */\nmodule test_lfsr_prbs31;\n\n// Parameters\nparameter LFSR_WIDTH = 31;\nparameter LFSR_POLY = 31'h10000001;\nparameter LFSR_CONFIG = \"FIBONACCI\";\nparameter LFSR_FEED_FORWARD = 0;\nparameter REVERSE = 0;\nparameter DATA_WIDTH = 8;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [DATA_WIDTH-1:0] data_in = 0;\nreg [LFSR_WIDTH-1:0] state_in = 0;\n\n// Outputs\nwire [DATA_WIDTH-1:0] data_out;\nwire [LFSR_WIDTH-1:0] state_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        data_in,\n        state_in\n    );\n    $to_myhdl(\n        data_out,\n        state_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_prbs31.lxt\");\n    $dumpvars(0, test_lfsr_prbs31);\nend\n\nlfsr #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .LFSR_FEED_FORWARD(LFSR_FEED_FORWARD),\n    .REVERSE(REVERSE),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .data_in(data_in),\n    .state_in(state_in),\n    .data_out(data_out),\n    .state_out(state_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_prbs9.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\nmodule = 'lfsr'\ntestbench = 'test_%s_prbs9' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef prbs9(state = 0x1ff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x10) ^ bool(state & 0x100):\n                state = ((state & 0xff) << 1) | 1\n            else:\n                state = (state & 0xff) << 1\n        yield state & 0xff\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 9\n    LFSR_POLY = 0x021\n    LFSR_CONFIG = \"FIBONACCI\"\n    LFSR_FEED_FORWARD = 0\n    REVERSE = 0\n    DATA_WIDTH = 8\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    data_in = Signal(intbv(0)[DATA_WIDTH:])\n    state_in = Signal(intbv(0)[LFSR_WIDTH:])\n\n    # Outputs\n    data_out = Signal(intbv(0)[DATA_WIDTH:])\n    state_out = Signal(intbv(0)[LFSR_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n\n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        data_in=data_in,\n        state_in=state_in,\n        data_out=data_out,\n        state_out=state_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test PRBS9\")\n        current_test.next = 1\n\n        state_in.next = 0x1ff\n        data_in.next = 0\n        gen = prbs9()\n\n        for i in range(512):\n\n            yield clk.posedge\n\n            ref = next(gen)\n            val = data_out.val\n\n            print((ref, val))\n\n            assert ref == val\n\n            state_in.next = state_out.val\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_prbs9.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr\n */\nmodule test_lfsr_prbs9;\n\n// Parameters\nparameter LFSR_WIDTH = 9;\nparameter LFSR_POLY = 9'h021;\nparameter LFSR_CONFIG = \"FIBONACCI\";\nparameter LFSR_FEED_FORWARD = 0;\nparameter REVERSE = 0;\nparameter DATA_WIDTH = 8;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [DATA_WIDTH-1:0] data_in = 0;\nreg [LFSR_WIDTH-1:0] state_in = 0;\n\n// Outputs\nwire [DATA_WIDTH-1:0] data_out;\nwire [LFSR_WIDTH-1:0] state_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        data_in,\n        state_in\n    );\n    $to_myhdl(\n        data_out,\n        state_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_prbs9.lxt\");\n    $dumpvars(0, test_lfsr_prbs9);\nend\n\nlfsr #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .LFSR_FEED_FORWARD(LFSR_FEED_FORWARD),\n    .REVERSE(REVERSE),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .data_in(data_in),\n    .state_in(state_in),\n    .data_out(data_out),\n    .state_out(state_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_prbs_check_prbs31.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\nmodule = 'lfsr_prbs_check'\ntestbench = 'test_%s_prbs31' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"../rtl/lfsr.v\")\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef prbs31(state = 0x7fffffff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x08000000) ^ bool(state & 0x40000000):\n                state = ((state & 0x3fffffff) << 1) | 1\n            else:\n                state = (state & 0x3fffffff) << 1\n        yield ~state & 0xff\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 9\n    LFSR_POLY = 0x021\n    LFSR_INIT = 0x1ff\n    LFSR_CONFIG = \"FIBONACCI\"\n    REVERSE = 0\n    INVERT = 1\n    DATA_WIDTH = 8\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    data_in = Signal(intbv(0)[DATA_WIDTH:])\n    data_in_valid = Signal(bool(0))\n\n    # Outputs\n    data_out = Signal(intbv(0)[DATA_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n    \n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        data_in=data_in,\n        data_in_valid=data_in_valid,\n        data_out=data_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test PRBS31\")\n        current_test.next = 1\n\n        gen = prbs31()\n\n        data_in.next = next(gen)\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        for i in range(512):\n\n            data_in.next = next(gen)\n            data_in_valid.next = 1\n\n            val = data_out.val\n\n            print(val)\n\n            assert val == 0\n\n            yield clk.posedge\n\n        data_in_valid.next = 0\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: single error\")\n        current_test.next = 2\n\n        gen = prbs31()\n\n        for i in range(16):\n            data_in.next = next(gen)\n            data_in_valid.next = 1\n            yield clk.posedge\n\n        data_in.next = next(gen) ^ 0x08\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x00\n\n        data_in.next = next(gen)\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x08\n\n        data_in.next = next(gen)\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x00\n\n        data_in.next = next(gen)\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x00\n\n        data_in.next = next(gen)\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x00\n\n        data_in.next = next(gen)\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x90\n\n        data_in.next = next(gen)\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x00\n\n        yield clk.posedge\n\n        data_in_valid.next = 0\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_prbs_check_prbs31.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr_prbs_check\n */\nmodule test_lfsr_prbs_check_prbs31;\n\n// Parameters\nparameter LFSR_WIDTH = 31;\nparameter LFSR_POLY = 31'h10000001;\nparameter LFSR_INIT = {LFSR_WIDTH{1'b1}};\nparameter LFSR_CONFIG = \"FIBONACCI\";\nparameter REVERSE = 0;\nparameter INVERT = 1;\nparameter DATA_WIDTH = 8;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [DATA_WIDTH-1:0] data_in = 0;\nreg data_in_valid = 0;\n\n// Outputs\nwire [DATA_WIDTH-1:0] data_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        data_in,\n        data_in_valid\n    );\n    $to_myhdl(\n        data_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_prbs_check_prbs31.lxt\");\n    $dumpvars(0, test_lfsr_prbs_check_prbs31);\nend\n\nlfsr_prbs_check #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_INIT(LFSR_INIT),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .REVERSE(REVERSE),\n    .INVERT(INVERT),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .data_in(data_in),\n    .data_in_valid(data_in_valid),\n    .data_out(data_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_prbs_check_prbs31_64.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\nimport struct\n\nmodule = 'lfsr_prbs_check'\ntestbench = 'test_%s_prbs31_64' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"../rtl/lfsr.v\")\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef prbs31(state = 0x7fffffff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x08000000) ^ bool(state & 0x40000000):\n                state = ((state & 0x3fffffff) << 1) | 1\n            else:\n                state = (state & 0x3fffffff) << 1\n        yield ~state & 0xff\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 9\n    LFSR_POLY = 0x021\n    LFSR_INIT = 0x1ff\n    LFSR_CONFIG = \"FIBONACCI\"\n    REVERSE = 0\n    INVERT = 1\n    DATA_WIDTH = 64\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    data_in = Signal(intbv(0)[DATA_WIDTH:])\n    data_in_valid = Signal(bool(0))\n\n    # Outputs\n    data_out = Signal(intbv(0)[DATA_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n\n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        data_in=data_in,\n        data_in_valid=data_in_valid,\n        data_out=data_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test PRBS31\")\n        current_test.next = 1\n\n        gen = prbs31()\n\n        data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        for i in range(512):\n\n            data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]\n            data_in_valid.next = 1\n\n            val = data_out.val\n\n            print(val)\n\n            assert val == 0\n\n            yield clk.posedge\n\n        data_in_valid.next = 0\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: single error\")\n        current_test.next = 2\n\n        gen = prbs31()\n\n        for i in range(16):\n            data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]\n            data_in_valid.next = 1\n            yield clk.posedge\n\n        data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0] ^ 0x0001000000000000\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x0000000000000000\n\n        data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x0001000000120000\n\n        data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x0000000000000000\n\n        data_in_valid.next = 0\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_prbs_check_prbs31_64.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr_prbs_check\n */\nmodule test_lfsr_prbs_check_prbs31_64;\n\n// Parameters\nparameter LFSR_WIDTH = 31;\nparameter LFSR_POLY = 31'h10000001;\nparameter LFSR_INIT = {LFSR_WIDTH{1'b1}};\nparameter LFSR_CONFIG = \"FIBONACCI\";\nparameter REVERSE = 0;\nparameter INVERT = 1;\nparameter DATA_WIDTH = 64;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [DATA_WIDTH-1:0] data_in = 0;\nreg data_in_valid = 0;\n\n// Outputs\nwire [DATA_WIDTH-1:0] data_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        data_in,\n        data_in_valid\n    );\n    $to_myhdl(\n        data_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_prbs_check_prbs31_64.lxt\");\n    $dumpvars(0, test_lfsr_prbs_check_prbs31_64);\nend\n\nlfsr_prbs_check #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_INIT(LFSR_INIT),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .REVERSE(REVERSE),\n    .INVERT(INVERT),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .data_in(data_in),\n    .data_in_valid(data_in_valid),\n    .data_out(data_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_prbs_check_prbs9.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\nmodule = 'lfsr_prbs_check'\ntestbench = 'test_%s_prbs9' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"../rtl/lfsr.v\")\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef prbs9(state = 0x1ff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x10) ^ bool(state & 0x100):\n                state = ((state & 0xff) << 1) | 1\n            else:\n                state = (state & 0xff) << 1\n        yield state & 0xff\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 9\n    LFSR_POLY = 0x021\n    LFSR_INIT = 0x1ff\n    LFSR_CONFIG = \"FIBONACCI\"\n    REVERSE = 0\n    INVERT = 0\n    DATA_WIDTH = 8\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    data_in = Signal(intbv(0)[DATA_WIDTH:])\n    data_in_valid = Signal(bool(0))\n\n    # Outputs\n    data_out = Signal(intbv(0)[DATA_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n\n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        data_in=data_in,\n        data_in_valid=data_in_valid,\n        data_out=data_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test PRBS9\")\n        current_test.next = 1\n\n        gen = prbs9()\n\n        data_in.next = next(gen)\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        for i in range(512):\n\n            data_in.next = next(gen)\n            data_in_valid.next = 1\n\n            val = data_out.val\n\n            print(val)\n\n            assert val == 0\n\n            yield clk.posedge\n\n        data_in_valid.next = 0\n\n        yield delay(100)\n\n        yield clk.posedge\n        print(\"test 2: single error\")\n        current_test.next = 2\n\n        gen = prbs9()\n\n        for i in range(16):\n            data_in.next = next(gen)\n            data_in_valid.next = 1\n            yield clk.posedge\n\n        data_in.next = next(gen) ^ 0x08\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x00\n\n        data_in.next = next(gen)\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x08\n\n        data_in.next = next(gen)\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x44\n\n        data_in.next = next(gen)\n        data_in_valid.next = 1\n        yield clk.posedge\n\n        val = data_out.val\n\n        print(val)\n\n        assert val == 0x00\n\n        yield clk.posedge\n\n        data_in_valid.next = 0\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_prbs_check_prbs9.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr_prbs_check\n */\nmodule test_lfsr_prbs_check_prbs9;\n\n// Parameters\nparameter LFSR_WIDTH = 9;\nparameter LFSR_POLY = 9'h021;\nparameter LFSR_INIT = {LFSR_WIDTH{1'b1}};\nparameter LFSR_CONFIG = \"FIBONACCI\";\nparameter REVERSE = 0;\nparameter INVERT = 0;\nparameter DATA_WIDTH = 8;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [DATA_WIDTH-1:0] data_in = 0;\nreg data_in_valid = 0;\n\n// Outputs\nwire [DATA_WIDTH-1:0] data_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        data_in,\n        data_in_valid\n    );\n    $to_myhdl(\n        data_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_prbs_check_prbs9.lxt\");\n    $dumpvars(0, test_lfsr_prbs_check_prbs9);\nend\n\nlfsr_prbs_check #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_INIT(LFSR_INIT),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .REVERSE(REVERSE),\n    .INVERT(INVERT),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .data_in(data_in),\n    .data_in_valid(data_in_valid),\n    .data_out(data_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_prbs_gen_prbs31.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\nmodule = 'lfsr_prbs_gen'\ntestbench = 'test_%s_prbs31' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"../rtl/lfsr.v\")\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef prbs31(state = 0x7fffffff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x08000000) ^ bool(state & 0x40000000):\n                state = ((state & 0x3fffffff) << 1) | 1\n            else:\n                state = (state & 0x3fffffff) << 1\n        yield ~state & 0xff\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 31\n    LFSR_POLY = 0x10000001\n    LFSR_INIT = 0x7fffffff\n    LFSR_CONFIG = \"FIBONACCI\"\n    REVERSE = 0\n    INVERT = 1\n    DATA_WIDTH = 8\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    enable = Signal(bool(0))\n\n    # Outputs\n    data_out = Signal(intbv(0)[DATA_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n\n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        enable=enable,\n        data_out=data_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test PRBS31\")\n        current_test.next = 1\n\n        gen = prbs31()\n\n        enable.next = 1\n        yield clk.posedge\n        yield clk.posedge\n        enable.next = 0\n\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        enable.next = 1\n        yield clk.posedge\n\n        for i in range(512):\n\n            ref = next(gen)\n            val = data_out.val\n\n            print((ref, val))\n\n            assert ref == val\n\n            yield clk.posedge\n\n        enable.next = 0\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_prbs_gen_prbs31.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr_prbs_gen\n */\nmodule test_lfsr_prbs_gen_prbs31;\n\n// Parameters\nparameter LFSR_WIDTH = 31;\nparameter LFSR_POLY = 31'h10000001;\nparameter LFSR_INIT = {LFSR_WIDTH{1'b1}};\nparameter LFSR_CONFIG = \"FIBONACCI\";\nparameter REVERSE = 0;\nparameter INVERT = 1;\nparameter DATA_WIDTH = 8;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg enable = 0;\n\n// Outputs\nwire [DATA_WIDTH-1:0] data_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        enable\n    );\n    $to_myhdl(\n        data_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_prbs_gen_prbs31.lxt\");\n    $dumpvars(0, test_lfsr_prbs_gen_prbs31);\nend\n\nlfsr_prbs_gen #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_INIT(LFSR_INIT),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .REVERSE(REVERSE),\n    .INVERT(INVERT),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .enable(enable),\n    .data_out(data_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_prbs_gen_prbs31_64.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\nimport struct\n\nmodule = 'lfsr_prbs_gen'\ntestbench = 'test_%s_prbs31_64' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"../rtl/lfsr.v\")\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef prbs31(state = 0x7fffffff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x08000000) ^ bool(state & 0x40000000):\n                state = ((state & 0x3fffffff) << 1) | 1\n            else:\n                state = (state & 0x3fffffff) << 1\n        yield ~state & 0xff\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 31\n    LFSR_POLY = 0x10000001\n    LFSR_INIT = 0x7fffffff\n    LFSR_CONFIG = \"FIBONACCI\"\n    REVERSE = 0\n    INVERT = 1\n    DATA_WIDTH = 64\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    enable = Signal(bool(0))\n\n    # Outputs\n    data_out = Signal(intbv(0)[DATA_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n\n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        enable=enable,\n        data_out=data_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test PRBS31\")\n        current_test.next = 1\n\n        gen = prbs31()\n\n        enable.next = 1\n        yield clk.posedge\n        yield clk.posedge\n        enable.next = 0\n\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        enable.next = 1\n        yield clk.posedge\n\n        for i in range(512):\n\n            #ref = next(gen)\n            ref = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]\n            val = data_out.val\n\n            print((ref, val))\n\n            assert ref == val\n\n            yield clk.posedge\n\n        enable.next = 0\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_prbs_gen_prbs31_64.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr_prbs_gen\n */\nmodule test_lfsr_prbs_gen_prbs31_64;\n\n// Parameters\nparameter LFSR_WIDTH = 31;\nparameter LFSR_POLY = 31'h10000001;\nparameter LFSR_INIT = {LFSR_WIDTH{1'b1}};\nparameter LFSR_CONFIG = \"FIBONACCI\";\nparameter REVERSE = 0;\nparameter INVERT = 1;\nparameter DATA_WIDTH = 64;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg enable = 0;\n\n// Outputs\nwire [DATA_WIDTH-1:0] data_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        enable\n    );\n    $to_myhdl(\n        data_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_prbs_gen_prbs31_64.lxt\");\n    $dumpvars(0, test_lfsr_prbs_gen_prbs31_64);\nend\n\nlfsr_prbs_gen #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_INIT(LFSR_INIT),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .REVERSE(REVERSE),\n    .INVERT(INVERT),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .enable(enable),\n    .data_out(data_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_prbs_gen_prbs9.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\n\nmodule = 'lfsr_prbs_gen'\ntestbench = 'test_%s_prbs9' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"../rtl/lfsr.v\")\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef prbs9(state = 0x1ff):\n    while True:\n        for i in range(8):\n            if bool(state & 0x10) ^ bool(state & 0x100):\n                state = ((state & 0xff) << 1) | 1\n            else:\n                state = (state & 0xff) << 1\n        yield state & 0xff\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 9\n    LFSR_POLY = 0x021\n    LFSR_INIT = 0x1ff\n    LFSR_CONFIG = \"FIBONACCI\"\n    REVERSE = 0\n    INVERT = 0\n    DATA_WIDTH = 8\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    enable = Signal(bool(0))\n\n    # Outputs\n    data_out = Signal(intbv(0)[DATA_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n\n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        enable=enable,\n        data_out=data_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: test PRBS9\")\n        current_test.next = 1\n\n        gen = prbs9()\n\n        enable.next = 1\n        yield clk.posedge\n        yield clk.posedge\n        enable.next = 0\n\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        enable.next = 1\n        yield clk.posedge\n\n        for i in range(512):\n\n            ref = next(gen)\n            val = data_out.val\n\n            print((ref, val))\n\n            assert ref == val\n\n            yield clk.posedge\n\n        enable.next = 0\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_prbs_gen_prbs9.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr_prbs_gen\n */\nmodule test_lfsr_prbs_gen_prbs9;\n\n// Parameters\nparameter LFSR_WIDTH = 9;\nparameter LFSR_POLY = 9'h021;\nparameter LFSR_INIT = {LFSR_WIDTH{1'b1}};\nparameter LFSR_CONFIG = \"FIBONACCI\";\nparameter REVERSE = 0;\nparameter INVERT = 0;\nparameter DATA_WIDTH = 8;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg enable = 0;\n\n// Outputs\nwire [DATA_WIDTH-1:0] data_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        enable\n    );\n    $to_myhdl(\n        data_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_prbs_gen_prbs9.lxt\");\n    $dumpvars(0, test_lfsr_prbs_gen_prbs9);\nend\n\nlfsr_prbs_gen #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_INIT(LFSR_INIT),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .REVERSE(REVERSE),\n    .INVERT(INVERT),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .enable(enable),\n    .data_out(data_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_scramble.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\nimport struct\n\nmodule = 'lfsr_scramble'\ntestbench = 'test_%s' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"../rtl/lfsr.v\")\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef scramble_64b66b(data, state=0x3ffffffffffffff):\n    data_out = bytearray()\n    for d in data:\n        b = 0\n        for i in range(8):\n            if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):\n                state = ((state & 0x1ffffffffffffff) << 1) | 1\n                b = b | (1 << i)\n            else:\n                state = (state & 0x1ffffffffffffff) << 1\n        data_out += bytearray([b])\n    return data_out\n\ndef chunks(l, n):\n    \"\"\"Yield successive n-sized chunks from l.\"\"\"\n    for i in range(0, len(l), n):\n        yield l[i:i+n]\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 58\n    LFSR_POLY = 0x8000000001\n    LFSR_INIT = 0x3ffffffffffffff\n    LFSR_CONFIG = \"FIBONACCI\"\n    REVERSE = 1\n    DATA_WIDTH = 8\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    data_in = Signal(intbv(0)[DATA_WIDTH:])\n    data_in_valid = Signal(bool(0))\n\n    # Outputs\n    data_out = Signal(intbv(0)[DATA_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n\n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        data_in=data_in,\n        data_in_valid=data_in_valid,\n        data_out=data_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: block\")\n        current_test.next = 1\n\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        block = bytes(range(256))\n\n        scr = scramble_64b66b(block)\n\n        for i in range(len(block)):\n            data_in.next = block[i]\n            data_in_valid.next = 1\n            yield clk.posedge\n            if i > 0:\n                ref = scr[i-1]\n                print(hex(data_out))\n                print(hex(ref))\n                assert data_out == ref\n            i += 1\n        data_in_valid.next = 0\n        yield clk.posedge\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_scramble.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr_scramble\n */\nmodule test_lfsr_scramble;\n\n// Parameters\nparameter LFSR_WIDTH = 58;\nparameter LFSR_POLY = 58'h8000000001;\nparameter LFSR_INIT = {LFSR_WIDTH{1'b1}};\nparameter LFSR_CONFIG = \"FIBONACCI\";\nparameter REVERSE = 1;\nparameter DATA_WIDTH = 8;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [DATA_WIDTH-1:0] data_in = 0;\nreg data_in_valid = 0;\n\n// Outputs\nwire [DATA_WIDTH-1:0] data_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        data_in,\n        data_in_valid\n    );\n    $to_myhdl(\n        data_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_scramble.lxt\");\n    $dumpvars(0, test_lfsr_scramble);\nend\n\nlfsr_scramble #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_INIT(LFSR_INIT),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .REVERSE(REVERSE),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .data_in(data_in),\n    .data_in_valid(data_in_valid),\n    .data_out(data_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tb/test_lfsr_scramble_64.py",
    "content": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n\"\"\"\n\nfrom myhdl import *\nimport os\nimport struct\n\nmodule = 'lfsr_scramble'\ntestbench = 'test_%s_64' % module\n\nsrcs = []\n\nsrcs.append(\"../rtl/%s.v\" % module)\nsrcs.append(\"../rtl/lfsr.v\")\nsrcs.append(\"%s.v\" % testbench)\n\nsrc = ' '.join(srcs)\n\nbuild_cmd = \"iverilog -o %s.vvp %s\" % (testbench, src)\n\ndef scramble_64b66b(data, state=0x3ffffffffffffff):\n    data_out = bytearray()\n    for d in data:\n        b = 0\n        for i in range(8):\n            if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):\n                state = ((state & 0x1ffffffffffffff) << 1) | 1\n                b = b | (1 << i)\n            else:\n                state = (state & 0x1ffffffffffffff) << 1\n        data_out += bytearray([b])\n    return data_out\n\ndef chunks(l, n):\n    \"\"\"Yield successive n-sized chunks from l.\"\"\"\n    for i in range(0, len(l), n):\n        yield l[i:i+n]\n\ndef bench():\n\n    # Parameters\n    LFSR_WIDTH = 58\n    LFSR_POLY = 0x8000000001\n    LFSR_INIT = 0x3ffffffffffffff\n    LFSR_CONFIG = \"FIBONACCI\"\n    REVERSE = 1\n    DATA_WIDTH = 64\n    STYLE = \"AUTO\"\n\n    # Inputs\n    clk = Signal(bool(0))\n    rst = Signal(bool(0))\n    current_test = Signal(intbv(0)[8:])\n\n    data_in = Signal(intbv(0)[DATA_WIDTH:])\n    data_in_valid = Signal(bool(0))\n\n    # Outputs\n    data_out = Signal(intbv(0)[DATA_WIDTH:])\n\n    # DUT\n    if os.system(build_cmd):\n        raise Exception(\"Error running build command\")\n\n    dut = Cosimulation(\n        \"vvp -m myhdl %s.vvp -lxt2\" % testbench,\n        clk=clk,\n        rst=rst,\n        current_test=current_test,\n        data_in=data_in,\n        data_in_valid=data_in_valid,\n        data_out=data_out\n    )\n\n    @always(delay(4))\n    def clkgen():\n        clk.next = not clk\n\n    @instance\n    def check():\n        yield delay(100)\n        yield clk.posedge\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n        yield delay(100)\n        yield clk.posedge\n\n        # testbench stimulus\n\n        yield clk.posedge\n        print(\"test 1: block\")\n        current_test.next = 1\n\n        rst.next = 1\n        yield clk.posedge\n        rst.next = 0\n        yield clk.posedge\n\n        block = bytes(range(256))\n\n        scr = scramble_64b66b(block)\n\n        for i in range(0, len(block), 8):\n            data_in.next = struct.unpack('<Q', block[i:i+8])[0]\n            data_in_valid.next = 1\n            yield clk.posedge\n            if i > 0:\n                ref = struct.unpack('<Q', scr[i-8:i])[0]\n                print(hex(data_out))\n                print(hex(ref))\n                assert data_out == ref\n            i += 8\n        data_in_valid.next = 0\n        yield clk.posedge\n\n        yield delay(100)\n\n        raise StopSimulation\n\n    return instances()\n\ndef test_bench():\n    sim = Simulation(bench())\n    sim.run()\n\nif __name__ == '__main__':\n    print(\"Running test...\")\n    test_bench()\n"
  },
  {
    "path": "tb/test_lfsr_scramble_64.v",
    "content": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n*/\n\n// Language: Verilog 2001\n\n`timescale 1ns / 1ps\n\n/*\n * Testbench for lfsr_scramble\n */\nmodule test_lfsr_scramble_64;\n\n// Parameters\nparameter LFSR_WIDTH = 58;\nparameter LFSR_POLY = 58'h8000000001;\nparameter LFSR_INIT = {LFSR_WIDTH{1'b1}};\nparameter LFSR_CONFIG = \"FIBONACCI\";\nparameter REVERSE = 1;\nparameter DATA_WIDTH = 64;\nparameter STYLE = \"AUTO\";\n\n// Inputs\nreg clk = 0;\nreg rst = 0;\nreg [7:0] current_test = 0;\n\nreg [DATA_WIDTH-1:0] data_in = 0;\nreg data_in_valid = 0;\n\n// Outputs\nwire [DATA_WIDTH-1:0] data_out;\n\ninitial begin\n    // myhdl integration\n    $from_myhdl(\n        clk,\n        rst,\n        current_test,\n        data_in,\n        data_in_valid\n    );\n    $to_myhdl(\n        data_out\n    );\n\n    // dump file\n    $dumpfile(\"test_lfsr_scramble_64.lxt\");\n    $dumpvars(0, test_lfsr_scramble_64);\nend\n\nlfsr_scramble #(\n    .LFSR_WIDTH(LFSR_WIDTH),\n    .LFSR_POLY(LFSR_POLY),\n    .LFSR_INIT(LFSR_INIT),\n    .LFSR_CONFIG(LFSR_CONFIG),\n    .REVERSE(REVERSE),\n    .DATA_WIDTH(DATA_WIDTH),\n    .STYLE(STYLE)\n)\nUUT (\n    .clk(clk),\n    .rst(rst),\n    .data_in(data_in),\n    .data_in_valid(data_in_valid),\n    .data_out(data_out)\n);\n\nendmodule\n"
  },
  {
    "path": "tox.ini",
    "content": "# tox configuration\n[tox]\nenvlist = py3\nskipsdist = True\nminversion = 3.2.0\nrequires = virtualenv >= 16.1\n\n[gh-actions]\npython =\n    3.9: py3\n\n[testenv]\ndeps =\n    pytest == 7.1.3\n    pytest-xdist == 2.5.0\n    pytest-split == 0.8.0\n    cocotb == 1.7.0\n    cocotb-test == 0.2.2\n\ncommands =\n    pytest -n auto {posargs}\n\n# pytest configuration\n[pytest]\ntestpaths =\n    tb\naddopts =\n    --ignore-glob=tb/test_*.py\n    --import-mode importlib\n"
  }
]