0

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.

Tom Carpenter
  • 539
  • 4
  • 18
  • You could write your module with vectorized ports (`input [COUNT-1:0] bar`) and then write a code generator (e.g. directly in your TCL script) that creates the verilog file for a simple wrapper module that provides the type of interface you need in Qsys. Not ideal but maybe still an improvement over doing it manually. – CliffordVienna Feb 14 '16 at 08:46
  • I am not getting, what you exactly wants to do. Can you please, share the snipped code on how you are using/instantiating that module? – Karan Shah Feb 14 '16 at 09:41
  • @KaranShah I thought the example was fairly clear. In Qsys (graphical system builder), for the example above I would have four interfaces which would be connected to something else. Qsys can't assign say bit 0 of a vector to one interface, only the whole thing. This means that instead of doing ```input [3:0] bar```, I have to do ```input bar_0, input bar_1, ...```. I then have to internally in the module do something like ```wire[3:0] bar; assign bar = {bar_3,bar_2,bar_1,bar_0}``` in order to be able to use the ```bar_*``` ports as a vector. – Tom Carpenter Feb 14 '16 at 15:15
  • @CliffordVienna that sounds like a good idea, I'll look into it. – Tom Carpenter Feb 14 '16 at 15:17
  • @TomCarpenter : I have posted an answer. I believe, that would be helpful to you – Karan Shah Feb 14 '16 at 15:35

1 Answers1

0

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)
Karan Shah
  • 1,912
  • 1
  • 29
  • 42
  • I considered this approach, but alas it only works in SystemVerilog (not the end of the world), but also more critically wouldn't work in a ```generate``` for loop. For example ```. `deadbeef(idx)``` would expand to ```deafbeef_idx``` not the value of ```genvar idx```. But thanks for the suggestion. I would still have to write out all the code to merge the interface ports into an array. – Tom Carpenter Feb 14 '16 at 15:39
  • For that case, you can use 2 macros, for same variable. ` `deadbeef(x)` and ` `deadbeef_gen(x)`. And to work with other languages, you can always compile this code, as per verilog language, and then merge elaborated code with the other languages. – Karan Shah Feb 14 '16 at 15:48