I am trying to write a cover point to check where 2 signals should occurring at the same time or not.
covergroup signal#(posedge clk)
signals : coverpoint (a, b){
bins on_off = {2'b11}
}
I just wanted to know whether it is the correct path of writing the cover point.
I think you meant to write coverpoint {a,b} using concatenation braces. That would work. Another thing you can do is
covergroup signal #(posedge clk);
signals : coverpoint a&b {
bins on = {1};
}
endgroup
Related
Hi I am new to stackoverflow and systemverilog/uvm. I am currently trying to get the a cross coverpoint to catch the condition that (a==b) && (c==d), regardless of what value they are. I have tried the following crosses and none of them seem to be working.
covergroup abcd_tracking with function sample (bit [7:0] a, bit [7:0] b, bit [7:0] c, bit [7:0] d);
coverpoint a {
bins a_bin[1] = {[0:$]};
}
coverpoint b {
bins b_bin[1] = {[0:$]};
}
coverpoint c {
bins c_bin[1] = {[0:$]};
}
coverpoint d {
bins d_bin[1] = {[0:$]};
abcd_cross : cross a,b,c,d
{
bins abcd_bin = abcd_cross with( (a==b) && (c==d) );
}
abcd_cross_2 : cross a,b,c,d
{
bins abcd_2_bin = ( binsof(a) intersect(b) && binsof(c) intersect(d) );
}
abcd_cross_3 : cross a,b,c,d
{
bins abcd_3_bin = ( binsof(a) intersect{[0:$]} with (a==b) && binsof(c) intersect{[0:$]} with (c==d) );
}
This should actually be an illegal condition that never gets hit, but the 3 cross coverpoints seem to be constantly getting hit even though checking with my log files, the sampled variables don't meet the condition I am trying to define in my cross coverpoint. What is the proper syntax for catching this particular condition: " (a==b) && (c==d) " ?
You have a number of syntax errors, but event beyond that, I think you have some misconceptions on how coverpoints and crosses work.
Your four coverpoints have only one bin for all possible values. That means each bin gets hit on the first sample with any value, which is 100% coverage for each of the four coverpoints on the first sample. And since a cross creates bins for all possible bin combinations, you only get one cross bin on the first sample. So each of the three crosses are covered on the first sample.
If you want a separate bin for each value of a coverpoint, you need to write
coverpoint a {
bins a_bin[256] = {[0:$]};
}
Now a simple cross of a,b,c,d would create 256*256*257*256 = 232 cross bins. Bins of a cross are automatically generated and you only specify bins if you want them merged or ignored. If are only interested in the cases where (a==b) && (c==d), you have ignore all the other bins with
abcd: cross a,b,c,d {
ignore_bins not_equal = abcd with( a!=b || c!=d);
}
I'm creating coverage for my design and I want to reuse a covergroup definition for multiple instances. The first instance should use all of the coverpoints as intended, but for the second instance, I want to exclude some of the coverpoints in the covergroup.
I was thinking I could use an input to the covergroup and iff () the unwanted coverpoints such that the first instance ties the input to 1 and the second instance ties the input to 0. However I think this will still show the coverpoints for the second instance as always not hit, and I want them to not be included at all.
covergroup cg_address(input bit enable) # (posedge clock);
address_check: coverpoint (address){
bins addr_0 = {5'd0};
bins addr_1 = {5'd1};
}
data_check: coverpoint (data) iff (enable){
bins data_0 = {10'd0};
bins data_1 = {10'd1};
}
endgroup : cg_address
cg_address cg_address_inst0 = new(1'b1);
cg_address cg_address_inst1 = new(1'b0); //want this one to exclude data_check coverpoint
I know the above code won't work because the second instance will still have the data_check coverpoint, it will just never hit either bin because the enable is tied to 0. Is there any other way I can try to exclude the data_check coverpoint for the second instance?
You need to do two things:
Set the weight of the coverpoint to 0.
Turn on option.per_instance = 1; for the covergroup.
For example:
covergroup cg_address(input bit enable) # (posedge clock);
option.per_instance = 1;
address_check: coverpoint (address){
bins addr_0 = {5'd0};
bins addr_1 = {5'd1};
}
data_check: coverpoint (data) {
option.weight = enable;
bins data_0 = {10'd0};
bins data_1 = {10'd1};
}
endgroup : cg_address
cg_address cg_address_inst0 = new(1);
cg_address cg_address_inst1 = new(0); //want this one to exclude data_check coverpoint
Let's say I have an array of parameters I want to use in a covergroup.
In order to interate over all the parameters in the array I tried to use a for loop in this manner:
array [5];
covergroup param;
coefficient: coverpoint array[i]{
bin low = {0:50};
bins high = {51:100};
}
for (i=0;i<5;i++)
param = new(i);
for (i=0;i<5;i++)
param.sample(i);
I'm not really sure how to solve this rather than creating a coverpoint for every cell in the array, but that's just messy and wrong.
Pass the input argument to the covergroup.
int array [5];
covergroup param (ref int a);
coefficient: coverpoint a{
bin low = {0:50};
bins high = {51:100};
}
endgroup
for (i=0;i<5;i++)
param = new(array[i]);
for (i=0;i<5;i++)
param.sample();
I am trying to create a bin in my coverage group to sample values that are multiple of n (where n is a constant integer in my case 15). So far, I have came
up with the following code:
class rx_port;
int unsigned rx_rates[];
...
covergroup rx_cov with function sample (int unsigned rate);
coverpoint rate{
bins no_rate = {0};
bins mul_of_15 = {SOME_PRE_DEFINED_PATTERN};
}
endgroup;
....
endclass
Where SOME_PRE_DEFINED_PATTERN is an array of int from 0 to a system macro with the step of 15. I am not sure if this is the correct/best way of generating this bin. Any better suggestion?
How about writing some helper functions:
module FIFTEEN;
class rx_port;
typedef enum {IS_ZERO, IS_DIVISIBLE_BY_15, IS_NOT_DIVISIBLE_BY_15} rate_type;
function new;
rx_cov=new;
endfunction
local function rate_type covergroup_helper(input int unsigned i);
if (i==0) return IS_ZERO;
if (i%15==0) return IS_DIVISIBLE_BY_15;
return IS_NOT_DIVISIBLE_BY_15;
endfunction
function sample (input int unsigned i);
rx_cov.sample(covergroup_helper(i));
endfunction
covergroup rx_cov with function sample (rate_type rate);
coverpoint rate;
endgroup;
endclass
rx_port R = new;
initial
begin
void'(R.sample(0));
void'(R.sample(30));
void'(R.sample(31));
$display("coverage R.rx_cov.get_coverage= %f", R.rx_cov.get_coverage);
end
endmodule
https://www.edaplayground.com/x/65v7
Here I've written a function that determines whether its input is divisible by 15 or not and another function which calls that to do the sampling. You could combine those functions together, but I like the division of labour in my example.
It turns out that there is a better way:
module FIFTEEN;
class rx_port;
function new;
rx_cov=new;
endfunction
function sample (input int unsigned i);
rx_cov.sample(i);
endfunction
covergroup rx_cov with function sample (int unsigned rate);
coverpoint rate {
bins IS_ZERO = {0};
bins IS_DIVISIBLE_BY_15 = {[1:$]} with ((item % 15)==0);
bins IS_NOT_DIVISIBLE_BY_15 = {[1:$]} with ((item % 15)!=0);
}
endgroup;
endclass
rx_port R = new;
initial
begin
void'(R.sample(0));
void'(R.sample(30));
void'(R.sample(31));
$display("coverage R.rx_cov.get_coverage= %f", R.rx_cov.get_coverage);
end
endmodule
https://www.edaplayground.com/x/3T5v
You can use with to specify bins. So
bins IS_DIVISIBLE_BY_15 = {[1:$]} with ((item % 15)==0);
gives you a bin that is hit whenever the value is divisible by 15 (but not 0) and
bins IS_NOT_DIVISIBLE_BY_15 = {[1:$]} with ((item % 15)!=0);
gives you a bin that is hit whenever the value is not divisible by 15.
I found a very strange behaviour when design my ALU, hope someone can have a look it and tell me what is going on.
Here is the code
module adder (
output logic signed[31:0] y,
output logic Cout,
input logic signed[31:0] a, b,
input logic Cin, sub
);
logic [31:0] adder_b;
assign adder_b = b ^ {32{sub}};
assign {Cout, y} = {a[31],a} + {adder_b[31],adder_b} +Cin;
endmodule
////////////////////////////////////////////////////
////////////////////////////////////////////////////
////////////////////////////////////////////////////
module andlogic (
output logic [31:0] y,
input logic [31:0] a, b
);
assign y = a & b;
endmodule
////////////////////////////////////////////////////
////////////////////////////////////////////////////
////////////////////////////////////////////////////
module orlogic (
output logic [31:0] y,
input logic [31:0] a, b
);
assign y = a | b;
endmodule
////////////////////////////////////////////////////
////////////////////////////////////////////////////
////////////////////////////////////////////////////
module xorlogic (
output logic [31:0] y,
input logic [31:0] a, b
);
assign y = a ^ b;
endmodule
///////////////////////////////////////////////////
///////////////////////////////////////////////////
///////////////////////////////////////////////////
module ALU(
output logic signed[31:0] Result,
output logic N,Z,C,V,
input logic signed[31:0] a, b,
input logic [2:0] ALU_control
);
wire [31:0] adder_rlt, and_rlt, or_rlt, xor_rlt;
logic Cin;
adder adder (
.y (adder_rlt),
.a (a),
.b (b),
.Cin (Cin),
.Cout (Cout),
.sub (sub)
);
andlogic andlogic (
.y (and_rlt),
.a (a),
.b (b)
);
orlogic orlogic (
.y (or_rlt),
.a (a),
.b (b)
);
xorlogic xorlogic (
.y (xor_rlt),
.a (a),
.b (b)
);
assign C = Cout;
assign sub = ALU_control[1];
assign Cin = ALU_control[1];
assign N = Result[31];
//assign Z = (Result ==0 )? 1:0;
assign V = {{~a[31]} & {~b[31]} & Result[31]}|{a[31] & b[31] & {~Result[31]}};
always_comb
begin
if (Result == 0) Z = 1;
else Z = 0;
case(ALU_control)
3'b001: Result = adder_rlt;
3'b010: Result = adder_rlt;
3'b011: Result = and_rlt;
3'b100: Result = or_rlt;
3'b101: Result = xor_rlt;
default: Result = 0;
endcase
end
endmodule
The first 4 modules are individual functions of my ALU, the adder contains both addition and subtraction. Then here is the odd thing:
My ALU has 4 flags, Z represent Zero, it sets when the value of output Result is 0. If I use these code to describe the behaviour of Z
always_comb
begin
if (Result == 0) Z = 1;
else Z = 0;
The simulation result is wrong, Z some time is 1, and some time is 0, and it looks like not depend on the value of Result at all.
What is more odd is the result of the synthesis result. Here the picture shows a part of my synplify synthesis result.
The gate level looks like correct, Z is a AND gate of all inverted Result signals, which when Result == 0, the output Z should be 1.
However, I spend all my afternoon yesterday try to figure out how to fix this bug, I fount that if I use assign statement instead of using if statement, then the simulation gives correct behaviour. assign Z = (Result ==0 )? 1:0;
I thought this two version of describing Z should be same! After I modified my code by using
assign Z = (Result ==0 )? 1:0;
The synthesis result still same as the picture I showed above...
Can someone tell me what is going on?
Thanks so much!!!
I believe the issue is with your order of operation. always_comb blocks execute procedurally, top to bottom. In simulation, Z is updated first with the existing value of Result (from the previous time the always block was executed). The Result is updated and Z is not re-evaluated. Result is not part of the sensitivity list because it is a left-hand value. Therefore, Z will not get updated until a signal that assigns Result changes.
Synthesis is different, it connects equivalent logic gates which may result in asynchronous feedback. Logical equivalent is not the same as functional equivalent. This is why synthesis is giving you what you logically intend and RTL simulation is giving what you functionally wrote. Explaining the reasons for the differences is outside the scope of this question.
When coding a RTL combinational block, just do a little self check and ask yourself:
Are the values at the end of a single pass of this always-block the intended final values? If no, rearrange your code.
Will any current values in this always-block be used assign any values in the next pass? If yes, rearrange your code or synchronize with a flip-flop.
In ALU case, tt is an easy fix. Change:
always_comb begin
if (Result==0) Z = 1; // <-- Z is evaluated using the previous value of Result
else Z = 0;
/*Logic to assign Result*/ // <-- change to Result does not re-trigger the always
end
To:
always_comb begin
/*Logic to assign Result*/ // <-- update Result first
if (Result==0) Z = 1; // <-- Z is evaluated using the final value of Result
else Z = 0;
end
An alternative solution (which I highly discourage) is to replace the always_comb with The IEEE1364-1995 style of combinational logic. Where the sensitivity list is manually defined. Here you can add Result to get the feed back update:
always #(ALU_control or adder_rlt or add_rlt or or_rtl or xor_rtl or Result)
I highly discourage because it easy to miss a necessary signal, unessary signals waste simulation time, creates a risk of zero time infinite loop, and you still don't get a guaranty functional equivalent between RTL and synthesis.