0
\$\begingroup\$

I am pretty new to Verilog. I wrote a description for a generic multiplexer in Verilog as follows:

module mux_generic
#(parameter BUS_WIDTH = 4,
  parameter SEL = 5 )
( input wire [BUS_WIDTH-1:0] data_in [(2**SEL)-1:0],
  input wire [SEL-1:0] ctrl_sel,
  output reg [BUS_WIDTH-1:0] data_out );

  always @ ( * )
  begin
    data_out = data_in[ctrl_sel];
  end
endmodule //mux_generic

And though it synthezies with Xilinx ISE 14.7 without error, I so see a warning at line #4:

WARNING:HDLCompiler:1335 - "D:\verilog\mux_generic.v" Line 4: Port data_in must not be declared to be an array.

I also wrote a top level module, which instantiates the above module:

module mux_generic_top( input wire [1:0] data_in [31:0],
                        input wire [4:0] ctrl_sel,
                        output wire [1:0] data_out );

  mux_generic #(.BUS_WIDTH(2), .SEL(5)) mux_32to1_2b(.data_in(data_in),
                                                     .ctrl_sel(ctrl_sel),
                                                     .data_out(data_out));
endmodule // mux_generic_top

The synthesis tool now given an error:

ERROR:HDLCompiler:251 - "D:\verilog\mux_generic_top.v" Line 5: Cannot access memory data_in directly

Also previous warning shown during synthesis of mux_generic i.e. HDLCompiler:1335 , is now shown as Error by Xilinx ISE simulator.

Has it something to do with Verilog language version support ? Can ports not be declared an array in Verilog as they can be done in SystemVerilog ? How to avoid these issues in Verilog while still being able to write generic designs ?

\$\endgroup\$
1
\$\begingroup\$

Can ports not be declared an array in Verilog as they can be done in SystemVerilog ?

The simple answer is: No. You can't.

If you really need, you can concatenate and split:

  • Make the input a vector which is big enough to hold all the data.
  • Concatenate your array of vectors into one big vector.
  • Pass the vector through the port.
  • At the other side split into an array of vectors again.

This is how I learned to cope before System Verilog came along.

\$\endgroup\$
1
\$\begingroup\$

Ok, so I think I found similar problem here: https://electronics.stackexchange.com/a/189756/11120

Seems like Verilog does not support two dimensional arrays or unpacked arrays as ports and this support is only available in SystemVerilog. So instead of declaring array of ports where each port is a bit vector, one can instead declare single huge port (bus) which combines the bit lines of each bit vector (sub-bus). Thereafter, one can still access sub-bus within the bus by using the Verilog-2001 range select slicing method that uses operators such as +: or -: to access slice of a multi-bit vector.

My rewritten modules are as follows:

mux_generic.v

module mux_generic
#(parameter BUS_WIDTH = 4,
  parameter SEL = 5 )
( input wire [(BUS_WIDTH * (2**SEL) )-1:0] data_in,
  input wire [SEL-1:0] ctrl_sel,
  output reg [BUS_WIDTH-1:0] data_out );

  always @ ( * )
  begin
    data_out = data_in[ctrl_sel*BUS_WIDTH +: BUS_WIDTH];
  end
endmodule //mux_generic

mux_generic_top.v

module mux_generic_top( input wire [63:0] data_in,
                        input wire [4:0] ctrl_sel,
                        output wire [1:0] data_out );

  mux_generic #(.BUS_WIDTH(2), .SEL(5)) mux_32to1_2b(.data_in(data_in),
                                                     .ctrl_sel(ctrl_sel),
                                                     .data_out(data_out));
endmodule // mux_generic_top
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.