Help about if statement in constraint block

This is my code.

class packet;
  rand bit       cmd;
  rand bit [7:0] data;
  rand bit [1:0] td;
  rand bit [1:0] addr_inc;
  rand bit [3:0] num_rd;

  constraint solve_td_b4_cmd {
    solve td before cmd;
  }

  constraint solve_addr_inc_b4_cmd {
    solve addr_inc before cmd;
  }

  constraint solve_num_rd_b4_cmd {
    solve num_rd before cmd;
  }

  constraint solve_cmd_b4_data {
    solve cmd before data;
  }

  constraint set_data {
    if (cmd == 1'b0) {
      data == {td, addr_inc, num_rd};
    }
  }
endclass

Now the result is, data is generated randomly without concatenating td, addr_inc, and num_rd.

In reply to Reuben:

Can you explain your requirement? Its not clear on what you are trying to do and what is expected.
Also, “cmd” variable is not declared in your class.

Reuben,

It would help to add code tags to your example - I have done that for you. It would also help to cut and paste your code, or attach it to avoid typos. That would make things clearer.

The problem is you have your solve - before constraint ordering backwards. You want to solve for cmd first. That gives you a 50% chance of cmd==0 instead of (1/(1+2**8))% chance of cmd==0.

You can simplify your solve before constraint with either

solve cmd before td, addr_inc, num_rd;

or just

solve cmd before data;

Hi guys, I forgot some part of my codes so please check my code again. I just added the cmd and the solve cmd before data constraint.

In reply to Naven8:

Hi Naven,

I have 2 commands, Read and Write.
If cmd is 0 then it is Read. If cmd is 1 then it is Write.
If it is Write, then data is just randomized.
If it is Read, then data should concatenate the randomized value of td, addr_inc, and num_rd.

In reply to dave_59:

Hi Dave,

Thanks for the tags.

Regarding the solve cmd before data, I did this. Actually I just forgot to include it in my example.
It still didn’t work. The data is still randomized, not concatenating td, addr_inc, and num_rd.

In reply to Reuben:

You still have the first three b4 constraints backwards. But you can delete them. You only need solve cmd before data;

In reply to Reuben:

When “cmd == 0” data is not getting randomized. data is getting assigned with {td,addr_inc,num_rd};

I got following result when i generated 10 packets randomly.


DISP::: '{cmd:'h1, data:'h71, td:'h1, addr_inc:'h3, num_rd:'h5}
DISP::: '{cmd:'h1, data:'h60, td:'h3, addr_inc:'h0, num_rd:'he}
DISP::: '{cmd:'h0, data:'h81, td:'h2, addr_inc:'h0, num_rd:'h1}
DISP::: '{cmd:'h1, data:'h47, td:'h2, addr_inc:'h2, num_rd:'h1}
DISP::: '{cmd:'h0, data:'hff, td:'h3, addr_inc:'h3, num_rd:'hf}
DISP::: '{cmd:'h1, data:'h3a, td:'h1, addr_inc:'h0, num_rd:'h6}
DISP::: '{cmd:'h0, data:'haa, td:'h2, addr_inc:'h2, num_rd:'ha}
DISP::: '{cmd:'h0, data:'h5e, td:'h1, addr_inc:'h1, num_rd:'he}
DISP::: '{cmd:'h1, data:'h35, td:'h2, addr_inc:'h3, num_rd:'h2}
DISP::: '{cmd:'h1, data:'hba, td:'h1, addr_inc:'h3, num_rd:'h3}

In reply to dave_59:

Hi Dave,

Actually in my first code those were not included. I had only the solve cmd before data but it still didn’t work.
I just tried to add those other solve_b4_constraints just to see if it solves my problem.

In reply to Naven8:

Hi Naven,

It looks it is working on you…
Maybe it is not working for me because I’m using this.pkt.randomize() in another function in another class.

I think it’s better if I’ll just paste all my codes here.

========================================================


`define ADR_SZ  15
`define DAT_SZ  8
`define CRC_SZ  4
`define TD_SZ   2 
`define I_SZ    2
`define NRD_SZ  4

