cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
spilipchuk
Visitor
Visitor
920 Views
Registered: ‎09-18-2019

Why won't Vivado automatically create needed buffer when using inout / bidirectional port?

So I was trying to use this I2C component which obviously uses inout port for clock and data and I'm having hard time making it work.

To test how inout ports work I've setup this simple project (see attached).

The issue seems to be that Vivado won't automatically generate correct buffers for the INOUT and is giving me the following error during implementation:

  • [DRC RPBF-3] IO port buffering is incomplete: Device port SCL_PORT expects both input and output buffering but the buffers are incomplete.

Think is when I was implementing this using Xilinx ISE suite there was no issues whatsoever. Everything was automatically generated.

Any help and pointers would be greatly appreciated.

0 Kudos
16 Replies
hongh
Moderator
Moderator
882 Views
Registered: ‎11-04-2010

Hi, @spilipchuk ,

As an inout port, SCL_PORT should be used as both input and output.(Both driver and load)

In the test design port SCL_PORT is only used as an output(loader), so the IOBUF is not inferred automatically. 

Please try to use port SCL_PORT as a driver(input) in the test design.

 

-------------------------------------------------------------------------
Don't forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
spilipchuk
Visitor
Visitor
828 Views
Registered: ‎09-18-2019

I added the following line but now I get "SCL_PORT has multiple drivers" error.

SCL <= SCL_PORT;

0 Kudos
drjohnsmith
Teacher
Teacher
818 Views
Registered: ‎07-09-2009

So its VHDL

Well, 

A few house keeping things 

   don't use all those libraries,

https://www.nandland.com/articles/std_logic_arith_vs_numeric_std.html

 

next in the test bench etc, dont use the 

component TOP_MODULE
port(
EXT_CLK_IN : in std_logic; -- External FPGA clock input
SCL_PORT : inout std_logic; -- EPROM serial clock
OUTPUT_PORT : out std_logic); -- for testing purposes
end component;

just use 

uut: entity work.TOP_MODULE

