The normal constraints are called hard constraints because it is mandatory for the solver to always satisfy them. If the solver fails to find a solution, then the randomization will fail.

However, a constraint declared as soft gives the solver some flexibility that the constraint need to be satisfied if there are other contradicting constraints - either hard or a soft constraint with higher priority.

Soft constraints are used to specify default valus and distributions for random variables.

Example

Shown in the example below is a soft constraint that tells the solver to produce values within 4 and 12 for the variable called data.


class ABC;
  rand bit [3:0] data;
  
  // This constraint is defined as "soft" 
  constraint c_data { soft data >= 4;
                     data <= 12; }
endclass

module tb;
  ABC abc;
  
  initial begin
    abc = new;
    for (int i = 0; i < 5; i++) begin
      abc.randomize();
      $display ("abc = 0x%0h", abc.data);
    end
  end
endmodule

As expected, values of the randomized variable lies within 4 and 12.

 Simulation Log
ncsim> run
abc = 0x4
abc = 0x8
abc = 0x4
abc = 0x7
abc = 0x7
ncsim: *W,RNQUIE: Simulation is complete.

Let's see how a contradicting inline constraint is handled in this case.


module tb;
  ABC abc;
  
  initial begin
    abc = new;
    for (int i = 0; i < 5; i++) begin
      abc.randomize() with { data == 2; };
      $display ("abc = 0x%0h", abc.data);
    end
  end
endmodule

See that the contradicting inline constraint allowed the solver to constrain value of the variable to 2.

Remember that it is contradicting because the original constraint c_data is supposed to constrain it within 4 and 12, but the inline constraint asks the variable to be set to 2, which is outside the original range.

 Simulation Log
ncsim> run
abc = 0x2
abc = 0x2
abc = 0x2
abc = 0x2
abc = 0x2
ncsim: *W,RNQUIE: Simulation is complete.

How is it different from hard constraints ?

Let us take the class ABC and turn it into a hard constraint by removing the soft keyword and apply a contradicting inline constraint.


class ABC;
  rand bit [3:0] data;

  constraint c_data { data >= 4;
                     data <= 12; }
endclass

module tb;
  ABC abc;
  
  initial begin
    abc = new;
    for (int i = 0; i < 1; i++) begin
      abc.randomize() with { data == 2; };
      $display ("abc = 0x%0h", abc.data);
    end
  end
endmodule

The solver fails in this case because of the contradicting constraint and hence assigns the variable data to 0.

 Simulation Log
ncsim> run
      abc.randomize() with { data == 2; };
                  |
ncsim: *W,SVRNDF (./testbench.sv,14|18): The randomize method call failed. The unique id of the failed randomize call is 4.
Observed simulation time : 0 FS + 0
ncsim: *W,RNDOCS: These constraints contribute to the set of conflicting constraints:

  constraint c_data { data >= 4; (./testbench.sv,4)
      abc.randomize() with { data == 2; }; (./testbench.sv,14)
ncsim: *W,RNDOCS: These variables contribute to the set of conflicting constraints:

rand variables:
       data [./testbench.sv, 2]

abc = 0x0
ncsim: *W,RNQUIE: Simulation is complete.