`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: BITSILICA PRIVATE LIMITED // Design Name: ENCODER CRC ATTACHMENT // Module Name: encoder_crc_attachment_rtl // Project Name: POLAR ENCODER-DECODER // Target Devices: Zynq UltraScale+ ZCU111 Evaluation Platform (xczu28dr-ffvg1517-2-e) // Tool Versions: VIVADO 2020.1 // Description: RTL code for calculation and attachment of CRC to a given message, according to selected polynomial. // //~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~// // If the CRC width i.e., P = X, // // it means that we are going to use a X degree polynomial of length X+1 bits, // // the crc_out is of X bits. // // CRC POLYNOMIALS used in Polar IP // // CRC6 =0x21 == 010_0001 // // CRC11 =0x621 == 0110_0010_0001 // // CRC16 =0x1021 == 0_0001_0000_0010_0001 // // CRC24C =0xB2B117 == 0_1011_0010_1011_0001_0001_0111 // //~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~^~~~~~// // // encoder_crc_attachment_rtl is written to calculate and attach CRC for a given message input. // ////////////////////////////////////////////////////////////////////////////////// module encoder_crc_attachment_rtl #( parameter PUCCH = 0, // Uplink Channel enable parameter PBCH = 0, // Broadcast Channel enable parameter N = 512, parameter A = 140, // Message width A if no segmentation needed, A'=A/2 if segmentation is needed. parameter P=24, parameter K = A+P // Message width after CRC is appended ) ( input wire clock_i, // System clock input wire reset_ni, // System reset,active low synchronous input wire [A-1:0] msg_i, // Input message bits output reg [K-1:0] msg_o // total message = message input + CRC bits ); integer i; // looping variable wire [P:0] polynomial; // polynomial using which CRC needs to be calculated reg [K-1:0] polynomial_1='d0; // polynomial_1 is to store the right shifted polynomial in each step reg [K-1:0] msg_1='d0; // msg_1 is to hold the modified message in between the XOR operations reg [P-1:0] crc_out='d0; // Calculated CRC output for given msg_i reg [K-1:0] msg_2; // msg_2 is to hold the output msg after msg_i is appended with crc_out generate if (P == 'd6) //CRC-6 assign polynomial = 'h21; else if (P == 'd11) //CRC-11 assign polynomial = 'h621; else if (P == 'd24) //CRC-24C assign polynomial = 'h1d11a9b; else //CRC-16 assign polynomial = 'h1021; endgenerate // Procedural block to calculate CRC for input message bits. always@(*) begin polynomial_1 = { {(A-1){1'b0}}, polynomial[P:0] }; // initialization of polynomial_1 msg_1 = { {P{1'b0}}, msg_i[A-1:0] }; // initialization of msg_1 for (i = 0; i < A; i = i+1) begin // calculating CRC and storing in temporary internal register(A number of times) msg_1 = ( msg_1[i] )? ( msg_1 ^ polynomial_1 ) : ( msg_1 ^ {K{1'b0}} ); // exor with polynomial if message bit is 1, else exor with 0's. polynomial_1 = polynomial_1 << 1'b1; // left shifting the polynomial for each message bit end crc_out = msg_1[K-1 : A]; // assigning the internal register to CRC output msg_2 = { crc_out[P-1 : 0], msg_i[A-1 : 0] }; // the final message output end // instantiating a register(group of FF's) to hold the output and synchronize the module w.r.t clock and reset signals register #( .WIDTH(K), // overriding the width of register with the length of output to be registered .SR(2'b01), // overriding SR inputs of the register .RST_VAL({N{1'b0}}) // overriding the reset value with expected value in the output when reset is applied ) REG ( .clk(clock_i), // connecting clock ports .rstb(reset_ni), // connecting reset ports .din(msg_2), // connecting input of register with the value that needs to be registered .dout(msg_o) // connecting the registered output with the output port of current module ); endmodule