Hi!
I verify a generic block.
It receives an array of signals and a corresponding array of clocks - each signal has its own clock.
The desire is to make sure that the signal rises at the rise of its clock (and not, for example, in the middle of the pulse).
I inherited code that does not refer to the generics of the block, and it checks all entries, even though they are sometimes incomplete:
event ev0, ev1 , ev2 , ev3 .... ev31;
generate
if (EN_CLK_DOMAIN_CHECKER) begin
initial begin
fork
forever @( posedge src_clk[0]) -> ev0;
forever @( posedge src_clk[1]) -> ev1;
forever @( posedge src_clk[2]) -> ev2;
forever @( posedge src_clk[3]) -> ev3;
...
forever @( posedge src_clk[31]) -> ev31;
join_none
end
end
endgenerate
`define DETECT_CLK_DOMAIN(INDEX)\
function bit func``INDEX``();\
if (ev``INDEX``.triggered) return 1;\
else return 0;\
endfunction\
property detect``INDEX``;\
@(posedge sig_in[``INDEX``])\
(func``INDEX``());\
endproperty : detect``INDEX``\
DETECT``INDEX`` : assert property (detect``INDEX``) else $error("ERROR - WRONG CLOCK DOMAIN");\
initial begin\
$assertoff(0,generic_checker.DETECT``INDEX``);\
wait (rstn === 1'b1);\
#1ns;\
if (EN_CLK_DOMAIN_CHECKER) begin\
$asserton(0,generic_checker.DETECT``INDEX``);\
end\
end
`DETECT_CLK_DOMAIN(0)
`DETECT_CLK_DOMAIN(1)
`DETECT_CLK_DOMAIN(2)
`DETECT_CLK_DOMAIN(3)
...
`DETECT_CLK_DOMAIN(31)
This code works fine, but it throws up a lot of warnings during the elaboration.
I tried a different approach:
genvar idx;
generate
if (EN)
for (idx =0; idx < NUM; idx++) begin
always @(posedge sig_in[idx]) begin
CLK_RISE_ASSERT: assert property (@(posedge sig_in[idx]) $rose(sig_in[idx]) |-> $rose(src_clk[idx]))
else $error ("ERROR - WRONG CLOCK DOMAIN");
end
end
endgenerate
But the code didn’t work at all.
I tried to make adjustments to the first code and make it more generic - like this:
event clk_event_array[NUM];
function automatic event new_clk_event();
event e;
return e;
endfunction
initial begin
foreach (clk_event_array[i]) begin
clk_event_array[i] = new_clk_event();
$display ("clk_event_array[%0d]", i);
end
end
generate
if (EN_CLK_DOMAIN_CHECKER) begin
initial begin
for (int i = 0; i < NUM; i++) begin
automatic int j = i;
fork
begin
forever @( posedge src_clk[j]) -> clk_event_array[j];
end
join_none
end
end
end
endgenerate
function clk_trig_evaulate(int i);
if (clk_event_array[i].triggered)
return 1;
else
return 0;
endfunction
property detect(i, sig_in, rstn, clk_event_array);
@(posedge sig_in) disable iff (!rstn) clk_trig_evaulate(i);
endproperty : detect
initial begin
if (EN_CLK_DOMAIN_CHECKER) begin
for (int i = 0; i < NUM; i++) begin : assert_loop
DETECT : assert property (detect(i, sig_in[i], rstn, clk_event_array[i])) else $error("ERROR - WRONG CLOCK DOMAIN - INDEX [%0d]", i);
end
end
end
And indeed it caught all the cases that the first code caught, but this time it dropped tests for me even in the case that the signal did arrive with the increase of its clock.
Can you tell me why the second code did not identify the violations at all, and why the third code identified cases as violations even though they were normal?
Can you suggest how to make the first code generic?
Many thanks in advance