Verilog Ports in Generate Loop

2.6k views Asked by At

For reasons which cannot be avoided (requirements of Qsys), I have several Verilog modules which end up with many ports which would be far easier to work with if they were packed. To try and explain what I mean, here is an example:

module foo #(
    COUNT = 4
) (
    //Interface 0
    input  bar_0,
    output deadbeef_0,

    //Interface 1
    input  bar_1,
    output deadbeef_1,

    //Interface 2
    input  bar_2,
    output deadbeef_2,

    //Interface 3
    input  bar_3,
    output deadbeef_3,
);
...
endmodule

Now normally one would just make two vectorised ports (e.g. input [COUNT-1:0] bar,), however Qsys cannot cope with this if the signals need to be fed onto different interfaces - you can only select an entire port, not just a bit of one.

As you can imagine, this gets very irritating if internally you need to access the ports in something like a generate loop, and is especially problematic if you have a module with interfaces that have 10 ports which have to be written out 16 times!

What I've been doing up until now would be to add a mapping into the module manually. Again and example to explain - continuing the example above, I'd have something like this in the body of the module:

wire [COUNT-1:0] bar;
wire [COUNT-1:0] deadbeef;
generate
if (COUNT > 0) begin
    assign bar[0] = bar_0;
    assign deadbeef_0 = deafbeef[0];
end else begin
    assign deadbeef_0 = 1'b0; //Terminate!
end
if (COUNT > 1) begin
    assign bar[1] = bar_1;
    assign deadbeef_1 = deafbeef[1];
end else begin
    assign deadbeef_1 = 1'b0; //Terminate!
end
...
endgenerate

// deadbeef[] and bar[] can now be used as arrays, woop.

Even just writing out a couple of the interfaces for only two signals in that example was incredibly tedious!

Every part of the programmer in me is screaming out to stop doing this and that there must be a better way. And that brings me to my question:

Is there a simple way of doing this?

Ideally I'd have some form of loop which generates these mappings for me, generating the signal names from a loop variable. But I'm not sure if this is even possible in Verilog.

Also, just to make things interesting, I have been using hexadecimal for ports to make things easier when writing it out, for example:

input bar_0,
input bar_1,
...
input bar_9,
input bar_a,
input bar_b,
...

Ideally the solution to this would also cope with names like that, but to be honest I could easily convert the names to decimal (bar_10) if it simplifies things.


In case you are wondering, this is made very easy in Qsys to link the interfaces to ports because Qsys uses TCL files to make the mapping. In TCL I can simply use a for loop and concatenate the loop variable to make the names.

1

There are 1 answers

2
Karan Shah On

I guess, in your case, macro can be used to solve your problem. So, everywhere, in your code, you can use bar as a vector, though it is not.

Define a macro like this :

`define bar(n) bar_``n``
`define deadbeef(n) deadbeef_``n``

You can use now bar as a vector like below:

`bar(0)
`deadbeef(0)