Electrical – Task doesn’t work in verilog

hdlsystem-verilogverilog

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

Best Answer

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.