I have a project, written in Verilog (importantly not SystemVerilog) which has gotten a little unmanageable due to the number of signals being passed along between different parts of the design. Since I have several modules which all need the same signals, I was thinking of trying to consolidate them into a smaller number of named objects. The questions is how to do it.
Let's say this is my contrived example:
module mymodule(sig_a_in, sig_b_in, sig_c_in, sig_d_in, sig_e_in,
sig_a_out, sig_b_out, sig_c_out, sig_d_out, sig_e_out);
input wire sig_a_in, sig_b_in, sig_c_in;
input wire [5 : 0] sig_d_in;
input wire [31 : 0] sig_e_in;
output reg sig_a_out, sig_b_out, sig_c_out;
output reg [5 : 0] sig_d_out;
output reg [31 : 0] sig_e_out;
endmodule
It is important, in my opinion, for readability that I can reference the signals by name. However, I don't want to have to pass them all individually to each module. Again, I am only using Verilog in this project so SystemVerilog constructs are not possible.
My first thought was that I would just combine them into one bus and then use defined names to reference the individual wires. This is kind of clunky, however, particularly when you add other buses into the mix. This is pretty trivial in my contrived example because the signals have an obvious implicit order, but in real life they don't.
`define SIGNAL_BUS_WIDTH 41
`define A 0
`define B 1
`define C 2
`define D 3
`define E 9
module mymodule(signal_bus_in, signal_bus_out);
input wire [`SIGNAL_BUS_WIDTH-1 : 0] signal_bus_in;
output reg [`SIGNAL_BUS_WIDTH-1 : 0] signal_bus_out;
// reference a
signal_bus_in[`A]
// reference d? Not good when names don't have an obvious order
signal_bus_in[`E-1 : `D]
endmodule
Finally, in addition to all of this, it is necessary for the tool chain to be able to distinguish which wires in the struct are being used by the module and to only synthesize those wires. Not all the modules use all the wires, so I want to avoid having extra unused paths. I think that the tools should be smart enough to do this, even in my bus example above, but I'm not completely sure.
Is there a good way to get what I want in Verilog?
You can always extend you idea a bit further by use macros to define the range of each signal rather than an endpoint:
`define WIDTH 41
`define sigA 0:0
`define sigB 1:1
`define sigC 2:2
`define sigD 8:3
`define sigE 40:9
module mymodule(signal_bus_in, signal_bus_out);
input wire [`WIDTH-1 : 0] signal_bus_in;
output reg [`WIDTH-1 : 0] signal_bus_out;
...
// signal a
signal_bus_in[`sigA];
// signal d
signal_bus_in[`sigD];
...
Of course, this isnt as easy as SystemVerilog packed structs (which is why they exist!), but it will work for what you want. Also, this added order to your lines as well, but I see no structure that wont do that; even structs will add an order to your signals. So long as you use the macros however, it doesnt really matter that there order except when you define the marcos.
Any good synthesis tool should be able to throw out any port or wire that does not drive anything or is not drive by anything, so unless you have to explicitly tell it which lines to ignore for some reason, you shouldnt worry about it synthesizing extra space for unused module pins.
Verilog does not have structs. IMO combining all signals in a long vector (or as you call it a bus) is your best bet. But, you can slightly improve upon your macros:
`define SIGNAL_BUS_WIDTH 41
`define A 0:0
`define B 1:1
`define C 2:2
`define D 8:3
`define E 40:9
// reference a
signal_bus_in[`A]
// reference d
signal_bus_in[`D]
// reference e
signal_bus_in[`E]
Most synthesis tools do not create extra logic for the wires that are not connected and treat them as dont cares.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With