Reputation: 352
I have a Verilog testbench for a FIFO and I think using tasks to perform push and pop would be more effective than what I am doing now. Currently, I use a sequence of repeat (ticks) @ (negedge clk)
statements to push, pop or push and pop in a long initial begin/end block.
This makes the code ugly and difficult to read. I would rather have a task, push_task(ticks)
, that I can call. Something like this -
initial begin
task_push(5);
task_pop(2);
task_push(10);
...
end
The problem is, if I write my push_task
like this -
task push_task;
input [31:0] ticks;
repeat (ticks) begin
push <= 1'b1;
push_data <= $random % (2**DATA_WIDTH);
@ (negedge clk);
push <= 1'b0;
end
end
endtask
and I have a similar pop_task
, then I can either push or pop but not both at the same time. How do I get both to either execute at the same time or sequentially depending on what I want to do?
One obvious way is to create a third task that does both. Another way is to have a singe task with three inputs, ticks, push and pop and have push and pop be asserted based on whether the inputs to the task are asserted or not.
Does anyone have another (better?) way of doing this? I can find plenty of information online about what the syntax of tasks is and how to write them. Not much about what the correct way of using them is.
Upvotes: 1
Views: 4942
Reputation: 19094
Use fork
-join
for parallel operations, begin
-end
for sequential. Nesting is allowed.
Ex:
initial begin
task_push(10);
fork // parallel operations
task_push(4);
task_pop(7);
join
// back to sequential
fork // another parallel operation
task_push(6);
begin // sequential within parallel
task_pop(2);
@(negedge clk); // no pop for one cycle
task_pop(3);
end
join
end
FYI I will suggest changing your tasks to be more like the following. The header is more conventional; a IEEE1364-2001 & above and IEEE1800 style instead of the legacy IEEE1364-1995 style. Moving the assignments to push
outside the loop will save some CPU cycles in simulation. Your CPU time is probably nothing, but something to consider when scaling up to significantly larger project.
task push_task(input [31:0] ticks);
begin
push <= 1'b1;
repeat (ticks) begin
push_data <= $random % (2**DATA_WIDTH);
@(negedge clk);
end
push <= 1'b0;
end
endtask
Upvotes: 1