There is no requirement for inout
ports to be placed only in the top level. That being said, an FPGAs typically don't support internal tri-state buffers, so the use of them in internal modules is not necessarily representing a bidirectional signal.
In your case where you wish to feed a tristate signal from a lower level module up to the top level, this is perfectly acceptable. Just connect the inout
signal to the port connection list of your submodule. As long as each inout
pin connects ultimately to only one tristate buffer design at any level in the hierarchy, a proper tristate buffer will inferred. Remember, wires have no concept of direction until one is specified by an assignment, so feeding a bidirectional wire through the hierarchy is acceptable.
Where things get a bit more interesting is when you connect two inout
signals inside the FPGA. Typical FPGAs don't have internal tristates, so instead the synthesis tool has to infer multiplexing/demultiplexing logic (usually with some form of priority to avoid bus contention). This can cause differences between simulation and synthesis - sim might show x
for bus contention, but in synthesis one of the signals will take priority due to the multiplexer structure.
An example:
// Top level module inout represents a tri-state buffer
module topLevel(
inout [1:0] tlBidir
);
// inout can be fed entirely into one module, or shared between multiples
subModule first (
.bidir(tlBidir[0])
);
subModule second (
.bidir(tlBidir[1])
);
// This one is **not** a tristate buffer as used internally
// It will infer a multiplexer/demultiplexer structure.
wire internalWire;
subModule third (
.bidir(internalWire)
);
assign internalWire = ctrl ? 1'b0 : 1'bz;
endmodule
// A submodule which describes tristate buffer behaviour.
// Can be at any level
module subModule(
inout bidir
);
wire ctrl;
wire outVal;
wire inVal;
assign bidir = ctrl ? 1'bz : outVal;
assign inVal = bidir;
...
endmodule