0
\$\begingroup\$

I try to create a CRC module on Verilog.

The CRC calculating use an LFSR and can be fully-sequential (with two cycles), semi-sequential (with one cycle) or parallel. I have already made sequential module. And I try to create a fully-parallel. There is some code-generators for fixed methods (like "CRC-16 modbus" or "CRC-32 Ethernet"). But I want to create an universal parametrizade parallel module.

With for-loop expression I create a prametrized LFSR.

module main 
#(
parameter LFSR_SIZE     = 16,
parameter START_VALUE   = 'hFFFF,
parameter POLYNOME      = 'h8005)
(
input           clk,    
input           n_reset,    
output reg  [LFSR_SIZE-1:0]lfsr);

integer lfsr_index;

always @(posedge clk) begin
    if(n_reset) begin       
        lfsr[0] <= lfsr[LFSR_SIZE - 1];             
        for(lfsr_index = 1; lfsr_index < LFSR_SIZE; lfsr_index = lfsr_index + 1) begin
            if( ((1 << lfsr_index) & POLYNOME) == 0) begin
                lfsr[lfsr_index] <= lfsr[lfsr_index - 1];                   
            end
            else begin
                lfsr[lfsr_index] <= lfsr[lfsr_index - 1] ^ lfsr[LFSR_SIZE - 1];
            end
        end     
    end
    else begin
        lfsr <= START_VALUE;                
    end
end
endmodule

Is it possible to generate number of shifts of the LFSR with a nested loop (two loops, one inside other)? If answer is "no" does the nested loop usefull expression in some case?

\$\endgroup\$
2
  • \$\begingroup\$ What's wrong with simply nesting loops if that's what you want? I've never used Verilog but it works fine in VHDL so it ought to be OK. \$\endgroup\$
    – user16324
    Commented Oct 5, 2020 at 11:25
  • \$\begingroup\$ @Brian Drummond Sorry, I'm not good at terminology. I use the word "folded" instead of "nested". \$\endgroup\$
    – Arseniy
    Commented Oct 5, 2020 at 11:31

1 Answer 1

1
\$\begingroup\$

The essential thing of a for-loop in HDL is the nonblocking assignment. With nonblocking assignments you can direct some wires through the loop and direct other wires around the loop.

data_internal = data_in; 
crc_shift = crc_internal ^ (data_internal << (CRC_SIZE - DATA_SIZE));           
for(int data_index = 0; data_index < DATA_SIZE; data_index++) begin
    msb = crc_shift[CRC_SIZE-1];
    crc_lfsr = (crc_shift << 1);                    
    for(int crc_index = 1; crc_index < CRC_SIZE; crc_index++) begin
        if(((1 << crc_index) & POLYNOME) != 0) begin
            crc_lfsr[crc_index] = crc_lfsr[crc_index] ^ msb;
        end
    end
    crc_lfsr[0] = msb;                  
    crc_shift = crc_lfsr;
end         
crc_internal = crc_shift;
crc_out = crc_shift; 
        

But in you case there is no need to use two cycles. You can replace the inner cycle with the following expression:

crc_lfsr = crc_lfsr ^ ({CRC_SIZE{msb}} & POLYNOME);

Completely it will look like this:

module main 
#(      
parameter IS_CRC_REVERSED   = 1,
parameter IS_DATA_REVERSED  = 1,
parameter DATA_SIZE         = 8,    
parameter CRC_SIZE          = 16,
parameter START_VALUE       = 'hFFFF,
parameter POLYNOME          = 'h8005)
(
input       clk,    
input       n_reset,    
input       [DATA_SIZE-1:0]data_in,
output reg  [CRC_SIZE-1 :0]crc_out);    

reg [CRC_SIZE-1 :0]crc_internal;
reg [DATA_SIZE-1:0]data_internal;
reg msb;
reg [CRC_SIZE-1 :0]crc_shift;
reg [CRC_SIZE-1 :0]crc_lfsr;    

always @(posedge clk) begin
    if(n_reset) begin
        // data reverse
        if(IS_DATA_REVERSED) begin
            for(int i = 0; i < DATA_SIZE; i++) begin
                data_internal[i] = data_in[DATA_SIZE - 1 - i];
            end
        end
        else begin
            data_internal = data_in; 
        end     
        // CRC calculating
        crc_shift = crc_internal ^ (data_internal << (CRC_SIZE - DATA_SIZE));           
        for(int data_index = 0; data_index < DATA_SIZE; data_index++) begin
            msb = crc_shift[CRC_SIZE-1];
            crc_lfsr = (crc_shift << 1);                    
            crc_lfsr = crc_lfsr ^ ({CRC_SIZE{msb}} & POLYNOME);
            crc_lfsr[0] = msb;                  
            crc_shift = crc_lfsr;
        end         
        crc_internal = crc_shift;
        // CRC reverse
        if(IS_CRC_REVERSED) begin
            for(int i = 0; i < CRC_SIZE; i++) begin
                crc_out[i] = crc_shift[CRC_SIZE - 1 - i];
            end
        end
        else begin
            crc_out = crc_shift; 
        end
    end
    else begin
        crc_internal =  START_VALUE;
    end
end
endmodule
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.