PORT MAP (

 

last in your code you have

SCL <= SCL_internal;

and

SCL <= SCL_PORT

QED, SCL is being driven twice,

 

<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>
802 Views
Registered: ‎01-22-2015

@spilipchuk 

The goal is to connect an IOBUF to your VHDL inout port.

It is possible to infer the IOBUF by writing your VHDL is a special way.  

However, I think you will find it easiest to simply instantiate the IOBUF into your design and connect it to the inout port using VHDL.  See UG953(v2020.2) starting on page 382 for details of instantiating IOBUF for a 7-Series device.

You might find some useful I2C ideas in <this> post.

Cheers,
Mark

0 Kudos
spilipchuk
Visitor
Visitor
797 Views
Registered: ‎09-18-2019

I appreciate everyone's help. What really bothers me is why I didn't have this issue with inout ports when I was using ISE. I thought Vivado supposed to be the "new and next great" thing but it can't even automatically generate required buffers based on HDL which ISE did.

0 Kudos
spilipchuk
Visitor
Visitor
730 Views
Registered: ‎09-18-2019

Can someone post a simple example using inout port using Vivado and in VHDL without manually instantiating an IOBUF? I just can't seem to get it. The only time it works is if I make all IOBUF "I" and "O" external ports (physical pins) but that seems ridiculous since usually those signals are controlled by internal fabric. The minute I change them from ports to signals VIVADO can't automatically create the IOBUF and gives me error about incomplete buffers.

0 Kudos
drjohnsmith
Teacher
Teacher
720 Views
Registered: ‎07-09-2009

Did you read my post ?

   You have a typo in your code,

 

<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>
0 Kudos
spilipchuk
Visitor
Visitor
708 Views
Registered: ‎09-18-2019

Yes I saw your comment. Thank you.

I cleaned up the code and even removed the test bench as it is not needed at this point since I can't even get the design to work.

Please look at the attached cleaned up code. Vivado still refuses to instantiate the proper IO buffering and is giving me the following errors:

  • [DRC RPBF-3] IO port buffering is incomplete: Device port IO_PORT expects both input and output buffering but the buffers are incomplete.

And in the schematic it is clear that the IO_PORT buffering is wrong and there is no route from IO_PORT to the internal fabric, only out.

 

0 Kudos
drjohnsmith
Teacher
Teacher
693 Views
Registered: ‎07-09-2009

Nothing strange there,

  you have 

IO_PORT <= OUTPUT_sig WHEN EN_sig = '1' ELSE 'Z';
INPUT_sig <= IO_PORT;

 

But INPUT_Sig is not used in your code,

   so the tools trim it out, 

      that's why there is no bidirectional

 

Strongly suggest that you believe in the tools as the first stage,  

    Not making the buffer is very very common, you would not be the first to use them, so others would have found the problem is mor eliekly than it s a problem,

    Not saying a problem is impossible, but ocams razor says the tools are more likely right in this case.

https://simple.wikipedia.org/wiki/Occam%27s_razor#:~:text=Occam's%20razor%20(or%20Ockham's%20razor,the%20more%20unlikely%20an%20explanation.

If your in doubt

 

Try this code

https://startingelectronics.org/software/VHDL-CPLD-course/tut16-tri-state-buffer/

It makes a nice tri state buffer, that also works in the test bench 

You will get there

You will not believe ( I hope ) the stories I have about obvious mistakes I made , and still make,

   ( like the coin that got stuck to back of a board on bench, and made intermittent short, took hours till I lifted up the board and coin dropped out , I could have sworn it was a ghost in the board )  

 

 

<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>
spilipchuk
Visitor
Visitor
673 Views
Registered: ‎09-18-2019

Haha we've all been there. And its usually something small and seemingly insignificant that breaks the whole thing.

So I don't know why Vivado considers INPUT_sig not used. Do all signals HAVE to go out to external port in order to be considered "used"?? What if I just want to run a process run infinitely without outputting anything outside of the FPGA just for the purpose of using the FPGA as heat generator to warm up my garage? How do I do that?

But anyway, I've change a code a bit to put the INPUT_sig to use. See attached. Now Vivado is telling me the design is empty and implementation fails. 

 

0 Kudos
drjohnsmith
Teacher
Teacher
623 Views
Registered: ‎07-09-2009

The definition of a used signal is one that ends some where

   Normaly thats an IO pin.

The tools are very good at trimming back signals that are redundant,

One big thing, 

  You are missing the Simulation stage now,

      Simulation is where al these problems can be identified and fixed, 

    they are just like your C compiler, in the bit run on the CPU, all the redundant bits are optimised away.

In FPGA land we do not compile and hope, there is just to much going on inside the chips that we code to have few ideas as to what's gone wrong at run time.

So even if you have a great big function , that ends up at a single output , for instance a monitor circuit driving a led,

   if you forget to connect the led, all the monitor circuit will be removed as its redundant.

 

 

<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>
0 Kudos
drjohnsmith
Teacher
Teacher
619 Views
Registered: ‎07-09-2009

quick look at your code,

 

You have faults here

process (EXT_CLK_IN_PORT, OUTPUT_sig, counter) begin

and

process (EXT_CLK_IN_PORT, INPUT_sig, EN_sig) begin

Both of these the tolls would have warned you about.

 

Go back to the simple example I sent you the link for,

   make certain you can run that and a test bench,

    You are making all the classic beginners mistakes, we have all done, 

        you need to learn now how to debug them, as later it will get real complex, but the same skills will work on complex debugging.

In the simulator, trace your faulty signal back, trust the tools, and check the warnings the tools give you 

 

<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>
0 Kudos
spilipchuk
Visitor
Visitor
597 Views
Registered: ‎09-18-2019

Okay I narrowed it down to the fact that Vivado doesn't like something about this kind of statement: IO_PORT <= OUTPUT_sig when EN_sig = '0' else 'Z'. It doesn't seem to have anything to do with the type of signals in this statement but the statement structure/type in itself. Actually Vivado would give me an error that this is not supported when "Type" setting for the source file was set to VHDL  and not even run synthesis - I had to switch the type to VHDL-2008! But even then I was having all kinds of issues as discussed in this tread above UNTILL I changed that statement to the following:

process (EXT_CLK_IN_PORT, EN_sig, INPUT_sig, IO_PORT) begin
     if rising_edge (EXT_CLK_IN_PORT) then
          if (EN_sig = '0') then
                IO_PORT <= INPUT_sig;
         else
               IO_PORT <= 'Z';
        end if;
        INPUT_sig <= IO_PORT;
    end if;
end process;

 

This finally results in what looks like correct IOBUF inference. The T ling is tied to ground for some reason but I think that's because its not really driven by anything in my code.

Schematic.png
0 Kudos
drjohnsmith
Teacher
Teacher
588 Views
Registered: ‎07-09-2009

Your original code had faults, 

   which is why it did not work

This new code of yours is better ,

     its has no faults, but has warnings,

look here

process (EXT_CLK_IN_PORT, EN_sig, INPUT_sig, IO_PORT) begin

 

 

<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>
0 Kudos
spilipchuk
Visitor
Visitor
583 Views
Registered: ‎09-18-2019

Whats wrong with that line?

By the way, any idea why the second process is completely ignored? Is it again because those signals don't go out to a physical port?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity TOP_MODULE is
port (
EXT_CLK_IN_PORT : in std_logic; -- External FPGA clock input
IO_PORT : inout std_logic); -- Bi-directional IO port
end TOP_MODULE;

architecture RTL of TOP_MODULE is


signal EN_sig : std_logic := '0'; -- tri-state direction control signal for the IO port
signal INPUT_sig : std_logic := '0'; -- signal from the IO port to the FPGA internal fabric

begin


process (EXT_CLK_IN_PORT, EN_sig, INPUT_sig, IO_PORT) begin
-- if EN signal is 0 IO PORT is an output, otherwise in high-Z mode or input
if rising_edge (EXT_CLK_IN_PORT) then
if (EN_sig = '0') then
IO_PORT <= INPUT_sig;
else
IO_PORT <= 'Z';
end if;
INPUT_sig <= IO_PORT; -- creates a route from IO PORT to input signal for when IO PORT is an input
end if;
end process;

process (EXT_CLK_IN_PORT, INPUT_sig, EN_sig) begin
if rising_edge (EXT_CLK_IN_PORT) then
if (INPUT_sig = '1') then
EN_sig <= '0';
end if;
end if;
end process;

end architecture RTL;

0 Kudos
drjohnsmith
Teacher
Teacher
487 Views
Registered: ‎07-09-2009

a) look at the sensetivity list, and what is sensetive in the process

b) strongly suggest you get this book

http://freerangefactory.org/

c) Your second process, You have to understand the tools, in synthesis the tools are trying to fit your code, like in C compilers, any unused signals are removed. As you say , the second process has no need to be there, so its removed.

 

<== If this was helpful, please feel free to give Kudos, and close if it answers your question ==>
0 Kudos