`define AW        8
`define DBGDAT_SZ 28
`define TSTDAT_SZ 28
`define RDBK_SEL_SZ 2
`define LOG_SPACE 32767

class packet extends uvm_sequence_item;
  rand bit               cmd;
  rand bit [`ADR_SZ-1:0] addr;
  rand bit [`DAT_SZ-1:0] data;
       bit [`CRC_SZ-1:0] crc_key;

  rand bit [`TD_SZ-1:0]  td;
  rand bit [`I_SZ-1:0]   addr_inc;
  rand bit [`NRD_SZ-1:0] num_rd; 

  `uvm_object_utils_begin(packet)
     // I removed the part here since it's not related
  `uvm_object_utils_end

  constraint valid_addr {
    addr inside {[15'h0000:15'h6EFF], [15'h7F00:15'h7FFF]};
  }

  constraint solve_td_b4_data {
    solve td before cmd;
  }

  constraint solve_addr_inc_b4_data {
    solve addr_inc before cmd;
  }

  constraint solve_num_rd_b4_data {
    solve num_rd before cmd;
  }

  constraint solve_cmd_b4_data {
    solve cmd before data;
  }
 
  // To be deleted. For testing only
  constraint set_td {
    td == 2'b00;
  }

  // To be deleted. For testing only
  constraint set_addr {
    addr == 15'h4ba8;
  }

  // To be deleted. For tesing only
  constraint set_addr_inc {
    addr_inc == 2'b01;
  }

  constraint valid_num_rd {
    //num_rd != 0;
    num_rd == 4'h3;
  }

  constraint rd_cmd_data {
    if (cmd == 1'b0) {
      data == {td, addr_inc, num_rd};
    }  
  }

  function new(string name = "packet");
    super.new(name);

    `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
  endfunction
endclass

class rd_send_cmd_seq extends pkt_seq_base;
  `uvm_object_utils(rd_send_cmd_seq)

  function new(string name = "rd_send_cmd_seq");
    super.new(name);
    `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
  endfunction

  virtual task body();
    super.body();
    `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);

    // Ready the item
    start_item(pkt);

    // Set the item
    this.pkt.randomize();
    this.pkt.cmd     = 1'b0;
    this.pkt.crc_key = crc({this.pkt.cmd, this.pkt.addr, this.pkt.data},
                         `GEN_POL);

    // Go send the item
    finish_item(pkt);

    // Report the sent item
    `uvm_info($sformatf("rd_send_cmd_seq[%0d]", this.pkt.msg_id),
              {"\n", pkt.sprint()},
              UVM_MEDIUM);
  endtask
endclass

I know this is UVM but I think my problem is about System Verilog.

In reply to Reuben:

  
// Set the item
    this.pkt.randomize();
    this.pkt.cmd     = 1'b0;

With above code I understand you are overriding randmized packet and send the packet as read packing by changing cmd =0.

I believe, here your expectation is to the get pkt where cmd = 0 and data = {td,addr_inc, num_rd}; i.e randomized packet with read attribute if so, please try this one

  
// Set the item
    this.pkt.cmd     = 1'b0;
    this.pkt.cmd.rand_mode(0);
    this.pkt.randomize();

With this, it will always generate the read packet with as per your defined construct.

I am not sure, is this what you expecting here!

In reply to Vinay Jain:

Hi Vinay,

Thanks for the reply.

Anyway, I think I know what causes the problem. When the method this.pkt.randomize() occurs and it generates a cmd with a value of 1’b1, the data did not concatenate and just randomly generated… And then when I override it with this.pkt.cmd = 1’b0, I mistakenly concluded that the actual randomly generated value of cmd is 1’b0.

Anyway, I have already solved the problem. I just added the code below to override data during read operation.


// Set the item
this.pkt.randomize();
this.pkt.cmd     = 1'b0;
this.pkt.data    = {this.pkt.td, this.pkt.addr_inc, this.pkt.num_rd};
this.pkt.crc_key = crc({this.pkt.cmd, this.pkt.addr, this.pkt.data},
                         `GEN_POL);

In reply to Reuben:

Instead of manually updating the packet type you can use inline constraint to generate packet of type “cmd == 1’b0”.


pkt.randomize() with {cmd == 1'b0; crc == {...}};

In reply to Naven8:

Hi Naven,

Thanks. I think that’s a better solution. :)

In reply to Reuben:

Yes Naven,Reuben
What I mention is also same but its good practice to use ‘randomize with’.

Regards,
Vinay

In reply to Vinay Jain:

This is a big debate. Although it may seam easier to use ‘randomize with’, it does not always scale to the ‘OOP’ way of doing things because it becomes difficult to extend procedural code. If you really want packets of a particular cmd, you should extend the packet class with the additional constraints

class packet_cmd0 extends packet;
`uvm_object_utils(packet_cmd0;
constraint cmd0 {cmd == 0;}
endclass

Then create this class instead of the packet class.

In reply to dave_59:

Dave, Can you elaborate a little with an example?

I feel that its very difficult to create a new class for each packet type(by extending base calss).The user might end up in creating thousands of packet class even though they will be used only in 1 or 2 tests.

In reply to Naven8:

You are correct for that situation of only once or twice use. It really depends on how re-usable the code needs to be.