System verilog
Demonstrating Constraints
___
By Adhyansh Jaiswal
1. Even Number Generation
class packet;
rand bit [0:5] num; // 6-bit random number
// Constraint to ensure 'num' is an even number
constraint even_number {num % 2 == 0;}
function void display();
$display("num = %0d", num);
endfunction
endclass
module constraint_example;
packet pkt;
initial begin
pkt = new();
repeat(5) begin
[Link](); // Randomize and display the result
[Link]();
end
end
endmodule
2
2. Odd Number Generation
class packet;
rand bit [0:5] num; // 6-bit random number
// Constraint to ensure 'num' is an odd number
constraint odd_number {num % 2 != 0;}
function void display();
$display("\tnum = %0d", num);
endfunction
endclass
module constraint_example;
packet pkt;
initial begin
pkt = new();
$display("**********************");
$display("Odd Number Generation");
repeat(5) begin
[Link](); // Randomize and display the result
[Link]();
end
$display("**********************");
end
endmodule
3
3. Write a constraint where you have a 8 bit value bit [2:0] val
where you’d want to randomize this to where every
randomization would only allow 2 bits to differ from the
previous randomization. Can we solve it by using
$countones(prev_val^cur_val) == 2) This is so because if only
two bits are different in the previous and current value, their
XOR should have only two bits set. Any other logic is welcome.
class packet;
rand bit [2:0] prev_val;
rand bit [2:0] cur_val;
static int count = 0; // Initialize static count to 0
// Constraint to ensure 2 bits differ between prev_val and cur_val after first randomization
constraint check_val {
(count > 0) -> ($countones(prev_val ^ cur_val) == 2);
}
// Function to prepare for randomization
function void pre_randomize();
if(count > 0) begin
prev_val = cur_val; // Update prev_val to the last randomized value of cur_val
end
else begin
count++; // Increment count after the first randomization
end
endfunction
endclass
module constraint_questions;
initial begin
packet pkt = new(); // Create packet object
4
// Repeat randomization 5 times
repeat (5) begin
[Link](); // Randomize packet
$display("***********************");
$display("prev_val = %b", pkt.prev_val); // Display previous value in binary
$display("cur_val = %b", pkt.cur_val); // Display current value in binary
$display("count = %0d diff = %0d", [Link], $countones(pkt.cur_val ^ pkt.prev_val)); // Display
count and differing bits
end
$display("***********************");
end
endmodule
Problem Statement Explanation:
You want to randomize two 3-bit values (prev_val and cur_val), ensuring that after the first
randomization, exactly 2 bits differ between the previous value (prev_val) and the current value
(cur_val).
Key Concepts:
1. XOR Operation (^):
○ The XOR operation between two bits returns 1 if the bits are different and 0 if
they are the same.
5
○ If we XOR prev_val and cur_val, the result will show which bits are different
between the two values.
Example:
prev_val = 3'b110; // 110 in binary
cur_val = 3'b101; // 101 in binary
prev_val ^ cur_val = 3'b011; // XOR result: 011, so bits 0 and 1 differ.
2. Counting Differing Bits ($countones):
○ $countones() is a SystemVerilog built-in function that counts how many 1s are in
a bit-vector.
○ In this case, after XOR-ing prev_val and cur_val, the resulting bit-vector tells us
where the two values differ. The number of 1s in this result represents the number
of differing bits.
Example:
prev_val = 3'b110;
cur_val = 3'b101;
prev_val ^ cur_val = 3'b011; // XOR result: 011
$countones(3'b011) = 2; // There are exactly 2 differing bits
The Code Walkthrough:
1. Class Definition (packet):
○ The class packet has two randomizable 3-bit variables: prev_val and cur_val.
○ It also has a static int count to track how many times randomization has occurred.
This is important because for the first randomization, there's no previous value to
compare with.
2. The Constraint (check_val):
○ The constraint ensures that after the first randomization (when count > 0), the
XOR between prev_val and cur_val has exactly 2 bits that differ:
constraint check_val { (count > 0) -> ($countones(prev_val ^ cur_val) == 2); }
6
○ The count > 0 condition ensures that the constraint is applied only after the first
randomization.
○ $countones(prev_val ^ cur_val) == 2 ensures that exactly 2 bits differ between
prev_val and cur_val.
3. The pre_randomize() Function:
○ This function is called before each randomization to set up prev_val correctly for
comparison.
After the first randomization, the function sets prev_val to the current value cur_val so that the
next randomization can compare the new cur_val against this previous value:
if (count > 0) begin
prev_val = cur_val;
end else begin
count++;
end
In the repeat(5) loop, it randomizes pkt.cur_val and checks how many bits differ between
prev_val and cur_val:
[Link](); // Randomize packet
$display("prev_val = %b", pkt.prev_val); // Display previous value
$display("cur_val = %b", pkt.cur_val); // Display current value
$display("count = %0d diff = %0d", [Link], $countones(pkt.cur_val ^ pkt.prev_val));
○ It prints both prev_val and cur_val in binary format, and also shows how many
bits differ between the two values.
What Happens in Each Randomization:
● First Randomization:
○ Since count = 0, prev_val is not yet defined, so the check_val constraint does not
apply.
7
○ cur_val is randomly generated.
○ After randomization, pre_randomize() will copy cur_val to prev_val and
increment count to 1.
● Subsequent Randomizations:
○ Since count > 0, the constraint (count > 0) -> ($countones(prev_val ^ cur_val) ==
2) kicks in, ensuring that exactly 2 bits differ between prev_val and cur_val.
○ Before each new randomization, the current value cur_val is copied to prev_val so
that it can be compared to the next value generated by randomization.
Example Run:
Let’s say prev_val and cur_val are 3-bit wide (bit [2:0]), and the initial randomization yields:
First randomization:
prev_val = 000 (initial)
cur_val = 110 (randomized)
count = 1, diff = 2
Second randomization:
prev_val = 110 (from previous)
cur_val = 101 (randomized, 2-bit difference from prev_val)
count = 1, diff = 2
Each subsequent randomization will ensure exactly 2 bits differ from the previous value.
Why $countones(prev_val ^ cur_val) == 2 Works:
● The XOR (^) detects differences between the corresponding bits of prev_val and cur_val.
● The $countones() counts how many of these differences exist.
● By setting the constraint to $countones(...) == 2, we enforce the requirement that exactly
2 bits differ.
8
This approach is efficient and logical because it leverages bitwise operations and
SystemVerilog’s built-in $countones() function to solve the problem in a concise manner.
4. Descending order
class packet;
rand bit [0:5] num1;
rand bit [0:5] num2;
rand bit [0:5] num3;
constraint even_number {num1 > num2 > num3 ;}
function void display();
$display("****************************");
$display("num1=%0d num2=%0d num3=%0d",num1,num2,num3);
endfunction
Endclass
module constraint_example;
packet pkt;
initial
begin
$display("****descending order******");
pkt=new();
repeat(5)
begin
[Link]();
[Link]();
end
$display("****************************");
end
endmodule
9