SV Assertion - Implication matches unique valid sequences - system-verilog

I have assertion property as
assert property P;
property P;
#(posedge clk) A |-> ##[1:5] B;
endproperty
clk - 0 1 2 3 4 5 6 7 8 9 10
A - 0 1 0 1 0 0 0 0 0 0 0
B - 0 0 0 0 1 0 0 1 0 0 0
Here B = 1 at Clock num 4 satisfies assertion For A at Clocks 1 and 3.
How to write an assertion that checks for each A==1 we see a unique B==1 , meaning
A=1 at Clk 1 should match against B=1 at Clk 4
AND
A=1 at Clk 3 should match against B=1 at Clk 7.
Thanks,

Depending on you max number of outstanding A request without ack I would do something like:
// modeling layer
int A_cnt, B_cnt
always #(posedge clk)
if (A)
A_cnt += 1
if (B)
B_cnt += 1
property P;
int A_id_lv
#(posedge clk)
(A, A_id_lv=A_cnt) |-> ##[1:5] B && B_cnt == A_id_lv;
endproperty
I did not compile the code, this is a first draft, but I think the concept is there

int now_serving;
int ticket;
function int get_ticket();
return ticket++;
endfunction
property P;
int serving_ticket;
#(posedge clk) (A, serving_ticket = get_ticket()) |-> ##[1:5] (B && now_serving == serving_ticket);
endproperty
assert property(P) now_serving++;
else now_serving++;
This is uniqueness, credit to Ben, author of the systemverilog assertion handbook.

I don't think there is a way you can do it with modelling layer code. When the SVA is triggered on A==1 it cannot know if there has been a previous A that hasn't been "acked" with a B

Related

Logical equality for two different vector widths

Why does logical equality for two vectors of different widths have an output like below?
module eq_test;
logic check;
logic [3:0] cmp_0;
logic cmp_1 = 1'b0;
initial begin
for (int i = 0; i < 16; i++) begin
cmp_0 = i;
check = (cmp_0 == cmp_1);
$display("%b == %b is %b", cmp_0, cmp_1, check);
end
end
endmodule
With Vivado Simulator
0000 == 0 is 1
0001 == 0 is 0
0010 == 0 is 0
0011 == 0 is 0
0100 == 0 is 0
0101 == 0 is 0
0110 == 0 is 0
0111 == 0 is 0
1000 == 0 is 0
1001 == 0 is 0
1010 == 0 is 0
1011 == 0 is 0
1100 == 0 is 0
1101 == 0 is 0
1110 == 0 is 0
1111 == 0 is 0
I can assume that the variable with smaller width cmp_1 is expanded (unsigned expand) to the larger variable width cmp_0, is that so?
Yes, the variable with smaller width is expanded to the larger variable width.
This is described in IEEE Std 1800-2017, section 11.6.1 Rules for expression bit lengths.
The number of bits of an expression (known as the size of the
expression) shall be determined by the operands involved in the
expression and the context in which the expression is given.
In Table 11-21, the == operator has this comment:
Operands are sized to max(L(i),L(j))
where i and j represent expressions of an operand, and L(i) represents the bit length of the operand represented by i.
This is true for all simulators, not just for Vivado.

SystemVerilog assertion for primitive

is there a way to add an assertion for a SystemVerilog primitive or only in the module (cell) wrapping the primitive ? simply adding an assertion does not compile
primitive mux (q, d0, d1, s);
output q;
input s, d0, d1;
table
// d0 d1 s : q
0 ? 0 : 0 ;
1 ? 0 : 1 ;
? 0 1 : 0 ;
? 1 1 : 1 ;
0 0 x : 0 ;
1 1 x : 1 ;
endtable
//assert(s != x) else $error("s has value x"); - add this assertion
endprimitive
The only construct allowed inside a user defined primitive (UDP) is the table. You'll need to wrap the UDP in a module to add anything else.

char inside matlab function

