I created a module that first sorts a byte array then choose last element as minimum.(just for practice). When I moved sort to the task block, it doesn't worked as well as before. How can use task block properly for sorting ? thanks.
Sort without task:
module sort(input clk, input nrst, output byte choose);
byte sorted[0:3];
assign choose = sorted[3];// output must be minimum after sort (12)
always@(posedge clk, negedge nrst) begin
if(nrst == 0) begin // initialize to something
sorted[0] = 17;
sorted[1] = 12;
sorted[2] = 23;
sorted[3] = 21;
end
else begin
int i, j;
byte tmp;
//sort
for(i=0; i<4; i=i+1)
for(j=0; j<4; j=j+1)
if(sorted[j] < sorted[j+1]) begin
tmp = sorted[j]; // swap
sorted[j] = sorted[j+1];
sorted[j+1] = tmp;
end
end
end
endmodule
Sort with Task:
module sort(input clk, input nrst, output byte choose);
byte sorted[0:3];
assign choose = sorted[3];// output must be minimum after sort (12)
always@(posedge clk, negedge nrst) begin
if(nrst == 0) begin // initialize to something
sorted[0] = 17;
sorted[1] = 12;
sorted[2] = 23;
sorted[3] = 21;
end
else begin
sort_task(sorted);
end
end
task sort_task(inout byte list[3:0]);
begin
int i, j;
byte tmp;
//sort
for(i=0; i<4; i=i+1)
for(j=0; j<4; j=j+1)
if(list[j] < list[j+1]) begin
tmp = list[j];
list[j] = list[j+1];
list[j+1] = tmp;
end
end
endtask
endmodule
Testbench:
module tb();
byte choose;
reg nrst, clk;
sort sort(clk, nrst, choose);
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
int i;
nrst = 1;
#50;
for(i=0; i<4; i=i+1)
$display("50 : %d", sort.sorted[i]);
nrst = 0;
#50
for(i=0; i<4; i=i+1)
$display("100 : %d", sort.sorted[i]);
nrst = 1;
#50
for(i=0; i<4; i=i+1)
$display("150: %d", sort.sorted[i]);
end
endmodule
1 Answer 1
The problem is there is a mismatch in the index declaration for sorted[0:3]
versus list[3:0]
, so (list[j] < list[j+1])
gives you the reverse evaluation. I strongly recommend using common typedef's (in a package) to eliminate problems like this.
typedef byte list_t[4];
list_t sorted;
task sort_task( inout list_t list);
BTW, using a typedef gives you the syntax needed to declare a function with unpacked return type because any simple name is allowed for a return type, no matter how complex the typedef is.
Also, I agree with you that a task is synthesizable, as long as the code inside the task is meets your tools synthesis modelling style. But I would prefer that people use a void function instead of a task when their task has no time consuming statements. A function is a guarantee that it will not consume time.
-
\$\begingroup\$ This is being assigned as synchronous logic, therefore non-blocking assignments (
<=
) is recommended. Blocking assignments should be used inside method to keep it portable and self-contained. I'd suggest the method header befunction list_t sort_func( input list_t list);
which returns the sorted list, and then you can assign the array assorted <= sort_func(shorted);
. \$\endgroup\$Greg– Greg2016年03月16日 16:47:42 +00:00Commented Mar 16, 2016 at 16:47 -
\$\begingroup\$ Thank you for your professional guidance. I was involved in this question that how can return a list from a function. Using typedef solved it. But I don’t understand why function is better the task. I think in compile time, inner codes of the both blocks will move to the place that they called. \$\endgroup\$Soheil Shababi– Soheil Shababi2016年03月16日 17:31:37 +00:00Commented Mar 16, 2016 at 17:31
-
\$\begingroup\$ You will appreciate the guideline better when you start having nested calls to tasks and functions - especially when you start writing testbenches that have nested calls. Calling a function documents your intent that the call will not block, as well as any other nested call. The problem with using nested task calls is when a task deep inside your call stack has a modification that blocks - it will be very difficult to debug. Verilog did not have void functions - they always had to be used in an expression. That's why you see lots of non-time-consuming tasks. \$\endgroup\$dave_59– dave_592016年03月16日 20:52:41 +00:00Commented Mar 16, 2016 at 20:52
byte [0:3]
(for sorted list), Modelsim give error 'can't assign unpacked...'. I didn't know how to return a list of bytes from a function, so I preferred using task. I think tasks are synthesisable as well as functions. \$\endgroup\$