I am trying to build a driver module for the SMI interface on my ethernet PHY. My top level module contains the following ports with eth_mdio marked as inout.

    module top
        input        clk_100,
        input        cpu_rst_n,

        output       eth_mdc,
        inout        eth_mdio,
        output       eth_rstn,
        inout        eth_crsdv,
        inout        eth_rxerr,
        inout  [1:0] eth_rxd,
        output       eth_txen,
        output [1:0] eth_txd,
        output       eth_clkin,
        inout        eth_intn,
        input  [15:0] sw,
        output [15:0] led,
        input         btnc


    smi smi_inst




Inside the top module I create an instance of a submodule called smi which has the following ports.

module smi
    input         clk_50,
    input         rst_n,

    output        ready,
    input         valid,
    input         write,
    input  [4:0]  phyaddr,
    input  [4:0]  register,
    input  [15:0] write_value,
    output [15:0] read_value,

    output reg    eth_mdc,
    inout         eth_mdio

Inside of smi I assign eth_mdio as follows...

assign eth_mdio   = state == STATE_IDLE ? 1'b0 : (state == STATE_READ ? 1'bz : send_buffer[64]);

When I go to synthsize the design I get the following critical warning...

[Synth 8-5744] Inout buffer is not created at top module top for the pin eth_mdio, other connections may not have buffer connection ["/home/chase/workspace/EthernetTest/src/top.v":3]

What is causing this and how can I fix it? How can I pass an inout through the hierarchy?

  • \$\begingroup\$ Try putting parenthesis around state == STATE_IDLE, like so: (state == STATE_IDLE) \$\endgroup\$ Jun 13, 2018 at 2:36
  • \$\begingroup\$ also, you've got a bunch of inout ports that should probably just be input \$\endgroup\$ Jun 13, 2018 at 2:36

2 Answers 2


I thought that I had used Bi-directional port inside a hierarchy but to be 100% sure I tried a simple example.

That example passed synthesis in Vivado without any problems. However it maybe that it passes because the code is so trivial. Who knows what idiosyncrasies the Vivado synthesis tool has. This was what worked for me:

module bidir_top  (
   input         clk,
   output         I,
   input          set_in,
   inout          pad 

bidir bidir_0 (
   .clk     (clk),
   .I       (I),     //<
   .set_in  (set_in),//<
   .pad     (pad)    //X
); // bidir

endmodule // bidir_top  

module bidir (
  input  clk,
  output I,
  input  set_in,
  inout  pad
reg [1:0] cnt;
  always @(posedge clk)
     cnt <= cnt + 2'b01;  

  assign pad = set_in ? 1'bz : cnt[1];
  assign  I  = pad;

endmodule  // bidir 

You can try to make the tri-state expression as basic as possible as shown above. Maybe that works.

Alternative is to make a tri-state or read/write signal and pass all three signals (In,Out,Tri) to the top and there you have to make your I/O pads.


Like @Oldfart said,

Alternative is to make a tri-state or read/write signal and pass all three signals (In,Out,Tri) to the top and there you have to make your I/O pads.

This is my recommendation. Handle all tri-states at the top-level if possible (I always use IO rings). You may not be able to do this though (easily, i.e. without editing) if re-using a component/module that has bidirects on the ports, and in that case, there used to be (probably still is) a setting in synthesis for "push all tristates" (Pushes them to the top-level).

So, If you can't code it such that the tristates are "at the top", you can at least, with that setting prevent any mapping/PAR issues... last I knew there were no internal tri-states in an FPGA, and likely why you got your error.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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