Electrical – How to properly use packed 2D arrays as input and outputs of verilog task

modelsimverilog

In a part of my verilog project, I am assigning a data to register M[i] by reading from register N[j]. I have written and simulated the code in verilog without any problem. As this particular pattern is repeated many times in a module, I'd like to convert it into a task.
But I'm getting compilation errors when using a 2D array of registers as input and output of the task. Below is a sample code that illustrates the problem.

`timescale 1 ns/100 ps
module test(clk, rst_n);
    input clk, rst_n;
    reg [1:0] idx1;
    reg [2:0] idx2;
    reg [15:0] M[3:0];
    reg [15:0] N[7:0];

    always @(posedge clk or negedge rst_n) begin
        idx1 <= rst_n ? (idx1 + 1) : 0;
        idx2 <= rst_n ? (idx2 + 1) : 0;
    end

    always @(posedge clk or negedge rst_n) begin
        if(~rst_n) begin : reset_registers
            integer i;
            for(i = 0; i < 4; i = i+1) M[i] = 0;
            for(i = 0; i < 8; i = i+1) N[i] = i;
        end
        else begin
            M[idx1] <= N[idx2];
        end
    end
endmodule

The module compiles and simulates as expected now. I would like to convert the segment M[idx1] <= N[idx2]; to a task. So, the new code using a task is:

`timescale 1 ns/100 ps
module test(clk, rst_n);
    input clk, rst_n;
    reg [1:0] idx1;
    reg [2:0] idx2;
    reg [15:0] M[3:0];
    reg [15:0] N[7:0];

    always @(posedge clk or negedge rst_n) begin
        idx1 <= rst_n ? (idx1 + 1) : 0;
        idx2 <= rst_n ? (idx2 + 1) : 0;
    end

    always @(posedge clk or negedge rst_n) begin
        if(~rst_n) begin : reset_registers
            integer i;
            for(i = 0; i < 4; i = i+1) M[i] = 0;
            for(i = 0; i < 8; i = i+1) N[i] = i;
        end
        else begin
            copy(idx1, idx2, M, N);
        end
    end

    task copy;
        input [1:0] x1;
        input [2:0] x2;
        output reg [15:0] A[3:0];
        input [15:0] B[7:0];
        begin
            A[x1] <= B[x2];
        end
    endtask
endmodule

I am getting the following errors when trying to compile it using modelsim:

# -- Compiling module test
# ** Error: D:\projects\test.v(21): Illegal task output argument.
# ** Error: D:\projects\test.v(21): (vlog-2110) Illegal reference to memory "B".
# 
# ** Error: D:\projects\test.v(21): Illegal LHS of assignment.
# ** Error: D:\projects\test.v(21): (vlog-2110) Illegal reference to memory "N".
# 
# C:/modeltech64_10.2c/win64/vlog failed.

Can someone please advise how to use the registers properly in a task? Exactly what is making the statements illegal? Is it even possible to something like this using a task, or is there other way around?
Thank you.

Best Answer

You need to be using SystemVerilog to have unpacked arrays as arguments to a task. And the task as you have written it does not do the same thing as the code without the task. That is because the output array A is uninitialized and you are only setting the value indexed by x1.