Showing preview only (206K chars total). Download the full file or copy to clipboard to get everything.
Repository: alexforencich/verilog-lfsr
Branch: master
Commit: c1f86d036745
Files: 54
Total size: 191.6 KB
Directory structure:
gitextract_d0iwnulu/
├── .github/
│ └── workflows/
│ └── regression-tests.yml
├── .gitignore
├── AUTHORS
├── COPYING
├── README.md
├── rtl/
│ ├── lfsr.v
│ ├── lfsr_crc.v
│ ├── lfsr_descramble.v
│ ├── lfsr_prbs_check.v
│ ├── lfsr_prbs_gen.v
│ └── lfsr_scramble.v
├── tb/
│ ├── lfsr/
│ │ ├── Makefile
│ │ └── test_lfsr.py
│ ├── lfsr_crc/
│ │ ├── Makefile
│ │ └── test_lfsr_crc.py
│ ├── lfsr_descramble/
│ │ ├── Makefile
│ │ └── test_lfsr_descramble.py
│ ├── lfsr_prbs_check/
│ │ ├── Makefile
│ │ └── test_lfsr_prbs_check.py
│ ├── lfsr_prbs_gen/
│ │ ├── Makefile
│ │ └── test_lfsr_prbs_gen.py
│ ├── lfsr_scramble/
│ │ ├── Makefile
│ │ └── test_lfsr_scramble.py
│ ├── test_lfsr_crc32.py
│ ├── test_lfsr_crc32.v
│ ├── test_lfsr_crc_crc32.py
│ ├── test_lfsr_crc_crc32.v
│ ├── test_lfsr_crc_crc32_64.py
│ ├── test_lfsr_crc_crc32_64.v
│ ├── test_lfsr_descramble.py
│ ├── test_lfsr_descramble.v
│ ├── test_lfsr_descramble_64.py
│ ├── test_lfsr_descramble_64.v
│ ├── test_lfsr_prbs31.py
│ ├── test_lfsr_prbs31.v
│ ├── test_lfsr_prbs9.py
│ ├── test_lfsr_prbs9.v
│ ├── test_lfsr_prbs_check_prbs31.py
│ ├── test_lfsr_prbs_check_prbs31.v
│ ├── test_lfsr_prbs_check_prbs31_64.py
│ ├── test_lfsr_prbs_check_prbs31_64.v
│ ├── test_lfsr_prbs_check_prbs9.py
│ ├── test_lfsr_prbs_check_prbs9.v
│ ├── test_lfsr_prbs_gen_prbs31.py
│ ├── test_lfsr_prbs_gen_prbs31.v
│ ├── test_lfsr_prbs_gen_prbs31_64.py
│ ├── test_lfsr_prbs_gen_prbs31_64.v
│ ├── test_lfsr_prbs_gen_prbs9.py
│ ├── test_lfsr_prbs_gen_prbs9.v
│ ├── test_lfsr_scramble.py
│ ├── test_lfsr_scramble.v
│ ├── test_lfsr_scramble_64.py
│ └── test_lfsr_scramble_64.v
└── tox.ini
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/regression-tests.yml
================================================
name: Regression Tests
on: [push, pull_request]
jobs:
build:
name: Python ${{ matrix.python-version }} (${{ matrix.group }}/10)
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: [3.9]
group: [1, 2, 3, 4, 5]
steps:
- uses: actions/checkout@v1
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install Icarus Verilog
run: |
sudo apt install -y --no-install-recommends iverilog
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install tox tox-gh-actions
- name: Test with tox
run: tox -- --splits 5 --group ${{ matrix.group }} --splitting-algorithm least_duration
================================================
FILE: .gitignore
================================================
*~
*.lxt
*.pyc
*.vvp
*.kate-swp
================================================
FILE: AUTHORS
================================================
Alex Forencich <alex@alexforencich.com>
================================================
FILE: COPYING
================================================
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: README.md
================================================
# Verilog LFSR Readme
[](https://github.com/alexforencich/verilog-lfsr/actions/)
For more information and updates: http://alexforencich.com/wiki/en/verilog/lfsr/start
GitHub repository: https://github.com/alexforencich/verilog-lfsr
## Deprecation Notice
This repository is superseded by https://github.com/fpganinja/taxi. All new features and bug fixes will be applied there, and commercial support is also available. As a result, this repo is deprecated and will not receive any future maintenance or support.
## Introduction
Fully parametrizable combinatorial parallel LFSR/CRC module. Implements an unrolled LFSR next state computation. Includes full cocotb testbenches.
## Documentation
### lfsr module
Fully parametrizable combinatorial parallel LFSR/CRC module. Implements an unrolled LFSR next state computation.
### lfsr_crc module
Wrapper for lfsr module for standard CRC computation.
### lfsr_descramble module
Wrapper for lfsr module for self-synchronizing descrambler.
### lfsr_prbs_check module
Wrapper for lfsr module for standard PRBS check.
### lfsr_prbs_gen module
Wrapper for lfsr module for standard PRBS computation.
### lfsr_scramble module
Wrapper for lfsr module for self-synchronizing scrambler.
### Source Files
lfsr.v : Parametrizable combinatorial LFSR/CRC module
lfsr_crc.v : Parametrizable CRC computation wrapper
lfsr_descramble.v : Parametrizable LFSR self-synchronizing descrambler
lfsr_prbs_check.v : Parametrizable PRBS checker wrapper
lfsr_prbs_gen.v : Parametrizable PRBS generator wrapper
lfsr_scramble.v : Parametrizable LFSR self-synchronizing scrambler
## Testing
Running the included testbenches requires [cocotb](https://github.com/cocotb/cocotb) and [Icarus Verilog](http://iverilog.icarus.com/). The testbenches can be run with pytest directly (requires [cocotb-test](https://github.com/themperek/cocotb-test)), pytest via tox, or via cocotb makefiles.
================================================
FILE: rtl/lfsr.v
================================================
/*
Copyright (c) 2016-2023 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Parametrizable combinatorial parallel LFSR/CRC
*/
module lfsr #
(
// width of LFSR
parameter LFSR_WIDTH = 31,
// LFSR polynomial
parameter LFSR_POLY = 31'h10000001,
// LFSR configuration: "GALOIS", "FIBONACCI"
parameter LFSR_CONFIG = "FIBONACCI",
// LFSR feed forward enable
parameter LFSR_FEED_FORWARD = 0,
// bit-reverse input and output
parameter REVERSE = 0,
// width of data input
parameter DATA_WIDTH = 8,
// implementation style: "AUTO", "LOOP", "REDUCTION"
parameter STYLE = "AUTO"
)
(
input wire [DATA_WIDTH-1:0] data_in,
input wire [LFSR_WIDTH-1:0] state_in,
output wire [DATA_WIDTH-1:0] data_out,
output wire [LFSR_WIDTH-1:0] state_out
);
/*
Fully parametrizable combinatorial parallel LFSR/CRC module. Implements an unrolled LFSR
next state computation, shifting DATA_WIDTH bits per pass through the module. Input data
is XORed with LFSR feedback path, tie data_in to zero if this is not required.
Works in two parts: statically computes a set of bit masks, then uses these bit masks to
select bits for XORing to compute the next state.
Ports:
data_in
Data bits to be shifted through the LFSR (DATA_WIDTH bits)
state_in
LFSR/CRC current state input (LFSR_WIDTH bits)
data_out
Data bits shifted out of LFSR (DATA_WIDTH bits)
state_out
LFSR/CRC next state output (LFSR_WIDTH bits)
Parameters:
LFSR_WIDTH
Specify width of LFSR/CRC register
LFSR_POLY
Specify the LFSR/CRC polynomial in hex format. For example, the polynomial
x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
would be represented as
32'h04c11db7
Note that the largest term (x^32) is suppressed. This term is generated automatically based
on LFSR_WIDTH.
LFSR_CONFIG
Specify the LFSR configuration, either Fibonacci or Galois. Fibonacci is generally used
for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,
scramblers, and descrambers, while Galois is generally used for cyclic redundancy check
generators and checkers.
Fibonacci style (example for 64b66b scrambler, 0x8000000001)
DIN (LSB first)
|
V
(+)<---------------------------(+)<-----------------------------.
| ^ |
| .----. .----. .----. | .----. .----. .----. |
+->| 0 |->| 1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'
| '----' '----' '----' '----' '----' '----'
V
DOUT
Galois style (example for CRC16, 0x8005)
,-------------------+-------------------------+----------(+)<-- DIN (MSB first)
| | | ^
| .----. .----. V .----. .----. V .----. |
`->| 0 |->| 1 |->(+)->| 2 |->...->| 14 |->(+)->| 15 |--+---> DOUT
'----' '----' '----' '----' '----'
LFSR_FEED_FORWARD
Generate feed forward instead of feed back LFSR. Enable this for PRBS checking and self-
synchronous descrambling.
Fibonacci feed-forward style (example for 64b66b descrambler, 0x8000000001)
DIN (LSB first)
|
| .----. .----. .----. .----. .----. .----.
+->| 0 |->| 1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--.
| '----' '----' '----' | '----' '----' '----' |
| V |
(+)<---------------------------(+)------------------------------'
|
V
DOUT
Galois feed-forward style
,-------------------+-------------------------+------------+--- DIN (MSB first)
| | | |
| .----. .----. V .----. .----. V .----. V
`->| 0 |->| 1 |->(+)->| 2 |->...->| 14 |->(+)->| 15 |->(+)-> DOUT
'----' '----' '----' '----' '----'
REVERSE
Bit-reverse LFSR input and output. Shifts MSB first by default, set REVERSE for LSB first.
DATA_WIDTH
Specify width of input and output data bus. The module will perform one shift per input
data bit, so if the input data bus is not required tie data_in to zero and set DATA_WIDTH
to the required number of shifts per clock cycle.
STYLE
Specify implementation style. Can be "AUTO", "LOOP", or "REDUCTION". When "AUTO"
is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate
directives. "REDUCTION" and "LOOP" are functionally identical, however they simulate
and synthesize differently. "REDUCTION" is implemented with a loop over a Verilog
reduction operator. "LOOP" is implemented as a doubly-nested loop with no reduction
operator. "REDUCTION" is very fast for simulation in iverilog and synthesizes well in
Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing
problems with the optimizer. "LOOP" synthesizes will in both ISE and Quartus. "AUTO"
will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey
synthesis translate directives.
Settings for common LFSR/CRC implementations:
Name Configuration Length Polynomial Initial value Notes
CRC16-IBM Galois, bit-reverse 16 16'h8005 16'hffff
CRC16-CCITT Galois 16 16'h1021 16'h1d0f
CRC32 Galois, bit-reverse 32 32'h04c11db7 32'hffffffff Ethernet FCS; invert final output
CRC32C Galois, bit-reverse 32 32'h1edc6f41 32'hffffffff iSCSI, Intel CRC32 instruction; invert final output
PRBS6 Fibonacci 6 6'h21 any
PRBS7 Fibonacci 7 7'h41 any
PRBS9 Fibonacci 9 9'h021 any ITU V.52
PRBS10 Fibonacci 10 10'h081 any ITU
PRBS11 Fibonacci 11 11'h201 any ITU O.152
PRBS15 Fibonacci, inverted 15 15'h4001 any ITU O.152
PRBS17 Fibonacci 17 17'h04001 any
PRBS20 Fibonacci 20 20'h00009 any ITU V.57
PRBS23 Fibonacci, inverted 23 23'h040001 any ITU O.151
PRBS29 Fibonacci, inverted 29 29'h08000001 any
PRBS31 Fibonacci, inverted 31 31'h10000001 any
64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet
128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3
*/
function [LFSR_WIDTH+DATA_WIDTH-1:0] lfsr_mask(input [31:0] index);
reg [LFSR_WIDTH-1:0] lfsr_mask_state[LFSR_WIDTH-1:0];
reg [DATA_WIDTH-1:0] lfsr_mask_data[LFSR_WIDTH-1:0];
reg [LFSR_WIDTH-1:0] output_mask_state[DATA_WIDTH-1:0];
reg [DATA_WIDTH-1:0] output_mask_data[DATA_WIDTH-1:0];
reg [LFSR_WIDTH-1:0] state_val;
reg [DATA_WIDTH-1:0] data_val;
reg [DATA_WIDTH-1:0] data_mask;
integer i, j;
begin
// init bit masks
for (i = 0; i < LFSR_WIDTH; i = i + 1) begin
lfsr_mask_state[i] = 0;
lfsr_mask_state[i][i] = 1'b1;
lfsr_mask_data[i] = 0;
end
for (i = 0; i < DATA_WIDTH; i = i + 1) begin
output_mask_state[i] = 0;
if (i < LFSR_WIDTH) begin
output_mask_state[i][i] = 1'b1;
end
output_mask_data[i] = 0;
end
// simulate shift register
if (LFSR_CONFIG == "FIBONACCI") begin
// Fibonacci configuration
for (data_mask = {1'b1, {DATA_WIDTH-1{1'b0}}}; data_mask != 0; data_mask = data_mask >> 1) begin
// determine shift in value
// current value in last FF, XOR with input data bit (MSB first)
state_val = lfsr_mask_state[LFSR_WIDTH-1];
data_val = lfsr_mask_data[LFSR_WIDTH-1];
data_val = data_val ^ data_mask;
// add XOR inputs from correct indicies
for (j = 1; j < LFSR_WIDTH; j = j + 1) begin
if ((LFSR_POLY >> j) & 1) begin
state_val = lfsr_mask_state[j-1] ^ state_val;
data_val = lfsr_mask_data[j-1] ^ data_val;
end
end
// shift
for (j = LFSR_WIDTH-1; j > 0; j = j - 1) begin
lfsr_mask_state[j] = lfsr_mask_state[j-1];
lfsr_mask_data[j] = lfsr_mask_data[j-1];
end
for (j = DATA_WIDTH-1; j > 0; j = j - 1) begin
output_mask_state[j] = output_mask_state[j-1];
output_mask_data[j] = output_mask_data[j-1];
end
output_mask_state[0] = state_val;
output_mask_data[0] = data_val;
if (LFSR_FEED_FORWARD) begin
// only shift in new input data
state_val = {LFSR_WIDTH{1'b0}};
data_val = data_mask;
end
lfsr_mask_state[0] = state_val;
lfsr_mask_data[0] = data_val;
end
end else if (LFSR_CONFIG == "GALOIS") begin
// Galois configuration
for (data_mask = {1'b1, {DATA_WIDTH-1{1'b0}}}; data_mask != 0; data_mask = data_mask >> 1) begin
// determine shift in value
// current value in last FF, XOR with input data bit (MSB first)
state_val = lfsr_mask_state[LFSR_WIDTH-1];
data_val = lfsr_mask_data[LFSR_WIDTH-1];
data_val = data_val ^ data_mask;
// shift
for (j = LFSR_WIDTH-1; j > 0; j = j - 1) begin
lfsr_mask_state[j] = lfsr_mask_state[j-1];
lfsr_mask_data[j] = lfsr_mask_data[j-1];
end
for (j = DATA_WIDTH-1; j > 0; j = j - 1) begin
output_mask_state[j] = output_mask_state[j-1];
output_mask_data[j] = output_mask_data[j-1];
end
output_mask_state[0] = state_val;
output_mask_data[0] = data_val;
if (LFSR_FEED_FORWARD) begin
// only shift in new input data
state_val = {LFSR_WIDTH{1'b0}};
data_val = data_mask;
end
lfsr_mask_state[0] = state_val;
lfsr_mask_data[0] = data_val;
// add XOR inputs at correct indicies
for (j = 1; j < LFSR_WIDTH; j = j + 1) begin
if ((LFSR_POLY >> j) & 1) begin
lfsr_mask_state[j] = lfsr_mask_state[j] ^ state_val;
lfsr_mask_data[j] = lfsr_mask_data[j] ^ data_val;
end
end
end
end else begin
$error("Error: unknown configuration setting!");
$finish;
end
// reverse bits if selected
if (REVERSE) begin
if (index < LFSR_WIDTH) begin
state_val = 0;
for (i = 0; i < LFSR_WIDTH; i = i + 1) begin
state_val[i] = lfsr_mask_state[LFSR_WIDTH-index-1][LFSR_WIDTH-i-1];
end
data_val = 0;
for (i = 0; i < DATA_WIDTH; i = i + 1) begin
data_val[i] = lfsr_mask_data[LFSR_WIDTH-index-1][DATA_WIDTH-i-1];
end
end else begin
state_val = 0;
for (i = 0; i < LFSR_WIDTH; i = i + 1) begin
state_val[i] = output_mask_state[DATA_WIDTH-(index-LFSR_WIDTH)-1][LFSR_WIDTH-i-1];
end
data_val = 0;
for (i = 0; i < DATA_WIDTH; i = i + 1) begin
data_val[i] = output_mask_data[DATA_WIDTH-(index-LFSR_WIDTH)-1][DATA_WIDTH-i-1];
end
end
end else begin
if (index < LFSR_WIDTH) begin
state_val = lfsr_mask_state[index];
data_val = lfsr_mask_data[index];
end else begin
state_val = output_mask_state[index-LFSR_WIDTH];
data_val = output_mask_data[index-LFSR_WIDTH];
end
end
lfsr_mask = {data_val, state_val};
end
endfunction
// synthesis translate_off
`define SIMULATION
// synthesis translate_on
`ifdef SIMULATION
// "AUTO" style is "REDUCTION" for faster simulation
parameter STYLE_INT = (STYLE == "AUTO") ? "REDUCTION" : STYLE;
`else
// "AUTO" style is "LOOP" for better synthesis result
parameter STYLE_INT = (STYLE == "AUTO") ? "LOOP" : STYLE;
`endif
genvar n;
generate
if (STYLE_INT == "REDUCTION") begin
// use Verilog reduction operator
// fast in iverilog
// significantly larger than generated code with ISE (inferred wide XORs may be tripping up optimizer)
// slightly smaller than generated code with Quartus
// --> better for simulation
for (n = 0; n < LFSR_WIDTH; n = n + 1) begin : lfsr_state
wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n);
assign state_out[n] = ^({data_in, state_in} & mask);
end
for (n = 0; n < DATA_WIDTH; n = n + 1) begin : lfsr_data
wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n+LFSR_WIDTH);
assign data_out[n] = ^({data_in, state_in} & mask);
end
end else if (STYLE_INT == "LOOP") begin
// use nested loops
// very slow in iverilog
// slightly smaller than generated code with ISE
// same size as generated code with Quartus
// --> better for synthesis
for (n = 0; n < LFSR_WIDTH; n = n + 1) begin : lfsr_state
wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n);
reg state_reg;
assign state_out[n] = state_reg;
integer i;
always @* begin
state_reg = 1'b0;
for (i = 0; i < LFSR_WIDTH; i = i + 1) begin
if (mask[i]) begin
state_reg = state_reg ^ state_in[i];
end
end
for (i = 0; i < DATA_WIDTH; i = i + 1) begin
if (mask[i+LFSR_WIDTH]) begin
state_reg = state_reg ^ data_in[i];
end
end
end
end
for (n = 0; n < DATA_WIDTH; n = n + 1) begin : lfsr_data
wire [LFSR_WIDTH+DATA_WIDTH-1:0] mask = lfsr_mask(n+LFSR_WIDTH);
reg data_reg;
assign data_out[n] = data_reg;
integer i;
always @* begin
data_reg = 1'b0;
for (i = 0; i < LFSR_WIDTH; i = i + 1) begin
if (mask[i]) begin
data_reg = data_reg ^ state_in[i];
end
end
for (i = 0; i < DATA_WIDTH; i = i + 1) begin
if (mask[i+LFSR_WIDTH]) begin
data_reg = data_reg ^ data_in[i];
end
end
end
end
end else begin
initial begin
$error("Error: unknown style setting!");
$finish;
end
end
endgenerate
endmodule
`resetall
================================================
FILE: rtl/lfsr_crc.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* LFSR CRC generator
*/
module lfsr_crc #
(
// width of LFSR
parameter LFSR_WIDTH = 32,
// LFSR polynomial
parameter LFSR_POLY = 32'h04c11db7,
// Initial state
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},
// LFSR configuration: "GALOIS", "FIBONACCI"
parameter LFSR_CONFIG = "GALOIS",
// bit-reverse input and output
parameter REVERSE = 1,
// invert output
parameter INVERT = 1,
// width of data input and output
parameter DATA_WIDTH = 8,
// implementation style: "AUTO", "LOOP", "REDUCTION"
parameter STYLE = "AUTO"
)
(
input wire clk,
input wire rst,
input wire [DATA_WIDTH-1:0] data_in,
input wire data_in_valid,
output wire [LFSR_WIDTH-1:0] crc_out
);
/*
Fully parametrizable combinatorial parallel LFSR CRC module. Implements an unrolled LFSR
next state computation.
Ports:
clk
Clock input
rst
Reset module, set state to LFSR_INIT
data_in
CRC data input
data_in_valid
Shift input data through CRC when asserted
data_out
LFSR output (OUTPUT_WIDTH bits)
Parameters:
LFSR_WIDTH
Specify width of LFSR/CRC register
LFSR_POLY
Specify the LFSR/CRC polynomial in hex format. For example, the polynomial
x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
would be represented as
32'h04c11db7
Note that the largest term (x^32) is suppressed. This term is generated automatically based
on LFSR_WIDTH.
LFSR_INIT
Initial state of LFSR. Defaults to all 1s.
LFSR_CONFIG
Specify the LFSR configuration, either Fibonacci or Galois. Fibonacci is generally used
for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,
scramblers, and descrambers, while Galois is generally used for cyclic redundancy check
generators and checkers.
Fibonacci style (example for 64b66b scrambler, 0x8000000001)
DIN (LSB first)
|
V
(+)<---------------------------(+)<-----------------------------.
| ^ |
| .----. .----. .----. | .----. .----. .----. |
+->| 0 |->| 1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'
| '----' '----' '----' '----' '----' '----'
V
DOUT
Galois style (example for CRC16, 0x8005)
,-------------------+-------------------------+----------(+)<-- DIN (MSB first)
| | | ^
| .----. .----. V .----. .----. V .----. |
`->| 0 |->| 1 |->(+)->| 2 |->...->| 14 |->(+)->| 15 |--+---> DOUT
'----' '----' '----' '----' '----'
REVERSE
Bit-reverse LFSR input and output. Shifts MSB first by default, set REVERSE for LSB first.
INVERT
Bitwise invert CRC output.
DATA_WIDTH
Specify width of input data bus. The module will perform one shift per input data bit,
so if the input data bus is not required tie data_in to zero and set DATA_WIDTH to the
required number of shifts per clock cycle.
STYLE
Specify implementation style. Can be "AUTO", "LOOP", or "REDUCTION". When "AUTO"
is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate
directives. "REDUCTION" and "LOOP" are functionally identical, however they simulate
and synthesize differently. "REDUCTION" is implemented with a loop over a Verilog
reduction operator. "LOOP" is implemented as a doubly-nested loop with no reduction
operator. "REDUCTION" is very fast for simulation in iverilog and synthesizes well in
Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing
problems with the optimizer. "LOOP" synthesizes will in both ISE and Quartus. "AUTO"
will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey
synthesis translate directives.
Settings for common LFSR/CRC implementations:
Name Configuration Length Polynomial Initial value Notes
CRC16-IBM Galois, bit-reverse 16 16'h8005 16'hffff
CRC16-CCITT Galois 16 16'h1021 16'h1d0f
CRC32 Galois, bit-reverse 32 32'h04c11db7 32'hffffffff Ethernet FCS; invert final output
CRC32C Galois, bit-reverse 32 32'h1edc6f41 32'hffffffff iSCSI, Intel CRC32 instruction; invert final output
*/
reg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;
reg [LFSR_WIDTH-1:0] output_reg = 0;
wire [LFSR_WIDTH-1:0] lfsr_state;
assign crc_out = output_reg;
lfsr #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_CONFIG(LFSR_CONFIG),
.LFSR_FEED_FORWARD(0),
.REVERSE(REVERSE),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
lfsr_inst (
.data_in(data_in),
.state_in(state_reg),
.data_out(),
.state_out(lfsr_state)
);
always @(posedge clk) begin
if (rst) begin
state_reg <= LFSR_INIT;
output_reg <= 0;
end else begin
if (data_in_valid) begin
state_reg <= lfsr_state;
if (INVERT) begin
output_reg <= ~lfsr_state;
end else begin
output_reg <= lfsr_state;
end
end
end
end
endmodule
`resetall
================================================
FILE: rtl/lfsr_descramble.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* LFSR descrambler
*/
module lfsr_descramble #
(
// width of LFSR
parameter LFSR_WIDTH = 58,
// LFSR polynomial
parameter LFSR_POLY = 58'h8000000001,
// Initial state
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},
// LFSR configuration: "GALOIS", "FIBONACCI"
parameter LFSR_CONFIG = "FIBONACCI",
// bit-reverse input and output
parameter REVERSE = 1,
// width of data bus
parameter DATA_WIDTH = 64,
// implementation style: "AUTO", "LOOP", "REDUCTION"
parameter STYLE = "AUTO"
)
(
input wire clk,
input wire rst,
input wire [DATA_WIDTH-1:0] data_in,
input wire data_in_valid,
output wire [DATA_WIDTH-1:0] data_out
);
/*
Fully parametrizable combinatorial parallel LFSR CRC module. Implements an unrolled LFSR
next state computation.
Ports:
clk
Clock input
rst
Reset module, set state to LFSR_INIT
data_in
Scrambled data input (DATA_WIDTH bits)
data_in_valid
Shift input data through CRC when asserted
data_out
Descrambled data output (DATA_WIDTH bits)
Parameters:
LFSR_WIDTH
Specify width of LFSR/CRC register
LFSR_POLY
Specify the LFSR/CRC polynomial in hex format. For example, the polynomial
x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
would be represented as
32'h04c11db7
Note that the largest term (x^32) is suppressed. This term is generated automatically based
on LFSR_WIDTH.
LFSR_INIT
Initial state of LFSR. Defaults to all 1s.
LFSR_CONFIG
Specify the LFSR configuration, either Fibonacci or Galois. Fibonacci is generally used
for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,
scramblers, and descrambers, while Galois is generally used for cyclic redundancy check
generators and checkers.
Fibonacci style (example for 64b66b scrambler, 0x8000000001)
DIN (LSB first)
|
V
(+)<---------------------------(+)<-----------------------------.
| ^ |
| .----. .----. .----. | .----. .----. .----. |
+->| 0 |->| 1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'
| '----' '----' '----' '----' '----' '----'
V
DOUT
Galois style (example for CRC16, 0x8005)
,-------------------+-------------------------+----------(+)<-- DIN (MSB first)
| | | ^
| .----. .----. V .----. .----. V .----. |
`->| 0 |->| 1 |->(+)->| 2 |->...->| 14 |->(+)->| 15 |--+---> DOUT
'----' '----' '----' '----' '----'
REVERSE
Bit-reverse LFSR input and output.
DATA_WIDTH
Specify width of the data bus. The module will perform one shift per input data bit.
STYLE
Specify implementation style. Can be "AUTO", "LOOP", or "REDUCTION". When "AUTO"
is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate
directives. "REDUCTION" and "LOOP" are functionally identical, however they simulate
and synthesize differently. "REDUCTION" is implemented with a loop over a Verilog
reduction operator. "LOOP" is implemented as a doubly-nested loop with no reduction
operator. "REDUCTION" is very fast for simulation in iverilog and synthesizes well in
Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing
problems with the optimizer. "LOOP" synthesizes will in both ISE and Quartus. "AUTO"
will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey
synthesis translate directives.
Settings for common LFSR/CRC implementations:
Name Configuration Length Polynomial Initial value Notes
CRC32 Galois, bit-reverse 32 32'h04c11db7 32'hffffffff Ethernet FCS; invert final output
PRBS6 Fibonacci 6 6'h21 any
PRBS7 Fibonacci 7 7'h41 any
PRBS9 Fibonacci 9 9'h021 any ITU V.52
PRBS10 Fibonacci 10 10'h081 any ITU
PRBS11 Fibonacci 11 11'h201 any ITU O.152
PRBS15 Fibonacci, inverted 15 15'h4001 any ITU O.152
PRBS17 Fibonacci 17 17'h04001 any
PRBS20 Fibonacci 20 20'h00009 any ITU V.57
PRBS23 Fibonacci, inverted 23 23'h040001 any ITU O.151
PRBS29 Fibonacci, inverted 29 29'h08000001 any
PRBS31 Fibonacci, inverted 31 31'h10000001 any
64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet
128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3
*/
reg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;
reg [DATA_WIDTH-1:0] output_reg = 0;
wire [DATA_WIDTH-1:0] lfsr_data;
wire [LFSR_WIDTH-1:0] lfsr_state;
assign data_out = output_reg;
lfsr #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_CONFIG(LFSR_CONFIG),
.LFSR_FEED_FORWARD(1),
.REVERSE(REVERSE),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
lfsr_inst (
.data_in(data_in),
.state_in(state_reg),
.data_out(lfsr_data),
.state_out(lfsr_state)
);
always @(posedge clk) begin
if (rst) begin
state_reg <= LFSR_INIT;
output_reg <= 0;
end else begin
if (data_in_valid) begin
state_reg <= lfsr_state;
output_reg <= lfsr_data;
end
end
end
endmodule
`resetall
================================================
FILE: rtl/lfsr_prbs_check.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* LFSR PRBS checker
*/
module lfsr_prbs_check #
(
// width of LFSR
parameter LFSR_WIDTH = 31,
// LFSR polynomial
parameter LFSR_POLY = 31'h10000001,
// Initial state
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},
// LFSR configuration: "GALOIS", "FIBONACCI"
parameter LFSR_CONFIG = "FIBONACCI",
// bit-reverse input and output
parameter REVERSE = 0,
// invert input
parameter INVERT = 1,
// width of data input and output
parameter DATA_WIDTH = 8,
// implementation style: "AUTO", "LOOP", "REDUCTION"
parameter STYLE = "AUTO"
)
(
input wire clk,
input wire rst,
input wire [DATA_WIDTH-1:0] data_in,
input wire data_in_valid,
output wire [DATA_WIDTH-1:0] data_out
);
/*
Fully parametrizable combinatorial parallel LFSR PRBS checker. Implements an unrolled LFSR
PRBS checker.
Ports:
clk
Clock input
rst
Reset input, set state to LFSR_INIT
data_in
PRBS data input (DATA_WIDTH bits)
data_in_valid
Shift input data through LFSR when asserted
data_out
Error output (DATA_WIDTH bits)
Parameters:
LFSR_WIDTH
Specify width of LFSR/CRC register
LFSR_POLY
Specify the LFSR/CRC polynomial in hex format. For example, the polynomial
x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
would be represented as
32'h04c11db7
Note that the largest term (x^32) is suppressed. This term is generated automatically based
on LFSR_WIDTH.
LFSR_INIT
Initial state of LFSR. Defaults to all 1s.
LFSR_CONFIG
Specify the LFSR configuration, either Fibonacci or Galois. Fibonacci is generally used
for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,
scramblers, and descrambers, while Galois is generally used for cyclic redundancy check
generators and checkers.
Fibonacci style (example for 64b66b scrambler, 0x8000000001)
DIN (LSB first)
|
V
(+)<---------------------------(+)<-----------------------------.
| ^ |
| .----. .----. .----. | .----. .----. .----. |
+->| 0 |->| 1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'
| '----' '----' '----' '----' '----' '----'
V
DOUT
Galois style (example for CRC16, 0x8005)
,-------------------+-------------------------+----------(+)<-- DIN (MSB first)
| | | ^
| .----. .----. V .----. .----. V .----. |
`->| 0 |->| 1 |->(+)->| 2 |->...->| 14 |->(+)->| 15 |--+---> DOUT
'----' '----' '----' '----' '----'
REVERSE
Bit-reverse LFSR output. Shifts MSB first by default, set REVERSE for LSB first.
INVERT
Bitwise invert PRBS input.
DATA_WIDTH
Specify width of output data bus.
STYLE
Specify implementation style. Can be "AUTO", "LOOP", or "REDUCTION". When "AUTO"
is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate
directives. "REDUCTION" and "LOOP" are functionally identical, however they simulate
and synthesize differently. "REDUCTION" is implemented with a loop over a Verilog
reduction operator. "LOOP" is implemented as a doubly-nested loop with no reduction
operator. "REDUCTION" is very fast for simulation in iverilog and synthesizes well in
Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing
problems with the optimizer. "LOOP" synthesizes will in both ISE and Quartus. "AUTO"
will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey
synthesis translate directives.
Settings for common LFSR/CRC implementations:
Name Configuration Length Polynomial Initial value Notes
CRC32 Galois, bit-reverse 32 32'h04c11db7 32'hffffffff Ethernet FCS; invert final output
PRBS6 Fibonacci 6 6'h21 any
PRBS7 Fibonacci 7 7'h41 any
PRBS9 Fibonacci 9 9'h021 any ITU V.52
PRBS10 Fibonacci 10 10'h081 any ITU
PRBS11 Fibonacci 11 11'h201 any ITU O.152
PRBS15 Fibonacci, inverted 15 15'h4001 any ITU O.152
PRBS17 Fibonacci 17 17'h04001 any
PRBS20 Fibonacci 20 20'h00009 any ITU V.57
PRBS23 Fibonacci, inverted 23 23'h040001 any ITU O.151
PRBS29 Fibonacci, inverted 29 29'h08000001 any
PRBS31 Fibonacci, inverted 31 31'h10000001 any
64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet
128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3
*/
reg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;
reg [DATA_WIDTH-1:0] output_reg = 0;
wire [DATA_WIDTH-1:0] lfsr_data;
wire [LFSR_WIDTH-1:0] lfsr_state;
assign data_out = output_reg;
lfsr #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_CONFIG(LFSR_CONFIG),
.LFSR_FEED_FORWARD(1),
.REVERSE(REVERSE),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
lfsr_inst (
.data_in(INVERT ? ~data_in : data_in),
.state_in(state_reg),
.data_out(lfsr_data),
.state_out(lfsr_state)
);
always @(posedge clk) begin
if (rst) begin
state_reg <= LFSR_INIT;
output_reg <= 0;
end else begin
if (data_in_valid) begin
state_reg <= lfsr_state;
output_reg <= lfsr_data;
end
end
end
endmodule
`resetall
================================================
FILE: rtl/lfsr_prbs_gen.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* LFSR PRBS generator
*/
module lfsr_prbs_gen #
(
// width of LFSR
parameter LFSR_WIDTH = 31,
// LFSR polynomial
parameter LFSR_POLY = 31'h10000001,
// Initial state
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},
// LFSR configuration: "GALOIS", "FIBONACCI"
parameter LFSR_CONFIG = "FIBONACCI",
// bit-reverse input and output
parameter REVERSE = 0,
// invert output
parameter INVERT = 1,
// width of data output
parameter DATA_WIDTH = 8,
// implementation style: "AUTO", "LOOP", "REDUCTION"
parameter STYLE = "AUTO"
)
(
input wire clk,
input wire rst,
input wire enable,
output wire [DATA_WIDTH-1:0] data_out
);
/*
Fully parametrizable combinatorial parallel LFSR PRBS module. Implements an unrolled LFSR
next state computation.
Ports:
clk
Clock input
rst
Reset input, set state to LFSR_INIT
enable
Generate new output data
data_out
LFSR output (DATA_WIDTH bits)
Parameters:
LFSR_WIDTH
Specify width of LFSR/CRC register
LFSR_POLY
Specify the LFSR/CRC polynomial in hex format. For example, the polynomial
x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
would be represented as
32'h04c11db7
Note that the largest term (x^32) is suppressed. This term is generated automatically based
on LFSR_WIDTH.
LFSR_INIT
Initial state of LFSR. Defaults to all 1s.
LFSR_CONFIG
Specify the LFSR configuration, either Fibonacci or Galois. Fibonacci is generally used
for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,
scramblers, and descrambers, while Galois is generally used for cyclic redundancy check
generators and checkers.
Fibonacci style (example for 64b66b scrambler, 0x8000000001)
DIN (LSB first)
|
V
(+)<---------------------------(+)<-----------------------------.
| ^ |
| .----. .----. .----. | .----. .----. .----. |
+->| 0 |->| 1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'
| '----' '----' '----' '----' '----' '----'
V
DOUT
Galois style (example for CRC16, 0x8005)
,-------------------+-------------------------+----------(+)<-- DIN (MSB first)
| | | ^
| .----. .----. V .----. .----. V .----. |
`->| 0 |->| 1 |->(+)->| 2 |->...->| 14 |->(+)->| 15 |--+---> DOUT
'----' '----' '----' '----' '----'
REVERSE
Bit-reverse LFSR output. Shifts MSB first by default, set REVERSE for LSB first.
INVERT
Bitwise invert PRBS output.
DATA_WIDTH
Specify width of output data bus.
STYLE
Specify implementation style. Can be "AUTO", "LOOP", or "REDUCTION". When "AUTO"
is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate
directives. "REDUCTION" and "LOOP" are functionally identical, however they simulate
and synthesize differently. "REDUCTION" is implemented with a loop over a Verilog
reduction operator. "LOOP" is implemented as a doubly-nested loop with no reduction
operator. "REDUCTION" is very fast for simulation in iverilog and synthesizes well in
Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing
problems with the optimizer. "LOOP" synthesizes will in both ISE and Quartus. "AUTO"
will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey
synthesis translate directives.
Settings for common LFSR/CRC implementations:
Name Configuration Length Polynomial Initial value Notes
CRC32 Galois, bit-reverse 32 32'h04c11db7 32'hffffffff Ethernet FCS; invert final output
PRBS6 Fibonacci 6 6'h21 any
PRBS7 Fibonacci 7 7'h41 any
PRBS9 Fibonacci 9 9'h021 any ITU V.52
PRBS10 Fibonacci 10 10'h081 any ITU
PRBS11 Fibonacci 11 11'h201 any ITU O.152
PRBS15 Fibonacci, inverted 15 15'h4001 any ITU O.152
PRBS17 Fibonacci 17 17'h04001 any
PRBS20 Fibonacci 20 20'h00009 any ITU V.57
PRBS23 Fibonacci, inverted 23 23'h040001 any ITU O.151
PRBS29 Fibonacci, inverted 29 29'h08000001 any
PRBS31 Fibonacci, inverted 31 31'h10000001 any
64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet
128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3
*/
reg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;
reg [DATA_WIDTH-1:0] output_reg = 0;
wire [DATA_WIDTH-1:0] lfsr_data;
wire [LFSR_WIDTH-1:0] lfsr_state;
assign data_out = output_reg;
lfsr #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_CONFIG(LFSR_CONFIG),
.LFSR_FEED_FORWARD(0),
.REVERSE(REVERSE),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
lfsr_inst (
.data_in({DATA_WIDTH{1'b0}}),
.state_in(state_reg),
.data_out(lfsr_data),
.state_out(lfsr_state)
);
always @* begin
if (INVERT) begin
output_reg <= ~lfsr_data;
end else begin
output_reg <= lfsr_data;
end
end
always @(posedge clk) begin
if (rst) begin
state_reg <= LFSR_INIT;
end else begin
if (enable) begin
state_reg <= lfsr_state;
end
end
end
endmodule
`resetall
================================================
FILE: rtl/lfsr_scramble.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* LFSR scrambler
*/
module lfsr_scramble #
(
// width of LFSR
parameter LFSR_WIDTH = 58,
// LFSR polynomial
parameter LFSR_POLY = 58'h8000000001,
// Initial state
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}},
// LFSR configuration: "GALOIS", "FIBONACCI"
parameter LFSR_CONFIG = "FIBONACCI",
// bit-reverse input and output
parameter REVERSE = 1,
// width of data bus
parameter DATA_WIDTH = 64,
// implementation style: "AUTO", "LOOP", "REDUCTION"
parameter STYLE = "AUTO"
)
(
input wire clk,
input wire rst,
input wire [DATA_WIDTH-1:0] data_in,
input wire data_in_valid,
output wire [DATA_WIDTH-1:0] data_out
);
/*
Fully parametrizable combinatorial parallel LFSR CRC module. Implements an unrolled LFSR
next state computation.
Ports:
clk
Clock input
rst
Reset module, set state to LFSR_INIT
data_in
Unscrambled data input (DATA_WIDTH bits)
data_in_valid
Shift input data through CRC when asserted
data_out
Scrambled data output (DATA_WIDTH bits)
Parameters:
LFSR_WIDTH
Specify width of LFSR/CRC register
LFSR_POLY
Specify the LFSR/CRC polynomial in hex format. For example, the polynomial
x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
would be represented as
32'h04c11db7
Note that the largest term (x^32) is suppressed. This term is generated automatically based
on LFSR_WIDTH.
LFSR_INIT
Initial state of LFSR. Defaults to all 1s.
LFSR_CONFIG
Specify the LFSR configuration, either Fibonacci or Galois. Fibonacci is generally used
for linear-feedback shift registers (LFSR) for pseudorandom binary sequence (PRBS) generators,
scramblers, and descrambers, while Galois is generally used for cyclic redundancy check
generators and checkers.
Fibonacci style (example for 64b66b scrambler, 0x8000000001)
DIN (LSB first)
|
V
(+)<---------------------------(+)<-----------------------------.
| ^ |
| .----. .----. .----. | .----. .----. .----. |
+->| 0 |->| 1 |->...->| 38 |-+->| 39 |->...->| 56 |->| 57 |--'
| '----' '----' '----' '----' '----' '----'
V
DOUT
Galois style (example for CRC16, 0x8005)
,-------------------+-------------------------+----------(+)<-- DIN (MSB first)
| | | ^
| .----. .----. V .----. .----. V .----. |
`->| 0 |->| 1 |->(+)->| 2 |->...->| 14 |->(+)->| 15 |--+---> DOUT
'----' '----' '----' '----' '----'
REVERSE
Bit-reverse LFSR input and output.
DATA_WIDTH
Specify width of the data bus. The module will perform one shift per input data bit.
STYLE
Specify implementation style. Can be "AUTO", "LOOP", or "REDUCTION". When "AUTO"
is selected, implemenation will be "LOOP" or "REDUCTION" based on synthesis translate
directives. "REDUCTION" and "LOOP" are functionally identical, however they simulate
and synthesize differently. "REDUCTION" is implemented with a loop over a Verilog
reduction operator. "LOOP" is implemented as a doubly-nested loop with no reduction
operator. "REDUCTION" is very fast for simulation in iverilog and synthesizes well in
Quartus but synthesizes poorly in ISE, likely due to large inferred XOR gates causing
problems with the optimizer. "LOOP" synthesizes will in both ISE and Quartus. "AUTO"
will default to "REDUCTION" when simulating and "LOOP" for synthesizers that obey
synthesis translate directives.
Settings for common LFSR/CRC implementations:
Name Configuration Length Polynomial Initial value Notes
CRC32 Galois, bit-reverse 32 32'h04c11db7 32'hffffffff Ethernet FCS; invert final output
PRBS6 Fibonacci 6 6'h21 any
PRBS7 Fibonacci 7 7'h41 any
PRBS9 Fibonacci 9 9'h021 any ITU V.52
PRBS10 Fibonacci 10 10'h081 any ITU
PRBS11 Fibonacci 11 11'h201 any ITU O.152
PRBS15 Fibonacci, inverted 15 15'h4001 any ITU O.152
PRBS17 Fibonacci 17 17'h04001 any
PRBS20 Fibonacci 20 20'h00009 any ITU V.57
PRBS23 Fibonacci, inverted 23 23'h040001 any ITU O.151
PRBS29 Fibonacci, inverted 29 29'h08000001 any
PRBS31 Fibonacci, inverted 31 31'h10000001 any
64b66b Fibonacci, bit-reverse 58 58'h8000000001 any 10G Ethernet
128b130b Galois, bit-reverse 23 23'h210125 any PCIe gen 3
*/
reg [LFSR_WIDTH-1:0] state_reg = LFSR_INIT;
reg [DATA_WIDTH-1:0] output_reg = 0;
wire [DATA_WIDTH-1:0] lfsr_data;
wire [LFSR_WIDTH-1:0] lfsr_state;
assign data_out = output_reg;
lfsr #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_CONFIG(LFSR_CONFIG),
.LFSR_FEED_FORWARD(0),
.REVERSE(REVERSE),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
lfsr_inst (
.data_in(data_in),
.state_in(state_reg),
.data_out(lfsr_data),
.state_out(lfsr_state)
);
always @(posedge clk) begin
if (rst) begin
state_reg <= LFSR_INIT;
output_reg <= 0;
end else begin
if (data_in_valid) begin
state_reg <= lfsr_state;
output_reg <= lfsr_data;
end
end
end
endmodule
`resetall
================================================
FILE: tb/lfsr/Makefile
================================================
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
TOPLEVEL_LANG = verilog
SIM ?= icarus
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
DUT = lfsr
TOPLEVEL = $(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
# module parameters
export PARAM_LFSR_WIDTH ?= 32
export PARAM_LFSR_POLY ?= "32'h4c11db7"
export PARAM_LFSR_CONFIG ?= "\"GALOIS\""
export PARAM_LFSR_FEED_FORWARD ?= 0
export PARAM_REVERSE ?= 1
export PARAM_DATA_WIDTH ?= 8
export PARAM_STYLE ?= "\"AUTO\""
ifeq ($(SIM), icarus)
PLUSARGS += -fst
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
COMPILE_ARGS += -s iverilog_dump
endif
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst
endif
endif
include $(shell cocotb-config --makefiles)/Makefile.sim
iverilog_dump.v:
echo 'module iverilog_dump();' > $@
echo 'initial begin' >> $@
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
echo 'end' >> $@
echo 'endmodule' >> $@
clean::
@rm -rf iverilog_dump.v
@rm -rf dump.fst $(TOPLEVEL).fst
================================================
FILE: tb/lfsr/test_lfsr.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2023 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import itertools
import logging
import os
import zlib
import pytest
import cocotb_test.simulator
import cocotb
from cocotb.triggers import Timer
from cocotb.regression import TestFactory
class TB:
def __init__(self, dut):
self.dut = dut
self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG)
dut.data_in.setimmediatevalue(0)
dut.state_in.setimmediatevalue(0)
def chunks(lst, n, padvalue=None):
return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)
def crc32(data):
return zlib.crc32(data) & 0xffffffff
def crc32c(data, crc=0xffffffff, poly=0x82f63b78):
for d in data:
crc = crc ^ d
for bit in range(0, 8):
if crc & 1:
crc = (crc >> 1) ^ poly
else:
crc = crc >> 1
return ~crc & 0xffffffff
async def run_test_crc(dut, ref_crc):
data_width = len(dut.data_in)
byte_lanes = data_width // 8
state_width = len(dut.state_in)
state_mask = 2**state_width-1
tb = TB(dut)
await Timer(10, 'ns')
block = bytes([(x+1)*0x11 for x in range(byte_lanes)])
dut.state_in.value = state_mask
dut.data_in.value = int.from_bytes(block, 'little')
await Timer(10, 'ns')
val = ~dut.state_out.value.integer & state_mask
ref = ref_crc(block)
tb.log.info("CRC: 0x%x (ref: 0x%x)", val, ref)
assert val == ref
await Timer(10, 'ns')
block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))
dut.state_in.value = state_mask
for b in chunks(block, byte_lanes):
dut.data_in.value = int.from_bytes(b, 'little')
await Timer(10, 'ns')
dut.state_in.value = dut.state_out.value
val = ~dut.state_out.value.integer & state_mask
ref = ref_crc(block)
tb.log.info("CRC: 0x%x (ref: 0x%x)", val, ref)
assert val == ref
await Timer(10, 'ns')
def prbs9(state=0x1ff):
while True:
for i in range(8):
if bool(state & 0x10) ^ bool(state & 0x100):
state = ((state & 0xff) << 1) | 1
else:
state = (state & 0xff) << 1
yield ~state & 0xff
def prbs31(state=0x7fffffff):
while True:
for i in range(8):
if bool(state & 0x08000000) ^ bool(state & 0x40000000):
state = ((state & 0x3fffffff) << 1) | 1
else:
state = (state & 0x3fffffff) << 1
yield ~state & 0xff
async def run_test_prbs(dut, ref_prbs):
data_width = len(dut.data_in)
byte_lanes = data_width // 8
data_mask = 2**data_width-1
state_width = len(dut.state_in)
state_mask = 2**state_width-1
tb = TB(dut)
await Timer(10, 'ns')
dut.state_in.value = state_mask
dut.data_in.value = 0
gen = chunks(ref_prbs(), byte_lanes)
await Timer(10, 'ns')
for i in range(512):
ref = int.from_bytes(bytes(next(gen)), 'big')
val = ~dut.data_out.value.integer & data_mask
tb.log.info("PRBS: 0x%x (ref: 0x%x)", val, ref)
assert ref == val
dut.state_in.value = dut.state_out.value
await Timer(10, 'ns')
if cocotb.SIM_NAME:
if cocotb.top.LFSR_POLY.value == 0x4c11db7:
factory = TestFactory(run_test_crc)
factory.add_option("ref_crc", [crc32])
factory.generate_tests()
if cocotb.top.LFSR_POLY.value == 0x1edc6f41:
factory = TestFactory(run_test_crc)
factory.add_option("ref_crc", [crc32c])
factory.generate_tests()
if cocotb.top.LFSR_POLY.value == 0x021:
factory = TestFactory(run_test_prbs)
factory.add_option("ref_prbs", [prbs9])
factory.generate_tests()
if cocotb.top.LFSR_POLY.value == 0x10000001:
factory = TestFactory(run_test_prbs)
factory.add_option("ref_prbs", [prbs31])
factory.generate_tests()
# cocotb-test
tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
@pytest.mark.parametrize("style", ["AUTO", "LOOP"])
@pytest.mark.parametrize(("lfsr_width", "lfsr_poly", "lfsr_config", "reverse", "data_width"), [
(32, "32'h4c11db7", "GALOIS", 1, 8),
(32, "32'h4c11db7", "GALOIS", 1, 64),
(32, "32'h1edc6f41", "GALOIS", 1, 8),
(32, "32'h1edc6f41", "GALOIS", 1, 64),
(9, "9'h021", "FIBONACCI", 0, 8),
(9, "9'h021", "FIBONACCI", 0, 64),
(31, "31'h10000001", "FIBONACCI", 0, 8),
(31, "31'h10000001", "FIBONACCI", 0, 64),
])
def test_lfsr(request, lfsr_width, lfsr_poly, lfsr_config, reverse, data_width, style):
dut = "lfsr"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
]
parameters = {}
parameters['LFSR_WIDTH'] = lfsr_width
parameters['LFSR_POLY'] = lfsr_poly
parameters['LFSR_CONFIG'] = f'"{lfsr_config}"'
parameters['LFSR_FEED_FORWARD'] = 0
parameters['REVERSE'] = reverse
parameters['DATA_WIDTH'] = data_width
parameters['STYLE'] = f'"{style}"'
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)
================================================
FILE: tb/lfsr_crc/Makefile
================================================
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
TOPLEVEL_LANG = verilog
SIM ?= icarus
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
DUT = lfsr_crc
TOPLEVEL = $(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../rtl/lfsr.v
# module parameters
export PARAM_LFSR_WIDTH ?= 32
export PARAM_LFSR_POLY ?= "32'h4c11db7"
export PARAM_LFSR_INIT ?= "32'hffffffff"
export PARAM_LFSR_CONFIG ?= "\"GALOIS\""
export PARAM_REVERSE ?= 1
export PARAM_INVERT ?= 1
export PARAM_DATA_WIDTH ?= 8
export PARAM_STYLE ?= "\"AUTO\""
ifeq ($(SIM), icarus)
PLUSARGS += -fst
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
COMPILE_ARGS += -s iverilog_dump
endif
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst
endif
endif
include $(shell cocotb-config --makefiles)/Makefile.sim
iverilog_dump.v:
echo 'module iverilog_dump();' > $@
echo 'initial begin' >> $@
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
echo 'end' >> $@
echo 'endmodule' >> $@
clean::
@rm -rf iverilog_dump.v
@rm -rf dump.fst $(TOPLEVEL).fst
================================================
FILE: tb/lfsr_crc/test_lfsr_crc.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2023 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import itertools
import logging
import os
import zlib
import pytest
import cocotb_test.simulator
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.regression import TestFactory
class TB:
def __init__(self, dut):
self.dut = dut
self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG)
cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())
dut.data_in.setimmediatevalue(0)
dut.data_in_valid.setimmediatevalue(0)
async def reset(self):
self.dut.rst.setimmediatevalue(0)
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
self.dut.rst.value = 1
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
self.dut.rst.value = 0
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
def chunks(lst, n, padvalue=None):
return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)
def crc32(data):
return zlib.crc32(data) & 0xffffffff
def crc32c(data, crc=0xffffffff, poly=0x82f63b78):
for d in data:
crc = crc ^ d
for bit in range(0, 8):
if crc & 1:
crc = (crc >> 1) ^ poly
else:
crc = crc >> 1
return ~crc & 0xffffffff
async def run_test_crc(dut, ref_crc):
data_width = len(dut.data_in)
byte_lanes = data_width // 8
tb = TB(dut)
await tb.reset()
block = bytes([(x+1)*0x11 for x in range(byte_lanes)])
dut.data_in.value = int.from_bytes(block, 'little')
dut.data_in_valid.value = 1
await RisingEdge(dut.clk)
dut.data_in_valid.value = 0
await RisingEdge(dut.clk)
val = dut.crc_out.value.integer
ref = ref_crc(block)
tb.log.info("CRC: 0x%x (ref: 0x%x)", val, ref)
assert val == ref
await tb.reset()
block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))
for b in chunks(block, byte_lanes):
dut.data_in.value = int.from_bytes(b, 'little')
dut.data_in_valid.value = 1
await RisingEdge(dut.clk)
dut.data_in_valid.value = 0
await RisingEdge(dut.clk)
val = dut.crc_out.value.integer
ref = ref_crc(block)
tb.log.info("CRC: 0x%x (ref: 0x%x)", val, ref)
assert val == ref
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
if cocotb.SIM_NAME:
if cocotb.top.LFSR_POLY.value == 0x4c11db7:
factory = TestFactory(run_test_crc)
factory.add_option("ref_crc", [crc32])
factory.generate_tests()
if cocotb.top.LFSR_POLY.value == 0x1edc6f41:
factory = TestFactory(run_test_crc)
factory.add_option("ref_crc", [crc32c])
factory.generate_tests()
# cocotb-test
tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
@pytest.mark.parametrize("style", ["AUTO", "LOOP"])
@pytest.mark.parametrize(("lfsr_width", "lfsr_poly", "lfsr_init", "lfsr_config", "reverse", "invert", "data_width"), [
(32, "32'h4c11db7", "32'hffffffff", "GALOIS", 1, 1, 8),
(32, "32'h4c11db7", "32'hffffffff", "GALOIS", 1, 1, 64),
(32, "32'h1edc6f41", "32'hffffffff", "GALOIS", 1, 1, 8),
(32, "32'h1edc6f41", "32'hffffffff", "GALOIS", 1, 1, 64),
])
def test_lfsr_crc(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, invert, data_width, style):
dut = "lfsr_crc"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
os.path.join(rtl_dir, "lfsr.v"),
]
parameters = {}
parameters['LFSR_WIDTH'] = lfsr_width
parameters['LFSR_POLY'] = lfsr_poly
parameters['LFSR_INIT'] = lfsr_init
parameters['LFSR_CONFIG'] = f'"{lfsr_config}"'
parameters['REVERSE'] = reverse
parameters['INVERT'] = invert
parameters['DATA_WIDTH'] = data_width
parameters['STYLE'] = f'"{style}"'
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)
================================================
FILE: tb/lfsr_descramble/Makefile
================================================
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
TOPLEVEL_LANG = verilog
SIM ?= icarus
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
DUT = lfsr_descramble
TOPLEVEL = $(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../rtl/lfsr.v
# module parameters
export PARAM_LFSR_WIDTH ?= 58
export PARAM_LFSR_POLY ?= "58'h8000000001"
export PARAM_LFSR_INIT ?= "58'h3ffffffffffffff"
export PARAM_LFSR_CONFIG ?= "\"FIBONACCI\""
export PARAM_REVERSE ?= 1
export PARAM_DATA_WIDTH ?= 8
export PARAM_STYLE ?= "\"AUTO\""
ifeq ($(SIM), icarus)
PLUSARGS += -fst
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
COMPILE_ARGS += -s iverilog_dump
endif
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst
endif
endif
include $(shell cocotb-config --makefiles)/Makefile.sim
iverilog_dump.v:
echo 'module iverilog_dump();' > $@
echo 'initial begin' >> $@
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
echo 'end' >> $@
echo 'endmodule' >> $@
clean::
@rm -rf iverilog_dump.v
@rm -rf dump.fst $(TOPLEVEL).fst
================================================
FILE: tb/lfsr_descramble/test_lfsr_descramble.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2023 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import itertools
import logging
import os
import pytest
import cocotb_test.simulator
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.regression import TestFactory
class TB:
def __init__(self, dut):
self.dut = dut
self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG)
cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())
dut.data_in.setimmediatevalue(0)
dut.data_in_valid.setimmediatevalue(0)
async def reset(self):
self.dut.rst.setimmediatevalue(0)
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
self.dut.rst.value = 1
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
self.dut.rst.value = 0
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
def chunks(lst, n, padvalue=None):
return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)
def scramble_64b66b(data, state=0x3ffffffffffffff):
data_out = bytearray()
for d in data:
b = 0
for i in range(8):
if bool(state & (1 << 38)) ^ bool(state & (1 << 57)) ^ bool(d & (1 << i)):
state = ((state & 0x1ffffffffffffff) << 1) | 1
b = b | (1 << i)
else:
state = (state & 0x1ffffffffffffff) << 1
data_out.append(b)
return data_out
def descramble_64b66b(data, state=0x3ffffffffffffff):
data_out = bytearray()
for d in data:
b = 0
for i in range(8):
if bool(state & (1 << 38)) ^ bool(state & (1 << 57)) ^ bool(d & (1 << i)):
b = b | (1 << i)
state = (state & 0x1ffffffffffffff) << 1 | bool(d & (1 << i))
data_out += bytearray([b])
return data_out
async def run_test_descramble(dut, ref_scramble):
data_width = len(dut.data_in)
byte_lanes = data_width // 8
tb = TB(dut)
await tb.reset()
block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))
scr = scramble_64b66b(block)
dscr = descramble_64b66b(scr)
assert dscr == block
ref_iter = iter(chunks(block, byte_lanes))
first = True
for b in chunks(scr, byte_lanes):
dut.data_in.value = int.from_bytes(b, 'little')
dut.data_in_valid.value = 1
await RisingEdge(dut.clk)
val = dut.data_out.value.integer
if not first:
ref = int.from_bytes(bytes(next(ref_iter)), 'little')
tb.log.info("Descrambled: 0x%x (ref: 0x%x)", val, ref)
assert ref == val
first = False
dut.data_in_valid.value = 0
await RisingEdge(dut.clk)
if cocotb.SIM_NAME:
# if cocotb.top.LFSR_POLY.value == 0x8000000001:
if cocotb.top.LFSR_WIDTH == 58:
factory = TestFactory(run_test_descramble)
factory.add_option("ref_scramble", [scramble_64b66b])
factory.generate_tests()
# cocotb-test
tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
@pytest.mark.parametrize("style", ["AUTO", "LOOP"])
@pytest.mark.parametrize(("lfsr_width", "lfsr_poly", "lfsr_init", "lfsr_config", "reverse", "data_width"), [
(58, "58'h8000000001", "58'h3ffffffffffffff", "FIBONACCI", 1, 8),
(58, "58'h8000000001", "58'h3ffffffffffffff", "FIBONACCI", 1, 64),
])
def test_lfsr_descramble(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, data_width, style):
dut = "lfsr_descramble"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
os.path.join(rtl_dir, "lfsr.v"),
]
parameters = {}
parameters['LFSR_WIDTH'] = lfsr_width
parameters['LFSR_POLY'] = lfsr_poly
parameters['LFSR_INIT'] = lfsr_init
parameters['LFSR_CONFIG'] = f'"{lfsr_config}"'
parameters['REVERSE'] = reverse
parameters['DATA_WIDTH'] = data_width
parameters['STYLE'] = f'"{style}"'
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)
================================================
FILE: tb/lfsr_prbs_check/Makefile
================================================
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
TOPLEVEL_LANG = verilog
SIM ?= icarus
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
DUT = lfsr_prbs_check
TOPLEVEL = $(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../rtl/lfsr.v
# module parameters
export PARAM_LFSR_WIDTH ?= 31
export PARAM_LFSR_POLY ?= "31'h10000001"
export PARAM_LFSR_INIT ?= "31'h7fffffff"
export PARAM_LFSR_CONFIG ?= "\"FIBONACCI\""
export PARAM_REVERSE ?= 0
export PARAM_INVERT ?= 1
export PARAM_DATA_WIDTH ?= 8
export PARAM_STYLE ?= "\"AUTO\""
ifeq ($(SIM), icarus)
PLUSARGS += -fst
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
COMPILE_ARGS += -s iverilog_dump
endif
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst
endif
endif
include $(shell cocotb-config --makefiles)/Makefile.sim
iverilog_dump.v:
echo 'module iverilog_dump();' > $@
echo 'initial begin' >> $@
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
echo 'end' >> $@
echo 'endmodule' >> $@
clean::
@rm -rf iverilog_dump.v
@rm -rf dump.fst $(TOPLEVEL).fst
================================================
FILE: tb/lfsr_prbs_check/test_lfsr_prbs_check.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2023 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import itertools
import logging
import os
import pytest
import cocotb_test.simulator
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.regression import TestFactory
class TB:
def __init__(self, dut):
self.dut = dut
self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG)
cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())
dut.data_in.setimmediatevalue(0)
dut.data_in_valid.setimmediatevalue(0)
async def reset(self):
self.dut.rst.setimmediatevalue(0)
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
self.dut.rst.value = 1
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
self.dut.rst.value = 0
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
def chunks(lst, n, padvalue=None):
return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)
def prbs9(state=0x1ff):
while True:
for i in range(8):
if bool(state & 0x10) ^ bool(state & 0x100):
state = ((state & 0xff) << 1) | 1
else:
state = (state & 0xff) << 1
yield ~state & 0xff
def prbs31(state=0x7fffffff):
while True:
for i in range(8):
if bool(state & 0x08000000) ^ bool(state & 0x40000000):
state = ((state & 0x3fffffff) << 1) | 1
else:
state = (state & 0x3fffffff) << 1
yield ~state & 0xff
def count_set_bits(n):
cnt = 0
while n:
n &= n - 1
cnt += 1
return cnt
async def run_test_prbs(dut, ref_prbs):
data_width = len(dut.data_out)
byte_lanes = data_width // 8
tb = TB(dut)
await tb.reset()
gen = chunks(ref_prbs(), byte_lanes)
err_cnt = 0
for i in range(512):
dut.data_in.value = int.from_bytes(bytes(next(gen)), 'big')
dut.data_in_valid.value = 1
val = dut.data_out.value.integer
tb.log.info("Error value: 0x%x", val)
err_cnt += count_set_bits(val)
assert val == 0
await RisingEdge(dut.clk)
dut.data_in_valid.value = 0
tb.log.info("Error count: %d", err_cnt)
assert err_cnt == 0
await tb.reset()
tb.log.info("Single error test")
gen = chunks(ref_prbs(), byte_lanes)
err_cnt = 0
for i in range(64):
val = int.from_bytes(bytes(next(gen)), 'big')
if i == 32:
val = val ^ (1 << (data_width // 2))
dut.data_in.value = val
dut.data_in_valid.value = 1
val = dut.data_out.value.integer
tb.log.info("Error value: 0x%x", val)
err_cnt += count_set_bits(val)
await RisingEdge(dut.clk)
dut.data_in_valid.value = 0
tb.log.info("Error count: %d", err_cnt)
# one bit set per tap
assert err_cnt == 3
if cocotb.SIM_NAME:
if cocotb.top.LFSR_POLY.value == 0x021:
factory = TestFactory(run_test_prbs)
factory.add_option("ref_prbs", [prbs9])
factory.generate_tests()
if cocotb.top.LFSR_POLY.value == 0x10000001:
factory = TestFactory(run_test_prbs)
factory.add_option("ref_prbs", [prbs31])
factory.generate_tests()
# cocotb-test
tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
@pytest.mark.parametrize("style", ["AUTO", "LOOP"])
@pytest.mark.parametrize(("lfsr_width", "lfsr_poly", "lfsr_init", "lfsr_config", "reverse", "invert", "data_width"), [
(9, "9'h021", "9'h1ff", "FIBONACCI", 0, 1, 8),
(9, "9'h021", "9'h1ff", "FIBONACCI", 0, 1, 64),
(31, "31'h10000001", "31'h7fffffff", "FIBONACCI", 0, 1, 8),
(31, "31'h10000001", "31'h7fffffff", "FIBONACCI", 0, 1, 64),
])
def test_lfsr_prbs_check(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, invert, data_width, style):
dut = "lfsr_prbs_check"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
os.path.join(rtl_dir, "lfsr.v"),
]
parameters = {}
parameters['LFSR_WIDTH'] = lfsr_width
parameters['LFSR_POLY'] = lfsr_poly
parameters['LFSR_INIT'] = lfsr_init
parameters['LFSR_CONFIG'] = f'"{lfsr_config}"'
parameters['REVERSE'] = reverse
parameters['INVERT'] = invert
parameters['DATA_WIDTH'] = data_width
parameters['STYLE'] = f'"{style}"'
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)
================================================
FILE: tb/lfsr_prbs_gen/Makefile
================================================
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
TOPLEVEL_LANG = verilog
SIM ?= icarus
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
DUT = lfsr_prbs_gen
TOPLEVEL = $(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../rtl/lfsr.v
# module parameters
export PARAM_LFSR_WIDTH ?= 31
export PARAM_LFSR_POLY ?= "31'h10000001"
export PARAM_LFSR_INIT ?= "31'h7fffffff"
export PARAM_LFSR_CONFIG ?= "\"FIBONACCI\""
export PARAM_REVERSE ?= 0
export PARAM_INVERT ?= 1
export PARAM_DATA_WIDTH ?= 8
export PARAM_STYLE ?= "\"AUTO\""
ifeq ($(SIM), icarus)
PLUSARGS += -fst
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
COMPILE_ARGS += -s iverilog_dump
endif
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst
endif
endif
include $(shell cocotb-config --makefiles)/Makefile.sim
iverilog_dump.v:
echo 'module iverilog_dump();' > $@
echo 'initial begin' >> $@
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
echo 'end' >> $@
echo 'endmodule' >> $@
clean::
@rm -rf iverilog_dump.v
@rm -rf dump.fst $(TOPLEVEL).fst
================================================
FILE: tb/lfsr_prbs_gen/test_lfsr_prbs_gen.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2023 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import itertools
import logging
import os
import pytest
import cocotb_test.simulator
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.regression import TestFactory
class TB:
def __init__(self, dut):
self.dut = dut
self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG)
cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())
dut.enable.setimmediatevalue(0)
async def reset(self):
self.dut.rst.setimmediatevalue(0)
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
self.dut.rst.value = 1
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
self.dut.rst.value = 0
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
def chunks(lst, n, padvalue=None):
return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)
def prbs9(state=0x1ff):
while True:
for i in range(8):
if bool(state & 0x10) ^ bool(state & 0x100):
state = ((state & 0xff) << 1) | 1
else:
state = (state & 0xff) << 1
yield ~state & 0xff
def prbs31(state=0x7fffffff):
while True:
for i in range(8):
if bool(state & 0x08000000) ^ bool(state & 0x40000000):
state = ((state & 0x3fffffff) << 1) | 1
else:
state = (state & 0x3fffffff) << 1
yield ~state & 0xff
async def run_test_prbs(dut, ref_prbs):
data_width = len(dut.data_out)
byte_lanes = data_width // 8
tb = TB(dut)
await tb.reset()
gen = chunks(ref_prbs(), byte_lanes)
dut.enable.value = 1
await RisingEdge(dut.clk)
for i in range(512):
ref = int.from_bytes(bytes(next(gen)), 'big')
val = dut.data_out.value.integer
tb.log.info("PRBS: 0x%x (ref: 0x%x)", val, ref)
assert ref == val
await RisingEdge(dut.clk)
if cocotb.SIM_NAME:
if cocotb.top.LFSR_POLY.value == 0x021:
factory = TestFactory(run_test_prbs)
factory.add_option("ref_prbs", [prbs9])
factory.generate_tests()
if cocotb.top.LFSR_POLY.value == 0x10000001:
factory = TestFactory(run_test_prbs)
factory.add_option("ref_prbs", [prbs31])
factory.generate_tests()
# cocotb-test
tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
@pytest.mark.parametrize("style", ["AUTO", "LOOP"])
@pytest.mark.parametrize(("lfsr_width", "lfsr_poly", "lfsr_init", "lfsr_config", "reverse", "invert", "data_width"), [
(9, "9'h021", "9'h1ff", "FIBONACCI", 0, 1, 8),
(9, "9'h021", "9'h1ff", "FIBONACCI", 0, 1, 64),
(31, "31'h10000001", "31'h7fffffff", "FIBONACCI", 0, 1, 8),
(31, "31'h10000001", "31'h7fffffff", "FIBONACCI", 0, 1, 64),
])
def test_lfsr_prbs_gen(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, invert, data_width, style):
dut = "lfsr_prbs_gen"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
os.path.join(rtl_dir, "lfsr.v"),
]
parameters = {}
parameters['LFSR_WIDTH'] = lfsr_width
parameters['LFSR_POLY'] = lfsr_poly
parameters['LFSR_INIT'] = lfsr_init
parameters['LFSR_CONFIG'] = f'"{lfsr_config}"'
parameters['REVERSE'] = reverse
parameters['INVERT'] = invert
parameters['DATA_WIDTH'] = data_width
parameters['STYLE'] = f'"{style}"'
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)
================================================
FILE: tb/lfsr_scramble/Makefile
================================================
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
TOPLEVEL_LANG = verilog
SIM ?= icarus
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
DUT = lfsr_scramble
TOPLEVEL = $(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../rtl/lfsr.v
# module parameters
export PARAM_LFSR_WIDTH ?= 58
export PARAM_LFSR_POLY ?= "58'h8000000001"
export PARAM_LFSR_INIT ?= "58'h3ffffffffffffff"
export PARAM_LFSR_CONFIG ?= "\"FIBONACCI\""
export PARAM_REVERSE ?= 1
export PARAM_DATA_WIDTH ?= 8
export PARAM_STYLE ?= "\"AUTO\""
ifeq ($(SIM), icarus)
PLUSARGS += -fst
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
COMPILE_ARGS += -s iverilog_dump
endif
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst
endif
endif
include $(shell cocotb-config --makefiles)/Makefile.sim
iverilog_dump.v:
echo 'module iverilog_dump();' > $@
echo 'initial begin' >> $@
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
echo 'end' >> $@
echo 'endmodule' >> $@
clean::
@rm -rf iverilog_dump.v
@rm -rf dump.fst $(TOPLEVEL).fst
================================================
FILE: tb/lfsr_scramble/test_lfsr_scramble.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2023 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import itertools
import logging
import os
import pytest
import cocotb_test.simulator
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.regression import TestFactory
class TB:
def __init__(self, dut):
self.dut = dut
self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG)
cocotb.start_soon(Clock(dut.clk, 10, units="ns").start())
dut.data_in.setimmediatevalue(0)
dut.data_in_valid.setimmediatevalue(0)
async def reset(self):
self.dut.rst.setimmediatevalue(0)
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
self.dut.rst.value = 1
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
self.dut.rst.value = 0
await RisingEdge(self.dut.clk)
await RisingEdge(self.dut.clk)
def chunks(lst, n, padvalue=None):
return itertools.zip_longest(*[iter(lst)]*n, fillvalue=padvalue)
def scramble_64b66b(data, state=0x3ffffffffffffff):
data_out = bytearray()
for d in data:
b = 0
for i in range(8):
if bool(state & (1 << 38)) ^ bool(state & (1 << 57)) ^ bool(d & (1 << i)):
state = ((state & 0x1ffffffffffffff) << 1) | 1
b = b | (1 << i)
else:
state = (state & 0x1ffffffffffffff) << 1
data_out.append(b)
return data_out
async def run_test_scramble(dut, ref_scramble):
data_width = len(dut.data_in)
byte_lanes = data_width // 8
tb = TB(dut)
await tb.reset()
block = bytearray(itertools.islice(itertools.cycle(range(256)), 1024))
scr = scramble_64b66b(block)
scr_iter = iter(chunks(scr, byte_lanes))
first = True
for b in chunks(block, byte_lanes):
dut.data_in.value = int.from_bytes(b, 'little')
dut.data_in_valid.value = 1
await RisingEdge(dut.clk)
val = dut.data_out.value.integer
if not first:
ref = int.from_bytes(bytes(next(scr_iter)), 'little')
tb.log.info("Scrambled: 0x%x (ref: 0x%x)", val, ref)
assert ref == val
first = False
dut.data_in_valid.value = 0
await RisingEdge(dut.clk)
if cocotb.SIM_NAME:
# if cocotb.top.LFSR_POLY.value == 0x8000000001:
if cocotb.top.LFSR_WIDTH == 58:
factory = TestFactory(run_test_scramble)
factory.add_option("ref_scramble", [scramble_64b66b])
factory.generate_tests()
# cocotb-test
tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
@pytest.mark.parametrize("style", ["AUTO", "LOOP"])
@pytest.mark.parametrize(("lfsr_width", "lfsr_poly", "lfsr_init", "lfsr_config", "reverse", "data_width"), [
(58, "58'h8000000001", "58'h3ffffffffffffff", "FIBONACCI", 1, 8),
(58, "58'h8000000001", "58'h3ffffffffffffff", "FIBONACCI", 1, 64),
])
def test_lfsr_scramble(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config, reverse, data_width, style):
dut = "lfsr_scramble"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
os.path.join(rtl_dir, "lfsr.v"),
]
parameters = {}
parameters['LFSR_WIDTH'] = lfsr_width
parameters['LFSR_POLY'] = lfsr_poly
parameters['LFSR_INIT'] = lfsr_init
parameters['LFSR_CONFIG'] = f'"{lfsr_config}"'
parameters['REVERSE'] = reverse
parameters['DATA_WIDTH'] = data_width
parameters['STYLE'] = f'"{style}"'
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)
================================================
FILE: tb/test_lfsr_crc32.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import zlib
module = 'lfsr'
testbench = 'test_%s_crc32' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def bench():
# Parameters
LFSR_WIDTH = 32
LFSR_POLY = 0x4c11db7
LFSR_CONFIG = "GALOIS"
LFSR_FEED_FORWARD = 0
REVERSE = 1
DATA_WIDTH = 8
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
data_in = Signal(intbv(0)[DATA_WIDTH:])
state_in = Signal(intbv(0)[LFSR_WIDTH:])
# Outputs
data_out = Signal(intbv(0)[DATA_WIDTH:])
state_out = Signal(intbv(0)[LFSR_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
data_in=data_in,
state_in=state_in,
data_out=data_out,
state_out=state_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: single word")
current_test.next = 1
state_in.next = 0xffffffff
data_in.next = 0x12
yield clk.posedge
print(hex(~state_out.val))
print(hex(zlib.crc32(b'\x12') & 0xffffffff))
assert ~state_out.val == zlib.crc32(b'\x12') & 0xffffffff
yield delay(100)
yield clk.posedge
print("test 2: block")
current_test.next = 2
block = b'\x11\x22\x33\x44'
state_in.next = 0xffffffff
for b in block:
data_in.next = b
yield clk.posedge
state_in.next = state_out.val
print(hex(~state_out.val))
print(hex(zlib.crc32(block) & 0xffffffff))
assert ~state_out.val == zlib.crc32(block) & 0xffffffff
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_crc32.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr_crc32
*/
module test_lfsr_crc32;
// Parameters
parameter LFSR_WIDTH = 32;
parameter LFSR_POLY = 32'h4c11db7;
parameter LFSR_CONFIG = "GALOIS";
parameter LFSR_FEED_FORWARD = 0;
parameter REVERSE = 1;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [DATA_WIDTH-1:0] data_in = 0;
reg [LFSR_WIDTH-1:0] state_in = 0;
// Outputs
wire [DATA_WIDTH-1:0] data_out = 0;
wire [LFSR_WIDTH-1:0] state_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
data_in,
state_in
);
$to_myhdl(
data_out,
state_out
);
// dump file
$dumpfile("test_lfsr_crc32.lxt");
$dumpvars(0, test_lfsr_crc32);
end
lfsr #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_CONFIG(LFSR_CONFIG),
.LFSR_FEED_FORWARD(LFSR_FEED_FORWARD),
.REVERSE(REVERSE),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.data_in(data_in),
.state_in(state_in),
.data_out(data_out),
.state_out(state_out)
);
endmodule
================================================
FILE: tb/test_lfsr_crc_crc32.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import zlib
module = 'lfsr_crc'
testbench = 'test_%s_crc32' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def bench():
# Parameters
LFSR_WIDTH = 32
LFSR_POLY = 0x04c11db7
LFSR_INIT = 0xffffffff
LFSR_CONFIG = "GALOIS"
REVERSE = 1
INVERT = 1
DATA_WIDTH = 8
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
data_in = Signal(intbv(0)[DATA_WIDTH:])
data_in_valid = Signal(bool(0))
# Outputs
crc_out = Signal(intbv(0)[LFSR_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
data_in=data_in,
data_in_valid=data_in_valid,
crc_out=crc_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
print("mark")
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: single word")
current_test.next = 1
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
data_in.next = 0x12
data_in_valid.next = 1
yield clk.posedge
data_in_valid.next = 0
yield clk.posedge
print(hex(crc_out.val))
print(hex(zlib.crc32(b'\x12') & 0xffffffff))
assert crc_out.val == zlib.crc32(b'\x12') & 0xffffffff
yield delay(100)
yield clk.posedge
print("test 2: block")
current_test.next = 2
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
block = b'\x11\x22\x33\x44'
for b in block:
data_in.next = b
data_in_valid.next = 1
yield clk.posedge
data_in_valid.next = 0
yield clk.posedge
print(hex(crc_out.val))
print(hex(zlib.crc32(block) & 0xffffffff))
assert crc_out.val == zlib.crc32(block) & 0xffffffff
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_crc_crc32.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr_crc
*/
module test_lfsr_crc_crc32;
// Parameters
parameter LFSR_WIDTH = 32;
parameter LFSR_POLY = 32'h04c11db7;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "GALOIS";
parameter REVERSE = 1;
parameter INVERT = 1;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;
// Outputs
wire [LFSR_WIDTH-1:0] crc_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
data_in,
data_in_valid
);
$to_myhdl(
crc_out
);
// dump file
$dumpfile("test_lfsr_crc_crc32.lxt");
$dumpvars(0, test_lfsr_crc_crc32);
end
lfsr_crc #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_INIT(LFSR_INIT),
.LFSR_CONFIG(LFSR_CONFIG),
.REVERSE(REVERSE),
.INVERT(INVERT),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.clk(clk),
.rst(rst),
.data_in(data_in),
.data_in_valid(data_in_valid),
.crc_out(crc_out)
);
endmodule
================================================
FILE: tb/test_lfsr_crc_crc32_64.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import zlib
import struct
module = 'lfsr_crc'
testbench = 'test_%s_crc32_64' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i+n]
def bench():
# Parameters
LFSR_WIDTH = 32
LFSR_POLY = 0x04c11db7
LFSR_INIT = 0xffffffff
LFSR_CONFIG = "GALOIS"
REVERSE = 1
INVERT = 1
DATA_WIDTH = 64
OUTPUT_WIDTH = LFSR_WIDTH
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
data_in = Signal(intbv(0)[DATA_WIDTH:])
data_in_valid = Signal(bool(0))
# Outputs
crc_out = Signal(intbv(0)[OUTPUT_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
data_in=data_in,
data_in_valid=data_in_valid,
crc_out=crc_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: single word")
current_test.next = 1
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
block = bytes(range(8))
data_in.next = struct.unpack('<Q', block)[0]
data_in_valid.next = 1
yield clk.posedge
data_in_valid.next = 0
yield clk.posedge
print(hex(crc_out.val))
print(hex(zlib.crc32(block) & 0xffffffff))
assert crc_out.val == zlib.crc32(block) & 0xffffffff
yield delay(100)
yield clk.posedge
print("test 2: block")
current_test.next = 2
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
block = bytes(range(64))
for b in chunks(block, 8):
data_in.next = struct.unpack('<Q', b)[0]
data_in_valid.next = 1
yield clk.posedge
data_in_valid.next = 0
yield clk.posedge
print(hex(crc_out.val))
print(hex(zlib.crc32(block) & 0xffffffff))
assert crc_out.val == zlib.crc32(block) & 0xffffffff
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_crc_crc32_64.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr_crc
*/
module test_lfsr_crc_crc32_64;
// Parameters
parameter LFSR_WIDTH = 32;
parameter LFSR_POLY = 32'h04c11db7;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "GALOIS";
parameter REVERSE = 1;
parameter INVERT = 1;
parameter DATA_WIDTH = 64;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;
// Outputs
wire [LFSR_WIDTH-1:0] crc_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
data_in,
data_in_valid
);
$to_myhdl(
crc_out
);
// dump file
$dumpfile("test_lfsr_crc_crc32_64.lxt");
$dumpvars(0, test_lfsr_crc_crc32_64);
end
lfsr_crc #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_INIT(LFSR_INIT),
.LFSR_CONFIG(LFSR_CONFIG),
.REVERSE(REVERSE),
.INVERT(INVERT),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.clk(clk),
.rst(rst),
.data_in(data_in),
.data_in_valid(data_in_valid),
.crc_out(crc_out)
);
endmodule
================================================
FILE: tb/test_lfsr_descramble.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import struct
module = 'lfsr_descramble'
testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def scramble_64b66b(data, state=0x3ffffffffffffff):
data_out = bytearray()
for d in data:
b = 0
for i in range(8):
if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):
state = ((state & 0x1ffffffffffffff) << 1) | 1
b = b | (1 << i)
else:
state = (state & 0x1ffffffffffffff) << 1
data_out += bytearray([b])
return data_out
def descramble_64b66b(data, state=0x3ffffffffffffff):
data_out = bytearray()
for d in data:
b = 0
for i in range(8):
if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):
b = b | (1 << i)
state = (state & 0x1ffffffffffffff) << 1 | bool(d & (1 << i))
data_out += bytearray([b])
return data_out
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i+n]
def bench():
# Parameters
LFSR_WIDTH = 58
LFSR_POLY = 0x8000000001
LFSR_INIT = 0x3ffffffffffffff
LFSR_CONFIG = "FIBONACCI"
REVERSE = 1
DATA_WIDTH = 8
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
data_in = Signal(intbv(0)[DATA_WIDTH:])
data_in_valid = Signal(bool(0))
# Outputs
data_out = Signal(intbv(0)[DATA_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
data_in=data_in,
data_in_valid=data_in_valid,
data_out=data_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: block")
current_test.next = 1
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
block = bytes(range(256))
scr = scramble_64b66b(block)
dscr = descramble_64b66b(scr)
for i in range(len(scr)):
data_in.next = scr[i]
data_in_valid.next = 1
yield clk.posedge
if i > 0:
ref = block[i-1]
print(hex(data_out))
print(hex(ref))
assert data_out == ref
i += 1
data_in_valid.next = 0
yield clk.posedge
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_descramble.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr_descramble
*/
module test_lfsr_descramble;
// Parameters
parameter LFSR_WIDTH = 58;
parameter LFSR_POLY = 58'h8000000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 1;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;
// Outputs
wire [DATA_WIDTH-1:0] data_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
data_in,
data_in_valid
);
$to_myhdl(
data_out
);
// dump file
$dumpfile("test_lfsr_descramble.lxt");
$dumpvars(0, test_lfsr_descramble);
end
lfsr_descramble #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_INIT(LFSR_INIT),
.LFSR_CONFIG(LFSR_CONFIG),
.REVERSE(REVERSE),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.clk(clk),
.rst(rst),
.data_in(data_in),
.data_in_valid(data_in_valid),
.data_out(data_out)
);
endmodule
================================================
FILE: tb/test_lfsr_descramble_64.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import struct
module = 'lfsr_descramble'
testbench = 'test_%s_64' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def scramble_64b66b(data, state=0x3ffffffffffffff):
data_out = bytearray()
for d in data:
b = 0
for i in range(8):
if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):
state = ((state & 0x1ffffffffffffff) << 1) | 1
b = b | (1 << i)
else:
state = (state & 0x1ffffffffffffff) << 1
data_out += bytearray([b])
return data_out
def descramble_64b66b(data, state=0x3ffffffffffffff):
data_out = bytearray()
for d in data:
b = 0
for i in range(8):
if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):
b = b | (1 << i)
state = (state & 0x1ffffffffffffff) << 1 | bool(d & (1 << i))
data_out += bytearray([b])
print(hex(d)+" "+hex(b))
print(hex(state))
return data_out
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i+n]
def bench():
# Parameters
LFSR_WIDTH = 58
LFSR_POLY = 0x8000000001
LFSR_INIT = 0x3ffffffffffffff
LFSR_CONFIG = "FIBONACCI"
REVERSE = 1
DATA_WIDTH = 64
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
data_in = Signal(intbv(0)[DATA_WIDTH:])
data_in_valid = Signal(bool(0))
# Outputs
data_out = Signal(intbv(0)[DATA_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
data_in=data_in,
data_in_valid=data_in_valid,
data_out=data_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: block")
current_test.next = 1
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
block = bytes(range(256))
scr = scramble_64b66b(block)
dscr = descramble_64b66b(scr)
for i in range(0, len(scr), 8):
data_in.next = struct.unpack('<Q', scr[i:i+8])[0]
data_in_valid.next = 1
yield clk.posedge
if i > 0:
ref = struct.unpack('<Q', block[i-8:i])[0]
print(hex(data_out))
print(hex(ref))
assert data_out == ref
i += 8
data_in_valid.next = 0
yield clk.posedge
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_descramble_64.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr_descramble
*/
module test_lfsr_descramble_64;
// Parameters
parameter LFSR_WIDTH = 58;
parameter LFSR_POLY = 58'h8000000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 1;
parameter DATA_WIDTH = 64;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;
// Outputs
wire [DATA_WIDTH-1:0] data_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
data_in,
data_in_valid
);
$to_myhdl(
data_out
);
// dump file
$dumpfile("test_lfsr_descramble_64.lxt");
$dumpvars(0, test_lfsr_descramble_64);
end
lfsr_descramble #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_INIT(LFSR_INIT),
.LFSR_CONFIG(LFSR_CONFIG),
.REVERSE(REVERSE),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.clk(clk),
.rst(rst),
.data_in(data_in),
.data_in_valid(data_in_valid),
.data_out(data_out)
);
endmodule
================================================
FILE: tb/test_lfsr_prbs31.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
module = 'lfsr'
testbench = 'test_%s_prbs31' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def prbs31(state = 0x7fffffff):
while True:
for i in range(8):
if bool(state & 0x08000000) ^ bool(state & 0x40000000):
state = ((state & 0x3fffffff) << 1) | 1
else:
state = (state & 0x3fffffff) << 1
yield state & 0xff
def bench():
# Parameters
LFSR_WIDTH = 31
LFSR_POLY = 0x10000001
LFSR_CONFIG = "FIBONACCI"
LFSR_FEED_FORWARD = 0
REVERSE = 0
DATA_WIDTH = 8
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
data_in = Signal(intbv(0)[DATA_WIDTH:])
state_in = Signal(intbv(0)[LFSR_WIDTH:])
# Outputs
data_out = Signal(intbv(0)[DATA_WIDTH:])
state_out = Signal(intbv(0)[LFSR_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
data_in=data_in,
state_in=state_in,
data_out=data_out,
state_out=state_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: test PRBS31")
current_test.next = 1
state_in.next = 0x7fffffff
data_in.next = 0
gen = prbs31()
for i in range(512):
yield clk.posedge
ref = next(gen)
val = data_out.val
print((ref, val))
assert ref == val
state_in.next = state_out.val
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_prbs31.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr
*/
module test_lfsr_prbs31;
// Parameters
parameter LFSR_WIDTH = 31;
parameter LFSR_POLY = 31'h10000001;
parameter LFSR_CONFIG = "FIBONACCI";
parameter LFSR_FEED_FORWARD = 0;
parameter REVERSE = 0;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [DATA_WIDTH-1:0] data_in = 0;
reg [LFSR_WIDTH-1:0] state_in = 0;
// Outputs
wire [DATA_WIDTH-1:0] data_out;
wire [LFSR_WIDTH-1:0] state_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
data_in,
state_in
);
$to_myhdl(
data_out,
state_out
);
// dump file
$dumpfile("test_lfsr_prbs31.lxt");
$dumpvars(0, test_lfsr_prbs31);
end
lfsr #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_CONFIG(LFSR_CONFIG),
.LFSR_FEED_FORWARD(LFSR_FEED_FORWARD),
.REVERSE(REVERSE),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.data_in(data_in),
.state_in(state_in),
.data_out(data_out),
.state_out(state_out)
);
endmodule
================================================
FILE: tb/test_lfsr_prbs9.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
module = 'lfsr'
testbench = 'test_%s_prbs9' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def prbs9(state = 0x1ff):
while True:
for i in range(8):
if bool(state & 0x10) ^ bool(state & 0x100):
state = ((state & 0xff) << 1) | 1
else:
state = (state & 0xff) << 1
yield state & 0xff
def bench():
# Parameters
LFSR_WIDTH = 9
LFSR_POLY = 0x021
LFSR_CONFIG = "FIBONACCI"
LFSR_FEED_FORWARD = 0
REVERSE = 0
DATA_WIDTH = 8
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
data_in = Signal(intbv(0)[DATA_WIDTH:])
state_in = Signal(intbv(0)[LFSR_WIDTH:])
# Outputs
data_out = Signal(intbv(0)[DATA_WIDTH:])
state_out = Signal(intbv(0)[LFSR_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
data_in=data_in,
state_in=state_in,
data_out=data_out,
state_out=state_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: test PRBS9")
current_test.next = 1
state_in.next = 0x1ff
data_in.next = 0
gen = prbs9()
for i in range(512):
yield clk.posedge
ref = next(gen)
val = data_out.val
print((ref, val))
assert ref == val
state_in.next = state_out.val
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_prbs9.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr
*/
module test_lfsr_prbs9;
// Parameters
parameter LFSR_WIDTH = 9;
parameter LFSR_POLY = 9'h021;
parameter LFSR_CONFIG = "FIBONACCI";
parameter LFSR_FEED_FORWARD = 0;
parameter REVERSE = 0;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [DATA_WIDTH-1:0] data_in = 0;
reg [LFSR_WIDTH-1:0] state_in = 0;
// Outputs
wire [DATA_WIDTH-1:0] data_out;
wire [LFSR_WIDTH-1:0] state_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
data_in,
state_in
);
$to_myhdl(
data_out,
state_out
);
// dump file
$dumpfile("test_lfsr_prbs9.lxt");
$dumpvars(0, test_lfsr_prbs9);
end
lfsr #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_CONFIG(LFSR_CONFIG),
.LFSR_FEED_FORWARD(LFSR_FEED_FORWARD),
.REVERSE(REVERSE),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.data_in(data_in),
.state_in(state_in),
.data_out(data_out),
.state_out(state_out)
);
endmodule
================================================
FILE: tb/test_lfsr_prbs_check_prbs31.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
module = 'lfsr_prbs_check'
testbench = 'test_%s_prbs31' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def prbs31(state = 0x7fffffff):
while True:
for i in range(8):
if bool(state & 0x08000000) ^ bool(state & 0x40000000):
state = ((state & 0x3fffffff) << 1) | 1
else:
state = (state & 0x3fffffff) << 1
yield ~state & 0xff
def bench():
# Parameters
LFSR_WIDTH = 9
LFSR_POLY = 0x021
LFSR_INIT = 0x1ff
LFSR_CONFIG = "FIBONACCI"
REVERSE = 0
INVERT = 1
DATA_WIDTH = 8
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
data_in = Signal(intbv(0)[DATA_WIDTH:])
data_in_valid = Signal(bool(0))
# Outputs
data_out = Signal(intbv(0)[DATA_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
data_in=data_in,
data_in_valid=data_in_valid,
data_out=data_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: test PRBS31")
current_test.next = 1
gen = prbs31()
data_in.next = next(gen)
data_in_valid.next = 1
yield clk.posedge
for i in range(512):
data_in.next = next(gen)
data_in_valid.next = 1
val = data_out.val
print(val)
assert val == 0
yield clk.posedge
data_in_valid.next = 0
yield delay(100)
yield clk.posedge
print("test 2: single error")
current_test.next = 2
gen = prbs31()
for i in range(16):
data_in.next = next(gen)
data_in_valid.next = 1
yield clk.posedge
data_in.next = next(gen) ^ 0x08
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x00
data_in.next = next(gen)
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x08
data_in.next = next(gen)
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x00
data_in.next = next(gen)
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x00
data_in.next = next(gen)
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x00
data_in.next = next(gen)
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x90
data_in.next = next(gen)
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x00
yield clk.posedge
data_in_valid.next = 0
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_prbs_check_prbs31.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr_prbs_check
*/
module test_lfsr_prbs_check_prbs31;
// Parameters
parameter LFSR_WIDTH = 31;
parameter LFSR_POLY = 31'h10000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 0;
parameter INVERT = 1;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;
// Outputs
wire [DATA_WIDTH-1:0] data_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
data_in,
data_in_valid
);
$to_myhdl(
data_out
);
// dump file
$dumpfile("test_lfsr_prbs_check_prbs31.lxt");
$dumpvars(0, test_lfsr_prbs_check_prbs31);
end
lfsr_prbs_check #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_INIT(LFSR_INIT),
.LFSR_CONFIG(LFSR_CONFIG),
.REVERSE(REVERSE),
.INVERT(INVERT),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.clk(clk),
.rst(rst),
.data_in(data_in),
.data_in_valid(data_in_valid),
.data_out(data_out)
);
endmodule
================================================
FILE: tb/test_lfsr_prbs_check_prbs31_64.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import struct
module = 'lfsr_prbs_check'
testbench = 'test_%s_prbs31_64' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def prbs31(state = 0x7fffffff):
while True:
for i in range(8):
if bool(state & 0x08000000) ^ bool(state & 0x40000000):
state = ((state & 0x3fffffff) << 1) | 1
else:
state = (state & 0x3fffffff) << 1
yield ~state & 0xff
def bench():
# Parameters
LFSR_WIDTH = 9
LFSR_POLY = 0x021
LFSR_INIT = 0x1ff
LFSR_CONFIG = "FIBONACCI"
REVERSE = 0
INVERT = 1
DATA_WIDTH = 64
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
data_in = Signal(intbv(0)[DATA_WIDTH:])
data_in_valid = Signal(bool(0))
# Outputs
data_out = Signal(intbv(0)[DATA_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
data_in=data_in,
data_in_valid=data_in_valid,
data_out=data_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: test PRBS31")
current_test.next = 1
gen = prbs31()
data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]
data_in_valid.next = 1
yield clk.posedge
for i in range(512):
data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]
data_in_valid.next = 1
val = data_out.val
print(val)
assert val == 0
yield clk.posedge
data_in_valid.next = 0
yield delay(100)
yield clk.posedge
print("test 2: single error")
current_test.next = 2
gen = prbs31()
for i in range(16):
data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]
data_in_valid.next = 1
yield clk.posedge
data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0] ^ 0x0001000000000000
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x0000000000000000
data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x0001000000120000
data_in.next = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x0000000000000000
data_in_valid.next = 0
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_prbs_check_prbs31_64.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr_prbs_check
*/
module test_lfsr_prbs_check_prbs31_64;
// Parameters
parameter LFSR_WIDTH = 31;
parameter LFSR_POLY = 31'h10000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 0;
parameter INVERT = 1;
parameter DATA_WIDTH = 64;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;
// Outputs
wire [DATA_WIDTH-1:0] data_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
data_in,
data_in_valid
);
$to_myhdl(
data_out
);
// dump file
$dumpfile("test_lfsr_prbs_check_prbs31_64.lxt");
$dumpvars(0, test_lfsr_prbs_check_prbs31_64);
end
lfsr_prbs_check #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_INIT(LFSR_INIT),
.LFSR_CONFIG(LFSR_CONFIG),
.REVERSE(REVERSE),
.INVERT(INVERT),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.clk(clk),
.rst(rst),
.data_in(data_in),
.data_in_valid(data_in_valid),
.data_out(data_out)
);
endmodule
================================================
FILE: tb/test_lfsr_prbs_check_prbs9.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
module = 'lfsr_prbs_check'
testbench = 'test_%s_prbs9' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def prbs9(state = 0x1ff):
while True:
for i in range(8):
if bool(state & 0x10) ^ bool(state & 0x100):
state = ((state & 0xff) << 1) | 1
else:
state = (state & 0xff) << 1
yield state & 0xff
def bench():
# Parameters
LFSR_WIDTH = 9
LFSR_POLY = 0x021
LFSR_INIT = 0x1ff
LFSR_CONFIG = "FIBONACCI"
REVERSE = 0
INVERT = 0
DATA_WIDTH = 8
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
data_in = Signal(intbv(0)[DATA_WIDTH:])
data_in_valid = Signal(bool(0))
# Outputs
data_out = Signal(intbv(0)[DATA_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
data_in=data_in,
data_in_valid=data_in_valid,
data_out=data_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: test PRBS9")
current_test.next = 1
gen = prbs9()
data_in.next = next(gen)
data_in_valid.next = 1
yield clk.posedge
for i in range(512):
data_in.next = next(gen)
data_in_valid.next = 1
val = data_out.val
print(val)
assert val == 0
yield clk.posedge
data_in_valid.next = 0
yield delay(100)
yield clk.posedge
print("test 2: single error")
current_test.next = 2
gen = prbs9()
for i in range(16):
data_in.next = next(gen)
data_in_valid.next = 1
yield clk.posedge
data_in.next = next(gen) ^ 0x08
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x00
data_in.next = next(gen)
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x08
data_in.next = next(gen)
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x44
data_in.next = next(gen)
data_in_valid.next = 1
yield clk.posedge
val = data_out.val
print(val)
assert val == 0x00
yield clk.posedge
data_in_valid.next = 0
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_prbs_check_prbs9.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr_prbs_check
*/
module test_lfsr_prbs_check_prbs9;
// Parameters
parameter LFSR_WIDTH = 9;
parameter LFSR_POLY = 9'h021;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 0;
parameter INVERT = 0;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;
// Outputs
wire [DATA_WIDTH-1:0] data_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
data_in,
data_in_valid
);
$to_myhdl(
data_out
);
// dump file
$dumpfile("test_lfsr_prbs_check_prbs9.lxt");
$dumpvars(0, test_lfsr_prbs_check_prbs9);
end
lfsr_prbs_check #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_INIT(LFSR_INIT),
.LFSR_CONFIG(LFSR_CONFIG),
.REVERSE(REVERSE),
.INVERT(INVERT),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.clk(clk),
.rst(rst),
.data_in(data_in),
.data_in_valid(data_in_valid),
.data_out(data_out)
);
endmodule
================================================
FILE: tb/test_lfsr_prbs_gen_prbs31.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
module = 'lfsr_prbs_gen'
testbench = 'test_%s_prbs31' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def prbs31(state = 0x7fffffff):
while True:
for i in range(8):
if bool(state & 0x08000000) ^ bool(state & 0x40000000):
state = ((state & 0x3fffffff) << 1) | 1
else:
state = (state & 0x3fffffff) << 1
yield ~state & 0xff
def bench():
# Parameters
LFSR_WIDTH = 31
LFSR_POLY = 0x10000001
LFSR_INIT = 0x7fffffff
LFSR_CONFIG = "FIBONACCI"
REVERSE = 0
INVERT = 1
DATA_WIDTH = 8
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
enable = Signal(bool(0))
# Outputs
data_out = Signal(intbv(0)[DATA_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
enable=enable,
data_out=data_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: test PRBS31")
current_test.next = 1
gen = prbs31()
enable.next = 1
yield clk.posedge
yield clk.posedge
enable.next = 0
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
enable.next = 1
yield clk.posedge
for i in range(512):
ref = next(gen)
val = data_out.val
print((ref, val))
assert ref == val
yield clk.posedge
enable.next = 0
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_prbs_gen_prbs31.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr_prbs_gen
*/
module test_lfsr_prbs_gen_prbs31;
// Parameters
parameter LFSR_WIDTH = 31;
parameter LFSR_POLY = 31'h10000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 0;
parameter INVERT = 1;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg enable = 0;
// Outputs
wire [DATA_WIDTH-1:0] data_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
enable
);
$to_myhdl(
data_out
);
// dump file
$dumpfile("test_lfsr_prbs_gen_prbs31.lxt");
$dumpvars(0, test_lfsr_prbs_gen_prbs31);
end
lfsr_prbs_gen #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_INIT(LFSR_INIT),
.LFSR_CONFIG(LFSR_CONFIG),
.REVERSE(REVERSE),
.INVERT(INVERT),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.clk(clk),
.rst(rst),
.enable(enable),
.data_out(data_out)
);
endmodule
================================================
FILE: tb/test_lfsr_prbs_gen_prbs31_64.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import struct
module = 'lfsr_prbs_gen'
testbench = 'test_%s_prbs31_64' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def prbs31(state = 0x7fffffff):
while True:
for i in range(8):
if bool(state & 0x08000000) ^ bool(state & 0x40000000):
state = ((state & 0x3fffffff) << 1) | 1
else:
state = (state & 0x3fffffff) << 1
yield ~state & 0xff
def bench():
# Parameters
LFSR_WIDTH = 31
LFSR_POLY = 0x10000001
LFSR_INIT = 0x7fffffff
LFSR_CONFIG = "FIBONACCI"
REVERSE = 0
INVERT = 1
DATA_WIDTH = 64
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
enable = Signal(bool(0))
# Outputs
data_out = Signal(intbv(0)[DATA_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
enable=enable,
data_out=data_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: test PRBS31")
current_test.next = 1
gen = prbs31()
enable.next = 1
yield clk.posedge
yield clk.posedge
enable.next = 0
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
enable.next = 1
yield clk.posedge
for i in range(512):
#ref = next(gen)
ref = struct.unpack('>Q', bytes([x for _, x in zip(range(8), gen)]))[0]
val = data_out.val
print((ref, val))
assert ref == val
yield clk.posedge
enable.next = 0
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_prbs_gen_prbs31_64.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr_prbs_gen
*/
module test_lfsr_prbs_gen_prbs31_64;
// Parameters
parameter LFSR_WIDTH = 31;
parameter LFSR_POLY = 31'h10000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 0;
parameter INVERT = 1;
parameter DATA_WIDTH = 64;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg enable = 0;
// Outputs
wire [DATA_WIDTH-1:0] data_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
enable
);
$to_myhdl(
data_out
);
// dump file
$dumpfile("test_lfsr_prbs_gen_prbs31_64.lxt");
$dumpvars(0, test_lfsr_prbs_gen_prbs31_64);
end
lfsr_prbs_gen #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_INIT(LFSR_INIT),
.LFSR_CONFIG(LFSR_CONFIG),
.REVERSE(REVERSE),
.INVERT(INVERT),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.clk(clk),
.rst(rst),
.enable(enable),
.data_out(data_out)
);
endmodule
================================================
FILE: tb/test_lfsr_prbs_gen_prbs9.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
module = 'lfsr_prbs_gen'
testbench = 'test_%s_prbs9' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def prbs9(state = 0x1ff):
while True:
for i in range(8):
if bool(state & 0x10) ^ bool(state & 0x100):
state = ((state & 0xff) << 1) | 1
else:
state = (state & 0xff) << 1
yield state & 0xff
def bench():
# Parameters
LFSR_WIDTH = 9
LFSR_POLY = 0x021
LFSR_INIT = 0x1ff
LFSR_CONFIG = "FIBONACCI"
REVERSE = 0
INVERT = 0
DATA_WIDTH = 8
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
enable = Signal(bool(0))
# Outputs
data_out = Signal(intbv(0)[DATA_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
enable=enable,
data_out=data_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: test PRBS9")
current_test.next = 1
gen = prbs9()
enable.next = 1
yield clk.posedge
yield clk.posedge
enable.next = 0
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
enable.next = 1
yield clk.posedge
for i in range(512):
ref = next(gen)
val = data_out.val
print((ref, val))
assert ref == val
yield clk.posedge
enable.next = 0
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_prbs_gen_prbs9.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr_prbs_gen
*/
module test_lfsr_prbs_gen_prbs9;
// Parameters
parameter LFSR_WIDTH = 9;
parameter LFSR_POLY = 9'h021;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 0;
parameter INVERT = 0;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg enable = 0;
// Outputs
wire [DATA_WIDTH-1:0] data_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
enable
);
$to_myhdl(
data_out
);
// dump file
$dumpfile("test_lfsr_prbs_gen_prbs9.lxt");
$dumpvars(0, test_lfsr_prbs_gen_prbs9);
end
lfsr_prbs_gen #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_INIT(LFSR_INIT),
.LFSR_CONFIG(LFSR_CONFIG),
.REVERSE(REVERSE),
.INVERT(INVERT),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.clk(clk),
.rst(rst),
.enable(enable),
.data_out(data_out)
);
endmodule
================================================
FILE: tb/test_lfsr_scramble.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import struct
module = 'lfsr_scramble'
testbench = 'test_%s' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def scramble_64b66b(data, state=0x3ffffffffffffff):
data_out = bytearray()
for d in data:
b = 0
for i in range(8):
if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):
state = ((state & 0x1ffffffffffffff) << 1) | 1
b = b | (1 << i)
else:
state = (state & 0x1ffffffffffffff) << 1
data_out += bytearray([b])
return data_out
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i+n]
def bench():
# Parameters
LFSR_WIDTH = 58
LFSR_POLY = 0x8000000001
LFSR_INIT = 0x3ffffffffffffff
LFSR_CONFIG = "FIBONACCI"
REVERSE = 1
DATA_WIDTH = 8
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
data_in = Signal(intbv(0)[DATA_WIDTH:])
data_in_valid = Signal(bool(0))
# Outputs
data_out = Signal(intbv(0)[DATA_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
data_in=data_in,
data_in_valid=data_in_valid,
data_out=data_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: block")
current_test.next = 1
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
block = bytes(range(256))
scr = scramble_64b66b(block)
for i in range(len(block)):
data_in.next = block[i]
data_in_valid.next = 1
yield clk.posedge
if i > 0:
ref = scr[i-1]
print(hex(data_out))
print(hex(ref))
assert data_out == ref
i += 1
data_in_valid.next = 0
yield clk.posedge
yield delay(100)
raise StopSimulation
return instances()
def test_bench():
sim = Simulation(bench())
sim.run()
if __name__ == '__main__':
print("Running test...")
test_bench()
================================================
FILE: tb/test_lfsr_scramble.v
================================================
/*
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`timescale 1ns / 1ps
/*
* Testbench for lfsr_scramble
*/
module test_lfsr_scramble;
// Parameters
parameter LFSR_WIDTH = 58;
parameter LFSR_POLY = 58'h8000000001;
parameter LFSR_INIT = {LFSR_WIDTH{1'b1}};
parameter LFSR_CONFIG = "FIBONACCI";
parameter REVERSE = 1;
parameter DATA_WIDTH = 8;
parameter STYLE = "AUTO";
// Inputs
reg clk = 0;
reg rst = 0;
reg [7:0] current_test = 0;
reg [DATA_WIDTH-1:0] data_in = 0;
reg data_in_valid = 0;
// Outputs
wire [DATA_WIDTH-1:0] data_out;
initial begin
// myhdl integration
$from_myhdl(
clk,
rst,
current_test,
data_in,
data_in_valid
);
$to_myhdl(
data_out
);
// dump file
$dumpfile("test_lfsr_scramble.lxt");
$dumpvars(0, test_lfsr_scramble);
end
lfsr_scramble #(
.LFSR_WIDTH(LFSR_WIDTH),
.LFSR_POLY(LFSR_POLY),
.LFSR_INIT(LFSR_INIT),
.LFSR_CONFIG(LFSR_CONFIG),
.REVERSE(REVERSE),
.DATA_WIDTH(DATA_WIDTH),
.STYLE(STYLE)
)
UUT (
.clk(clk),
.rst(rst),
.data_in(data_in),
.data_in_valid(data_in_valid),
.data_out(data_out)
);
endmodule
================================================
FILE: tb/test_lfsr_scramble_64.py
================================================
#!/usr/bin/env python
"""
Copyright (c) 2016 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
from myhdl import *
import os
import struct
module = 'lfsr_scramble'
testbench = 'test_%s_64' % module
srcs = []
srcs.append("../rtl/%s.v" % module)
srcs.append("../rtl/lfsr.v")
srcs.append("%s.v" % testbench)
src = ' '.join(srcs)
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
def scramble_64b66b(data, state=0x3ffffffffffffff):
data_out = bytearray()
for d in data:
b = 0
for i in range(8):
if bool(state & (1<<38)) ^ bool(state & (1<<57)) ^ bool(d & (1 << i)):
state = ((state & 0x1ffffffffffffff) << 1) | 1
b = b | (1 << i)
else:
state = (state & 0x1ffffffffffffff) << 1
data_out += bytearray([b])
return data_out
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i+n]
def bench():
# Parameters
LFSR_WIDTH = 58
LFSR_POLY = 0x8000000001
LFSR_INIT = 0x3ffffffffffffff
LFSR_CONFIG = "FIBONACCI"
REVERSE = 1
DATA_WIDTH = 64
STYLE = "AUTO"
# Inputs
clk = Signal(bool(0))
rst = Signal(bool(0))
current_test = Signal(intbv(0)[8:])
data_in = Signal(intbv(0)[DATA_WIDTH:])
data_in_valid = Signal(bool(0))
# Outputs
data_out = Signal(intbv(0)[DATA_WIDTH:])
# DUT
if os.system(build_cmd):
raise Exception("Error running build command")
dut = Cosimulation(
"vvp -m myhdl %s.vvp -lxt2" % testbench,
clk=clk,
rst=rst,
current_test=current_test,
data_in=data_in,
data_in_valid=data_in_valid,
data_out=data_out
)
@always(delay(4))
def clkgen():
clk.next = not clk
@instance
def check():
yield delay(100)
yield clk.posedge
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
yield delay(100)
yield clk.posedge
# testbench stimulus
yield clk.posedge
print("test 1: block")
current_test.next = 1
rst.next = 1
yield clk.posedge
rst.next = 0
yield clk.posedge
block = bytes(range(256))
scr = scramble_64b66b(block)
for i in range(0, len(block), 8):
data_in.next = struct.unpack('<Q', block[i:i+8])[0]
data_in_valid.next = 1
yield clk.posedge
if i > 0:
ref = struct.unpack('<Q',
gitextract_d0iwnulu/ ├── .github/ │ └── workflows/ │ └── regression-tests.yml ├── .gitignore ├── AUTHORS ├── COPYING ├── README.md ├── rtl/ │ ├── lfsr.v │ ├── lfsr_crc.v │ ├── lfsr_descramble.v │ ├── lfsr_prbs_check.v │ ├── lfsr_prbs_gen.v │ └── lfsr_scramble.v ├── tb/ │ ├── lfsr/ │ │ ├── Makefile │ │ └── test_lfsr.py │ ├── lfsr_crc/ │ │ ├── Makefile │ │ └── test_lfsr_crc.py │ ├── lfsr_descramble/ │ │ ├── Makefile │ │ └── test_lfsr_descramble.py │ ├── lfsr_prbs_check/ │ │ ├── Makefile │ │ └── test_lfsr_prbs_check.py │ ├── lfsr_prbs_gen/ │ │ ├── Makefile │ │ └── test_lfsr_prbs_gen.py │ ├── lfsr_scramble/ │ │ ├── Makefile │ │ └── test_lfsr_scramble.py │ ├── test_lfsr_crc32.py │ ├── test_lfsr_crc32.v │ ├── test_lfsr_crc_crc32.py │ ├── test_lfsr_crc_crc32.v │ ├── test_lfsr_crc_crc32_64.py │ ├── test_lfsr_crc_crc32_64.v │ ├── test_lfsr_descramble.py │ ├── test_lfsr_descramble.v │ ├── test_lfsr_descramble_64.py │ ├── test_lfsr_descramble_64.v │ ├── test_lfsr_prbs31.py │ ├── test_lfsr_prbs31.v │ ├── test_lfsr_prbs9.py │ ├── test_lfsr_prbs9.v │ ├── test_lfsr_prbs_check_prbs31.py │ ├── test_lfsr_prbs_check_prbs31.v │ ├── test_lfsr_prbs_check_prbs31_64.py │ ├── test_lfsr_prbs_check_prbs31_64.v │ ├── test_lfsr_prbs_check_prbs9.py │ ├── test_lfsr_prbs_check_prbs9.v │ ├── test_lfsr_prbs_gen_prbs31.py │ ├── test_lfsr_prbs_gen_prbs31.v │ ├── test_lfsr_prbs_gen_prbs31_64.py │ ├── test_lfsr_prbs_gen_prbs31_64.v │ ├── test_lfsr_prbs_gen_prbs9.py │ ├── test_lfsr_prbs_gen_prbs9.v │ ├── test_lfsr_scramble.py │ ├── test_lfsr_scramble.v │ ├── test_lfsr_scramble_64.py │ └── test_lfsr_scramble_64.v └── tox.ini
SYMBOL INDEX (99 symbols across 21 files)
FILE: tb/lfsr/test_lfsr.py
class TB (line 39) | class TB:
method __init__ (line 40) | def __init__(self, dut):
function chunks (line 50) | def chunks(lst, n, padvalue=None):
function crc32 (line 54) | def crc32(data):
function crc32c (line 58) | def crc32c(data, crc=0xffffffff, poly=0x82f63b78):
function run_test_crc (line 69) | async def run_test_crc(dut, ref_crc):
function prbs9 (line 114) | def prbs9(state=0x1ff):
function prbs31 (line 124) | def prbs31(state=0x7fffffff):
function run_test_prbs (line 134) | async def run_test_prbs(dut, ref_prbs):
function test_lfsr (line 206) | def test_lfsr(request, lfsr_width, lfsr_poly, lfsr_config, reverse, data...
FILE: tb/lfsr_crc/test_lfsr_crc.py
class TB (line 40) | class TB:
method __init__ (line 41) | def __init__(self, dut):
method reset (line 52) | async def reset(self):
function chunks (line 64) | def chunks(lst, n, padvalue=None):
function crc32 (line 68) | def crc32(data):
function crc32c (line 72) | def crc32c(data, crc=0xffffffff, poly=0x82f63b78):
function run_test_crc (line 83) | async def run_test_crc(dut, ref_crc):
function test_lfsr_crc (line 155) | def test_lfsr_crc(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_config...
FILE: tb/lfsr_descramble/test_lfsr_descramble.py
class TB (line 39) | class TB:
method __init__ (line 40) | def __init__(self, dut):
method reset (line 51) | async def reset(self):
function chunks (line 63) | def chunks(lst, n, padvalue=None):
function scramble_64b66b (line 67) | def scramble_64b66b(data, state=0x3ffffffffffffff):
function descramble_64b66b (line 81) | def descramble_64b66b(data, state=0x3ffffffffffffff):
function run_test_descramble (line 93) | async def run_test_descramble(dut, ref_scramble):
function test_lfsr_descramble (line 154) | def test_lfsr_descramble(request, lfsr_width, lfsr_poly, lfsr_init, lfsr...
FILE: tb/lfsr_prbs_check/test_lfsr_prbs_check.py
class TB (line 39) | class TB:
method __init__ (line 40) | def __init__(self, dut):
method reset (line 51) | async def reset(self):
function chunks (line 63) | def chunks(lst, n, padvalue=None):
function prbs9 (line 67) | def prbs9(state=0x1ff):
function prbs31 (line 77) | def prbs31(state=0x7fffffff):
function count_set_bits (line 87) | def count_set_bits(n):
function run_test_prbs (line 95) | async def run_test_prbs(dut, ref_prbs):
function test_lfsr_prbs_check (line 189) | def test_lfsr_prbs_check(request, lfsr_width, lfsr_poly, lfsr_init, lfsr...
FILE: tb/lfsr_prbs_gen/test_lfsr_prbs_gen.py
class TB (line 39) | class TB:
method __init__ (line 40) | def __init__(self, dut):
method reset (line 50) | async def reset(self):
function chunks (line 62) | def chunks(lst, n, padvalue=None):
function prbs9 (line 66) | def prbs9(state=0x1ff):
function prbs31 (line 76) | def prbs31(state=0x7fffffff):
function run_test_prbs (line 86) | async def run_test_prbs(dut, ref_prbs):
function test_lfsr_prbs_gen (line 137) | def test_lfsr_prbs_gen(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_c...
FILE: tb/lfsr_scramble/test_lfsr_scramble.py
class TB (line 39) | class TB:
method __init__ (line 40) | def __init__(self, dut):
method reset (line 51) | async def reset(self):
function chunks (line 63) | def chunks(lst, n, padvalue=None):
function scramble_64b66b (line 67) | def scramble_64b66b(data, state=0x3ffffffffffffff):
function run_test_scramble (line 81) | async def run_test_scramble(dut, ref_scramble):
function test_lfsr_scramble (line 137) | def test_lfsr_scramble(request, lfsr_width, lfsr_poly, lfsr_init, lfsr_c...
FILE: tb/test_lfsr_crc32.py
function bench (line 42) | def bench():
function test_bench (line 135) | def test_bench():
FILE: tb/test_lfsr_crc_crc32.py
function bench (line 43) | def bench():
function test_bench (line 149) | def test_bench():
FILE: tb/test_lfsr_crc_crc32_64.py
function chunks (line 44) | def chunks(l, n):
function bench (line 49) | def bench():
function test_bench (line 157) | def test_bench():
FILE: tb/test_lfsr_descramble.py
function scramble_64b66b (line 43) | def scramble_64b66b(data, state=0x3ffffffffffffff):
function descramble_64b66b (line 56) | def descramble_64b66b(data, state=0x3ffffffffffffff):
function chunks (line 67) | def chunks(l, n):
function bench (line 72) | def bench():
function test_bench (line 159) | def test_bench():
FILE: tb/test_lfsr_descramble_64.py
function scramble_64b66b (line 43) | def scramble_64b66b(data, state=0x3ffffffffffffff):
function descramble_64b66b (line 56) | def descramble_64b66b(data, state=0x3ffffffffffffff):
function chunks (line 69) | def chunks(l, n):
function bench (line 74) | def bench():
function test_bench (line 161) | def test_bench():
FILE: tb/test_lfsr_prbs31.py
function prbs31 (line 41) | def prbs31(state = 0x7fffffff):
function bench (line 50) | def bench():
function test_bench (line 132) | def test_bench():
FILE: tb/test_lfsr_prbs9.py
function prbs9 (line 41) | def prbs9(state = 0x1ff):
function bench (line 50) | def bench():
function test_bench (line 132) | def test_bench():
FILE: tb/test_lfsr_prbs_check_prbs31.py
function prbs31 (line 42) | def prbs31(state = 0x7fffffff):
function bench (line 51) | def bench():
function test_bench (line 223) | def test_bench():
FILE: tb/test_lfsr_prbs_check_prbs31_64.py
function prbs31 (line 43) | def prbs31(state = 0x7fffffff):
function bench (line 52) | def bench():
function test_bench (line 182) | def test_bench():
FILE: tb/test_lfsr_prbs_check_prbs9.py
function prbs9 (line 42) | def prbs9(state = 0x1ff):
function bench (line 51) | def bench():
function test_bench (line 193) | def test_bench():
FILE: tb/test_lfsr_prbs_gen_prbs31.py
function prbs31 (line 42) | def prbs31(state = 0x7fffffff):
function bench (line 51) | def bench():
function test_bench (line 141) | def test_bench():
FILE: tb/test_lfsr_prbs_gen_prbs31_64.py
function prbs31 (line 43) | def prbs31(state = 0x7fffffff):
function bench (line 52) | def bench():
function test_bench (line 143) | def test_bench():
FILE: tb/test_lfsr_prbs_gen_prbs9.py
function prbs9 (line 42) | def prbs9(state = 0x1ff):
function bench (line 51) | def bench():
function test_bench (line 141) | def test_bench():
FILE: tb/test_lfsr_scramble.py
function scramble_64b66b (line 43) | def scramble_64b66b(data, state=0x3ffffffffffffff):
function chunks (line 56) | def chunks(l, n):
function bench (line 61) | def bench():
function test_bench (line 146) | def test_bench():
FILE: tb/test_lfsr_scramble_64.py
function scramble_64b66b (line 43) | def scramble_64b66b(data, state=0x3ffffffffffffff):
function chunks (line 56) | def chunks(l, n):
function bench (line 61) | def bench():
function test_bench (line 146) | def test_bench():
Condensed preview — 54 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (208K chars).
[
{
"path": ".github/workflows/regression-tests.yml",
"chars": 825,
"preview": "name: Regression Tests\n\non: [push, pull_request]\n\njobs:\n build:\n name: Python ${{ matrix.python-version }} (${{ matr"
},
{
"path": ".gitignore",
"chars": 33,
"preview": "*~\n*.lxt\n*.pyc\n*.vvp\n*.kate-swp\n\n"
},
{
"path": "AUTHORS",
"chars": 40,
"preview": "Alex Forencich <alex@alexforencich.com>\n"
},
{
"path": "COPYING",
"chars": 1057,
"preview": "Copyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this "
},
{
"path": "README.md",
"chars": 2094,
"preview": "# Verilog LFSR Readme\n\n[ 2016-2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
},
{
"path": "rtl/lfsr_crc.v",
"chars": 6390,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/lfsr_descramble.v",
"chars": 6809,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/lfsr_prbs_check.v",
"chars": 6903,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/lfsr_prbs_gen.v",
"chars": 6833,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "rtl/lfsr_scramble.v",
"chars": 6805,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/lfsr/Makefile",
"chars": 2378,
"preview": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# o"
},
{
"path": "tb/lfsr/test_lfsr.py",
"chars": 6687,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/lfsr_crc/Makefile",
"chars": 2448,
"preview": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# o"
},
{
"path": "tb/lfsr_crc/test_lfsr_crc.py",
"chars": 5563,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/lfsr_descramble/Makefile",
"chars": 2443,
"preview": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# o"
},
{
"path": "tb/lfsr_descramble/test_lfsr_descramble.py",
"chars": 5621,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/lfsr_prbs_check/Makefile",
"chars": 2459,
"preview": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# o"
},
{
"path": "tb/lfsr_prbs_check/test_lfsr_prbs_check.py",
"chars": 6102,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/lfsr_prbs_gen/Makefile",
"chars": 2457,
"preview": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# o"
},
{
"path": "tb/lfsr_prbs_gen/test_lfsr_prbs_gen.py",
"chars": 5174,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/lfsr_scramble/Makefile",
"chars": 2441,
"preview": "# Copyright (c) 2023 Alex Forencich\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# o"
},
{
"path": "tb/lfsr_scramble/test_lfsr_scramble.py",
"chars": 5157,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2023 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_crc32.py",
"chars": 3529,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_crc32.v",
"chars": 2238,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_crc_crc32.py",
"chars": 3770,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_crc_crc32.v",
"chars": 2235,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_crc_crc32_64.py",
"chars": 4010,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_crc_crc32_64.v",
"chars": 2245,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_descramble.py",
"chars": 4335,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_descramble.v",
"chars": 2218,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_descramble_64.py",
"chars": 4461,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_descramble_64.v",
"chars": 2228,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_prbs31.py",
"chars": 3417,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_prbs31.v",
"chars": 2235,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_prbs9.py",
"chars": 3374,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_prbs9.v",
"chars": 2225,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_prbs_check_prbs31.py",
"chars": 4960,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_prbs_check_prbs31.v",
"chars": 2280,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_prbs_check_prbs31_64.py",
"chars": 4671,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_prbs_check_prbs31_64.v",
"chars": 2290,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_prbs_check_prbs9.py",
"chars": 4421,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_prbs_check_prbs9.v",
"chars": 2270,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_prbs_gen_prbs31.py",
"chars": 3477,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_prbs_gen_prbs31.v",
"chars": 2168,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_prbs_gen_prbs31_64.py",
"chars": 3580,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_prbs_gen_prbs31_64.v",
"chars": 2178,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_prbs_gen_prbs9.py",
"chars": 3433,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_prbs_gen_prbs9.v",
"chars": 2158,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_scramble.py",
"chars": 3905,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_scramble.v",
"chars": 2208,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tb/test_lfsr_scramble_64.py",
"chars": 3969,
"preview": "#!/usr/bin/env python\n\"\"\"\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "tb/test_lfsr_scramble_64.v",
"chars": 2218,
"preview": "/*\n\nCopyright (c) 2016 Alex Forencich\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "tox.ini",
"chars": 439,
"preview": "# tox configuration\n[tox]\nenvlist = py3\nskipsdist = True\nminversion = 3.2.0\nrequires = virtualenv >= 16.1\n\n[gh-actions]\n"
}
]
About this extraction
This page contains the full source code of the alexforencich/verilog-lfsr GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 54 files (191.6 KB), approximately 55.8k tokens, and a symbol index with 99 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.