I'm trying to build a task, which must delve into some hierarchy, that can concisely compare different pins on a particular instance. In particular, I'd like to do something like the following:
task check_expected;
input integer pin;
input [9:0] expected;
integer i, j;
reg [9:0] check;
begin
j = 0;
for (i = 0; i < 20; i = i + 1) begin
case (pin)
0: begin
check[0] = test.inst[i].lane_0.PIN_FIRST;
check[1] = test.inst[i].lane_1.PIN_FIRST;
...
check[9] = test.inst[i].lane_9.PIN_FIRST;
end
1: begin
check[0] = test.inst[i].lane_0.PIN_SECOND;
check[1] = test.inst[i].lane_1.PIN_SECOND;
...
check[9] = test.inst[i].lane_9.PIN_SECOND;
end
...
9: begin
check[0] = test.inst[i].lane_0.PIN_TENTH;
check[1] = test.inst[i].lane_1.PIN_TENTH;
...
check[9] = test.inst[i].lane_9.PIN_TENTH;
end
endcase
if (check[0] !== expected[j*10 + 0]) begin
TEST_FAILED = TEST_FAILED + 1;
$display("ERROR Expected=%b, @ %0t",expected[j*10 + 0],$time);
end
if (check[1] !== expected[j*10 + 1]) begin
TEST_FAILED = TEST_FAILED + 1;
$display("ERROR Expected=%b, @ %0t",expected[j*10 + 1],$time);
end
...
if (check[9] !== expected[j*10 + 9]) begin
TEST_FAILED = TEST_FAILED + 1;
$display("ERROR Expected=%b, @ %0t",expected[j*10 + 9],$time);
end
end
end
endtask
Unfortunately, attempting to do the above throws a NOTPAR error during elaboration, claiming that it is unacceptable to assign a register to a non-constant (it doesn't like any lines like check[0] = test.inst[i].lane_0.PIN_FIRST;
). This is just for testing purposes, not anything synthesizeable, by the way.
Can someone explain why this is disallowed and suggest a different solution? It's looking like I'll need to write a task for each and every loop iteration, and that seems like it would be needlessly bloated and ugly.
Thanks
To answer my own question, the answer is that there is no way to do it with Verilog. Verilog is an incredibly dumb (in terms of capabilities) language, and, with a task, can only support constant indices for module instances. No looping is possible.