Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /////////////////////////////////////////////////////////////////////////////////
- //{{{ BSD 3-Clause License
- // Copyright 2024
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are met:
- //
- // 1. Redistributions of source code must retain the above copyright notice,
- // this list of conditions and the following disclaimer.
- //
- // 2. Redistributions in binary form must reproduce the above copyright notice,
- // this list of conditions and the following disclaimer in the documentation
- // and/or other materials provided with the distribution.
- //
- // 3. Neither the name of the copyright holder nor the names of its
- // contributors may be used to endorse or promote products derived from this
- // software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS ISâ€
- // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- // POSSIBILITY OF SUCH DAMAGE.
- //}}}
- `default_nettype none
- ////////////////////////////////////////////////////////////////////////////////
- // {{{ lfsr_io_check commentary:
- // lfsr sequence checker for IO. This is a fancy version of lfsr_check.
- // this version makes a state vector from the lsb of the input. This means
- // the checker takes pStateWidth inputs to load the state, independent of
- // pBusWidth.
- //
- // this method has the benefit that errors specific to IO are easier to
- // detect. if the lsb of the bus is fine, then this version will be able to
- // check the other bits without those errors affecting the other lines.
- // This method also generates early/late checks for everything but the lsb.
- //
- // The early/late checks can have 1's, but having more than pStateWidth in a row
- // is an error.
- //
- // To be an effective IO checker, pBusWidth should be coprime with
- // (2**pStateWidth - 1). otherwise, some bits will have shorter sequence
- // lengths.
- // }}}
- ////////////////////////////////////////////////////////////////////////////////
- // {{{ Module
- module lfsr_io_check #(
- parameter pStateWidth = 17,
- parameter pBusWidth = 8,
- parameter pSerdes = 1,
- parameter [pStateWidth-1:0] pTaps = 17'b1_0010_0000_0000_0000
- ) (
- output reg [pBusWidth-1:0] oErr,
- output reg [pBusWidth-1:0] oEarly,
- output reg [pBusWidth-1:0] oLate,
- input wire [pSerdes*pBusWidth-1:0] iData,
- input wire iEn,
- input wire clk,
- input wire rst
- );
- //}}}
- ////////////////////////////////////////////////////////////////////////////
- // {{{ re-declare
- localparam S = pStateWidth;
- localparam B = pBusWidth;
- localparam N = pSerdes * pBusWidth;
- localparam T = pTaps;
- //}}}
- ////////////////////////////////////////////////////////////////////////////
- // {{{ matrix solver function
- // early[N-1][S-1:0] .. late[N-1][S-1:0] .. expected[N-1][S-1:0]
- function automatic [(B+B+N)*S-1:0] solver(input unused); begin : decl
- reg [S-1:0] state;
- reg [S-1:0] col;
- reg [N-1:0] late;
- integer i;
- integer j;
- reg [B+B+N+S-1:0] mtx [0:S-1]; // early, late, expected, state
- localparam kState0 = 0;
- localparam kStateEnd = kState0 + S - 1;
- localparam kBus0 = (kStateEnd+1);
- localparam kBusEnd = kBus0 + N - 1;
- localparam kLate0 = kBusEnd + 1;
- localparam kLateEnd = kLate0 + B - 1;
- localparam kEarly0 = kLateEnd + 1;
- localparam kEarlyEnd = kEarly0 + B - 1;
- // initialize serial state
- // V | the right column will be the state for the checker
- // 1 2 3 4 | this first step gets every N'th bit from the lfsr
- // 5 6 7 8 | output.
- // 9 A B C |
- // D E F 1.| col = 4 8 C 1. msb=4, lsb=1
- state = {(S){1'b1}};
- for (i = 0; i < N*S; i = i + 1) begin
- state = (state << 1) ^ (^(state & T));
- if (i % N == N-1) begin
- col = (col << 1) ^ state[0];
- end
- late = (late << 1) ^ state[0];
- end
- // form main matrix:
- // N+S columns
- // N+S-1 S S-1 0
- // first last
- // [outMsb .. outLsb] [stateMsb .. stateLsb]
- // ... S rows ...
- //
- // each row has the outputs to be generated from the state.
- // the next row's state is based on a shift + one of those bits.
- for (j = 0; j < S; j = j + 1) begin
- mtx[j][kStateEnd:kState0] = col;
- for (i = 0; i < N; i = i + 1) begin
- state = (state << 1) ^ (^(state & T));
- mtx[j][kBusEnd-i] = state[0];
- end
- col = (col << 1) ^ mtx[j][S];
- end
- // fill in early/late
- // c d e f g -- early
- // b c d e f -- expected
- // a b c d e -- late
- mtx[0][kLate0+:B] = (pSerdes==1) ? late : mtx[0][kBus0+B+:B];
- mtx[0][kEarly0+:B] = mtx[1][kBusEnd-:B];
- for (i = 1; i < S-1; i = i + 1) begin
- mtx[i][kLate0+:B] = (pSerdes==1) ? mtx[i-1][kBus0+:B] : mtx[i][kBus0+B+:B];
- mtx[i][kEarly0+:B] = mtx[i+1][kBusEnd-:B];
- end
- mtx[S-1][kLate0+:B] = (pSerdes==1) ? mtx[S-1-1][kBus0+:B] : mtx[S-1][kBus0+B+:B];
- for (i = 0; i < B; i = i + 1) begin
- state = (state << 1) ^ (^(state & T));
- mtx[S-1][kEarlyEnd-i] = state[0];
- end
- // triangular
- // [ bits ] [? ? ... ? 1]
- // [ bits ] [? ? ... 1 0]
- // ...
- // [ bits ] [? 1 ... 0 0]
- // [ bits ] [1 0 ... 0 0]
- for (j = 0; j < S; j = j + 1) begin
- if (!mtx[j][j]) begin
- i = j;
- while (i < S && !mtx[i][j]) begin
- i = i + 1;
- end
- mtx[j] = mtx[j] ^ mtx[i];
- end
- for (i = j+1; i < S; i = i + 1) begin
- if (mtx[i][j]) begin
- mtx[i] = mtx[i] ^ mtx[j];
- end
- end
- end
- // diagonal
- // [ out(N-1)tap(0) ... out(0)tap(0)] [0 0 ... 0 1]
- // [ out(N-1)tap(1) ... out(0)tap(1)] [0 0 ... 1 0]
- // ...
- // [ out(N-1)tap(S-2) ... out(0)tap(S-2)] [0 1 ... 0 0]
- // [ out(N-1)tap(S-1) ... out(0)tap(S-1)] [1 0 ... 0 0]
- for (j = S-1; j > 0; j = j - 1) begin
- for (i = 0; i < j; i = i + 1) begin
- if (mtx[i][j]) begin
- mtx[i] = mtx[i] ^ mtx[j];
- end
- end
- end
- // results:
- // {out(N-1)[S-1:0] ... out(0)[S-1:]}
- for (j = 0; j < B+B+N; j = j + 1) begin
- for (i = 0; i < S; i = i + 1) begin
- solver[S*j + i] = mtx[i][kBus0+j];
- end
- end
- end endfunction
- //}}}
- ////////////////////////////////////////////////////////////////////////////
- // {{{ next-value logic
- reg [S-1:0] state;
- reg [N-1:0] error_bits;
- reg [B-1:0] early_match;
- reg [B-1:0] late_match;
- reg [B-1:0] error_lanes;
- integer i;
- localparam [(B+B+N)*S-1:0] kMtx = solver(0);
- localparam kPredict0 = 0;
- localparam kPredictEnd = kPredict0 + N - 1;
- localparam kLate0 = kPredictEnd + 1;
- localparam kLateEnd = kLate0 + B - 1;
- localparam kEarly0 = kLateEnd + 1;
- localparam kEarlyEnd = kEarly0 + B - 1;
- always@(*) begin
- for (i = 0; i < N; i = i + 1) begin
- error_bits[i] = ^(state & kMtx[(kPredict0 + i)*S+:S]) ^ iData[i];
- end
- for (i = 0; i < B; i = i + 1) begin
- early_match[i] = ^(state & kMtx[(kEarly0 + i)*S+:S]) ^ ~iData[i];
- late_match[i] = ^(state & kMtx[(kLate0 + i)*S+:S]) ^ ~iData[i];
- end
- error_lanes = 0;
- for (i = 0; i < pSerdes; i = i + 1) begin
- error_lanes = error_lanes | error_bits[B*i+:B];
- end
- end
- //}}}
- ////////////////////////////////////////////////////////////////////////////
- // {{{ state and output registers
- always@(posedge clk) begin
- if (iEn) begin
- oErr <= error_lanes;
- oEarly <= early_match;
- oLate <= late_match;
- state <= {state[S-2:0], iData[0]};
- end
- if (rst) begin
- state <= 1;
- end
- end
- //}}}
- endmodule
- `default_nettype wire
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement