How to write a module with variable number of ports in Verilog

青春壹個敷衍的年華 提交于 2019-12-12 13:31:26

问题


I would like to write a module with a variable number of inputs, i.e. depending on some parameter, the result would be:

module my_module #(LENGTH)(
    input clk,
    input rst_n,
    input [LENGTH-1:0] data_1
);
//...
endmodule

or

module my_module #(LENGTH)(
    input clk,
    input rst_n,
    input [LENGTH-1:0] data_1,
    input [LENGTH-1:0] data_2,
    input [LENGTH-1:0] data_3
);
//...
endmodule

Would it be possible to do this in Verilog or Systemverilog or would I have to write a script, let's say in Python, in order to generate the code for a specific module with fixed number of inputs? (it might be more than 1000 inputs)


回答1:


There are no variable number of ports in SystemVerilog, but you could use a port that is a parameterized array.

module my_module #(int LENGTH, DEPTH)(
    input clk,
    input rst_n,
    input [LENGTH-1:0] data[DEPTH]
);
//...
endmodule

Otherwise, you would need to use a script to generate the code.




回答2:


Use a two dimensional input with a parameterized size. Added a generate for loop that can be used to set signals individually. Although many operations can be done with smart array operations.

module my_module #(SIZE, LENGTH)(
    input clk,
    input rst_n, 
    input [SIZE-1:0][LENGTH-1:0] data_in_array,
    output [SIZE-1:0][LENGTH-1:0] data_out_array
);
genvar N;
generate for (N=0; N<SIZE; N++) begin :la_coolOps
    //Do cool operations here. For example instantiate a module for every data_in
end
//...
endmodule

Edit: As Mehran Torki points out: The syntax above will work for SystemVerilog only. Verilog does not allow for multiple packed arrays. Use input [LENGTH*SIZE-1:0] data_in_array.




回答3:


I would add to these other answers that ports are just groupings of wires. While having 3, 1-bit wires named a, b, and c might be easier to read and understand, there is no physical/logical difference between a single, 3-bit wire abc, where abc[0] corresponds to a, abc[1] corresponds to b, and abc[2] corresponds to c.

So, you can always just expand or shrink a single (or multiple) signal(s) to get however many bits you need. It may not be as neat, but it will work. In the receiving module, you can then part-select the bus in whatever manner you like. So, you could have one really long wire the shrinks or expands (wire [(SOME_PARAM*8)-1:0] my_input_wire), or with SystemVerilog an array (wire [7:0] my_input_wire[0:SOME_PARAM-1])

If this is just testbench/verification code, the other thing you could do in SystemVerilog is use a dynamic array




回答4:


As others said, there is no direct way to do this, but another workaround is to use SystemVerilog interfaces, where you define all the inputs that you want in the interface definition and inside the module only use the ones that correspond to the parameter. Below is a sample:

module my_module #(LENGTH)(
       input clk;
       input rst_n;
       output o;
       interface i_data;
    );
    logic outValue;

    generate
        case (LENGTH) //Based on the value of LENGTH, use corresponding data
            1: outValue = i_data.data_1;
            2: outValue = i_data.data_1 + i_data.data_2;
            3: outValue = i_data.data_1 + i_data.data_2 + i_data.data_3;
        endcase 
    endgenerate

    always @(posedge clk) begin
    if (~rst_n)
        o <= '0;
    else
    begin
        o <= outValue;
    end

endmodule

You can still use a parameterized array for data and a for-generate loop if your outputs are similar.



来源:https://stackoverflow.com/questions/35156150/how-to-write-a-module-with-variable-number-of-ports-in-verilog

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!