CRC generator

Hi,

I’m trying to make a single task for CRC generator for CRC_15, CRC_17 & CRC_21. Following is the code:

  function crc_size crc_calc(crc_size crc ,bit data, int crc_bits, int crc_polynomial);
      bit crc_nxt=0;
      crc_calc = new [crc_bits+1];
      crc_nxt = data ^ crc[crc_bits];
      crc[crc_bits:1] = crc[crc_bits-1:0];
      crc[0] = 0;
      if(crc_nxt)begin
         crc[crc_bits:0]=crc ^ crc_polynomial;
      end
      return crc;
   endfunction

Where crc_size is defined as follows:

typedef bit crc_size[];

crc_bits & crc_polynomial are defined in a task as follows:

      int crc_bits;
      int crc_polynomial;

The values of crc_bits (i.e.,14,16,20) and crc_polynomial are assigned according to modes in the task and then is passed in the above function.

I’m getting the following error:
** Error: ** while parsing file included at : Range must be bounded by constant expressions.

Please help in this regards!!

crc__bits is a variable… therefore its value is not known till runtime.

However for the part select operation in Verilog the ranges should be
statically determinable at compile time. Hence crc[crc_bits:1] is not
legal.

In reply to logie:

But you can specify crc_bits as a parameter. Then it’s fine.

In reply to chr_sue:

Yes. That is correct, because parameters are resolved at elaboration time.

In reply to chr_sue:

Taking it as a parameter is fine but the value of crc_bits is dependent on the sequence_item. So if in a single testcase I want to send different data length formats which uses their respective CRCs then I won’t be able to change the crc_bits again and again.

crc_bits calculation is done something like this as follows:

crc_bits = (req.mode==1) ? ((req.data_length <= 16) ? 17 : 21):15;

And CRC polynomial is based on the crc_bits. After this assignment I’m passing these two values as argument to the CRC generator function

In reply to dpanda:

How does your crc gen behave when paasing the biggest value to it?

In reply to chr_sue:

I’m getting compilation error for the above codes. If talked about the biggest value then theoretically it’ll be CRC 21 generator. Following is it’s code:

CRC_RG = 0; // initialize shift register
REPEAT
CRCNXT = NXTBIT EXOR CRC_RG(20);
CRC_RG(20:1) = CRC_RG(19:0); // shift left by 1 position
CRC_RG(0) = 0;
IF CRCNXT THEN

CRC_RG(20:0) = CRC_RG(20:0) EXOR (302899hex); ENDIF
UNTIL (CRC SEQUENCE starts or there is an ERROR condition)

In reply to dpanda:

Could you please post the compilation error.

I first thought of using part-select but since width is variable, we can not use it. but since width is variable and only 3 possible combinations are there, why don’t you write case statement?

In reply to chr_sue:

I’ve mentioned it previously. Posting the same for your reference again:

** Error: ** while parsing file included at : Range must be bounded by constant expressions.

In reply to juhi_p:

Thanks Juhi for your reply. But as my present method isn’t working properly I’ve implemented the same concept using case statement itself.

I just want to optimize my code as case statement would just lengthen it more and I’ll have to make three functions for the same functionality.

Please do help in implementing this concept of using the same function for three different scenarios.

In reply to dpanda:

You can solve your problem by uasing a variable. But this variable nas to be initialized, best at declaration or using a default value in your task definition.
Afterwards you can update/modify this variable.

In reply to chr_sue:

I tried the way mentioned by you but still the same issue persists.

In reply to dpanda:

What did you really do? Did you set a default value on the corresponding task input?

In reply to chr_sue:

I’ve assigned a default value to the variable while declaring it. And still giving the crc_bits as input to it.

In reply to dpanda:

Looks like you are doing something wrong.
Please see my example here:

//=============================================================================
// Sequence    : example_top_default_seq
// Author      : <author>    Tel: <phone>   Email: <email>
// Using       : <list of sub-sequences used by this sequences>
// Description : Sequence generating 1 item;
//=============================================================================
class example_top_default_seq extends example_top_base_seq;


  `uvm_object_utils(example_top_default_seq)

  // UVC sequences
  apb_default_seq	apb_seq;
  spi_default_seq	spi_seq;

  int loop_no = 10;

  extern function new(string name = "example_top_default_seq");
  extern task body();
  extern task run_seq(input int noofloops = loop_no);

endclass : example_top_default_seq

//-----------------------------------------------------------------------------
// example_top_default_seq implementation
//-----------------------------------------------------------------------------

function example_top_default_seq::new(string name = "example_top_default_seq");
   super.new(name);
endfunction : new

task example_top_default_seq::run_seq(input int noofloops = loop_no);

  repeat(noofloops) begin
  `uvm_info(get_type_name(),"apb sequence starting", UVM_MEDIUM)
  `uvm_info(get_type_name(),$sformatf("loop_no = %0d", loop_no), UVM_MEDIUM)

  void'(apb_seq.randomize());
    apb_seq.start(apb_sequencer_i);
  `uvm_info(get_type_name(),"spi sequence starting", UVM_MEDIUM)

  void'(spi_seq.randomize());
    spi_seq.start(spi_sequencer_i);
  end

  `uvm_info(get_type_name(),"setting new loop_no", UVM_MEDIUM)

endtask

task example_top_default_seq::body();
  super.body();

  apb_seq = apb_default_seq::type_id::create("apb_seq");
  spi_seq = spi_default_seq::type_id::create("spi_seq");

  `uvm_info(get_type_name(),"default sequence starting", UVM_MEDIUM)

  run_seq(loop_no);

  loop_no = 5;

  run_seq(loop_no);

  `uvm_info(get_type_name(),"default sequence completed",UVM_MEDIUM)
endtask : body

In reply to chr_sue:

What is the intention of this typedef:
typedef bit crc_size;

We no 2 different typedefs.
The forward typedef for classes, like this typedef class C;
and the typedef to define a user-defined type like this

typedef logic [7:0] [3:0] T;
Here T is like an abbreviation with the following decalartion

T var;
mean this is a 2-dim variable var.

In reply to chr_sue:



Please check the following code:

class driver extends uvm_driver #(sequence_item);
   `uvm_component_utils_begin(driver)
   `uvm_component_utils_end
      
   uvm_analysis_port #(sequence_item)drv2scb_port;
   sequence_item seq_item;
   

   virtual interface interface vif;
   
   
   agent agent_ptr;
      
   int bit_q_size;
   typedef bit crc_size[];                       //Debug purpose for CRC
   
   
   function new(string name,uvm_component parent);
      super.new(name,parent);
   endfunction
   
   function void build();
      super.build();
      drv2scb_port=new("drv2scb_port",this);
   endfunction

// START_ENCRYPTION
      task run();
         //body
      endtask
  
   rand bit eof_bit;
   task frame(sequence_item obj);
      byte crc_data;
      int crc_bits = 14;
      int crc_polynomial;
      
      bit crc_reg[];          //Debug purpose for CRC
      bit crc_reg_cur[];      //Debug purpose for CRC
      obj.bit_q={};
      //body to send different frames
      
       crc_bits = 14;             // Need to update condition for 3 different scenarios
        crc_polynomial = 'h4599; // Need to update condition for 3 different scenarios
        
        for(int i=0; i<obj.bit_q.size;i++) begin
         for(int i=0;i<obj.bit_q.size;i++)begin
            crc_reg = new[crc_bits+1]; 
            crc_reg_cur = new[crc_bits+1]; 
      	    crc_reg = crc_calc(crc_reg_cur , obj.bit_q[i],crc_bits,crc_polynomial); 			 
            crc_reg_cur = crc_reg;
         end
         
   endtask :create_frame
///////////////////////////////////////////////////////////////////////////////
// crc calculation using frames sof -> data(if present) (else) controlled field 
///////////////////////////////////////////////////////////////////////////////

/*   function bit [14:0] crc_calc(bit [14:0]crc ,bit data); //Initial CRC calculation
      bit crc_nxt=0;
      crc_nxt = data ^ crc[14];
      crc[14:1] = crc[13:0];
      crc[0] = 0;
      if(crc_nxt)begin
         crc[14:0]=crc ^ 'h4599;
      end
      return crc;
   endfunction */

    //CRC calculation function updated by me
   function crc_size crc_calc(crc_size crc ,bit data, int crc_bits, int crc_polynomial); 
      bit crc_nxt=0;
      crc_calc = new [crc_bits+1];
      crc_nxt = data ^ crc[crc_bits];
      crc[crc_bits:1] = crc[crc_bits-1:0];
      crc[0] = 0;
      if(crc_nxt)begin
         crc[crc_bits:0]=crc ^ crc_polynomial;
      end
      return crc;
   endfunction

endclass


In reply to dpanda:

You did not set a default value for crc_bits.
It has to be

function crc_size crc_calc(crc_size crc ,bit data, int crc_bits = 7, int crc_polynomial);

Now crc_bits has a fixed value at elaboration, but it can be overridden by any other value later on. The default value can be any other number.

In reply to chr_sue:

I tried this way but still the same error persists