I want to run turnMatrix(30,X) in MATLAB. I get this error message:
Undefined function or variable 'X'.
If I change X to 1 it is successful. My code is below.
function turnMatrix(d,b)
a = d * pi / 180 ;
if b == X % 1
R = [1 0 0 0 ; 0 cos(a) -sin(a) 0 ; 0 sin(a) cos(a) 0 ; 0 0 0 1];
elseif b == Y % 2
R = [cos(a) 0 sin(a) 0 ; 0 1 0 0 ; -sin(a) 0 cos(a) 0 ; 0 0 0 1];
elseif b == Z % 3
R = [1 0 0 0 ; 0 cos(a) -sin(a) 0 ; 0 sin(a) cos(a) 0 ; 0 0 0 1];
end
R
end
It looks like you are really expecting/wanting to specify the second input as a characters/string, that is
turnMatrix(30,'X')
Note the single quotes around 'X', which say that it is literally the character string 'X', not the value of the variable X.
Then inside the function you need
if b == 'X'
elseif b == 'Y'
elseif b == 'Z'
end
That is, compare the value of variable b to the character 'X'. The way you have it, you are trying to compare the value of variable b to the value of variable X, but variable X doesn't exist and hence the error.
Note also, that if you were comparing anything other than a single character (and even in the single character case) you'd be better off using a switch-case construct rather than if-else
switch b
case 'X'
case 'Y'
case 'Z'
end

Minizinc - assign job to specific machine

I have say n jobs and m machines and have a jobtype array with type of job. If the job is of specific type in job type array , i have to assign even numbered machine among the available else to the odd numbered machine. Is it possible with minizinc?
Snippet I tried given below:
forall(w in 1..num_workers) (
if jobtype[job] == "NC" then assignment[job,(w mod 2 ==0)]=1
else assignment[job,(w mod 2 !=0)]=1 endif
)
which is giving the following warning
WARNING: undefined result becomes false in Boolean context
(array access out of bounds)
TIA
Here is one model that might be what you want, i.e. to assign even numbered machines to the jobs marked as "NC". The important constraint is the following, which might be the one you want. Here we use a temporary decision variable w in the range of 1..num_workers, and then ensure that for the NC jobs the machine number must be even:
forall(job in 1..num_jobs) (
let { var 1..num_workers: w; } in
% Jobs with NC must be assigned to even numbered workers (machines)
if jobtype[job] == "NC" then w mod 2 == 0 else w mod 2 == 1 endif
/\ assignment[job,w]=1
)
Here is the full model - as I imagined it - with 7 jobs and 7 workers. I assume that a worker/machine can only be assigned to at most one job. Well, it's a lot of guesswork...
int: num_workers = 7;
int: num_jobs = 7;
array[1..num_jobs] of string: jobtype = ["NC","X","NC","X","X","NC","X"];
% decision variables
array[1..num_jobs, 1..num_workers] of var 0..1: assignment;
solve satisfy;
constraint
forall(job in 1..num_jobs) (
let { var 1..num_workers: w; } in
% Jobs with NC must be assigned to even numbered workers (machines)
if jobtype[job] == "NC" then w mod 2 == 0 else w mod 2 == 1 endif
/\
assignment[job,w]=1
)
/\ % at most one worker for each job (or perhaps not)
forall(job in 1..num_jobs) (
sum([assignment[job,worker] | worker in 1..num_workers]) <= 1
)
/\ % and at most one job per worker (or perhaps not)
forall(worker in 1..num_workers) (
sum([assignment[job,worker] | job in 1..num_jobs]) <= 1
)
;
output [
if w == 1 then "\n" else " " endif ++
show(assignment[j,w])
++ if w == num_workers then " (\(jobtype[j]))" else "" endif
| j in 1..num_jobs, w in 1..num_workers
];
The model yields 144 different solutions. Here's the first:
0 0 0 0 0 1 0 ("NC")
0 0 0 0 0 0 1 ("X")
0 0 0 1 0 0 0 ("NC")
0 0 0 0 1 0 0 ("X")
0 0 1 0 0 0 0 ("X")
0 1 0 0 0 0 0 ("NC")
1 0 0 0 0 0 0 ("X")

Combine two boolean equations to separate a boolean variables from others

I have 2 programs: X and Y.
X has two bitmaps A and C.
X calls Y.
Y has a bitMap B.
The code I need to execute in Y is
if AB == B && BC == C
//do some action Z
I want to combine on A and C using boolean operations such that I can pass a single bitMap to Y. This single bitmap can then do any boolean operation with B to return true / false and accordingly I can decide to do action Z.
There is no way to simplify by combining A and C.
Here is our truth table:
B A C Z
0 0 0 1
0 0 1 0
0 1 0 1
0 1 1 0
1 0 0 0
1 0 1 0
1 1 0 1
1 1 1 1
We can see from the truth table that when B = 0, we have Z = not C; when B = 1, we have Z = A.
Suppose for the sake of contradiction that we have a one-bit function Y = f(A, C) that "summarizes" A and C. We use B to choose whether the summary equals 'not C' versus 'A'. But this is clearly impossible, because a single bit cannot preserve enough information to be able to extract the value 'not C' and also the value 'A'.