VHDL: BUFG: why doesn't the output repeat?


Jon W

Recommended Posts

I'm using Xilinx ISE 14.7 to program a Papilio One 250k.

I'm trying to simulate a process that uses a BUFG component, and the output of the component is all 0 -- it doesn't follow the input.

Here's a small snippet of code:

library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.NUMERIC_STD.ALL;entity UART is    Port ( CLK : in  std_logic;	--	 CLK runs at 32 MHz           CLKDIV : in unsigned(15 downto 0); -- divide to bit clock    );end UART;architecture Behavioral of UART is	signal BITCLK : std_logic := '0'; -- four clocks per bit	signal PREBITCLK : std_logic := '0';	component BUFG	port(		I : in std_logic;		O : out std_logic		);	end component;begin	Bitclk_Bufg: BUFG port map(		I => PREBITCLK,		O => BITCLK		);	Clk_Proc: process(CLK, CLKDIV)			variable PREVDIV : unsigned(15 downto 0) := to_unsigned(0, 16);			variable CURCNT : unsigned(15 downto 0) := to_unsigned(0, 16);		begin			if rising_edge(CLK) then				if not (PREVDIV = CLKDIV) then					CURCNT := to_unsigned(0, 16);					PREVDIV := CLKDIV;				elsif CURCNT = PREVDIV then					CURCNT := to_unsigned(0, 16);					PREBITCLK <= not PREBITCLK;				else					CURCNT := CURCNT + 1;				end if;			end if;		end process;...

I see CLK coming in in my simulation, and I see PREBITCLK being generated. However, the BITCLK output is just 0 no matter how long I run the simulation.

Why is this? Isn't it supposed to just buffer the clock, and thus repeat the input? How can I make it do that?

 

Link to comment
Share on other sites

Can confirm the problem exists. However this now works in simulation for me:

library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.NUMERIC_STD.ALL;library UNISIM;use UNISIM.VComponents.all;entity bufg_test is    Port ( CLK : in  std_logic;   --    CLK runs at 32 MHz           CLKDIV : in unsigned(15 downto 0); -- divide to bit clock           BITCLK : out std_logic    );end bufg_test;architecture Behavioral of bufg_test is   signal PREBITCLK : std_logic := '0';begin   Bitclk_Bufg: BUFG port map(      I => PREBITCLK,      O => BITCLK      );   Clk_Proc: process(CLK, CLKDIV)         variable PREVDIV : unsigned(15 downto 0) := to_unsigned(0, 16);         variable CURCNT : unsigned(15 downto 0) := to_unsigned(0, 16);      begin         if rising_edge(CLK) then            if not (PREVDIV = CLKDIV) then               CURCNT := to_unsigned(0, 16);               PREVDIV := CLKDIV;            elsif CURCNT = PREVDIV then               CURCNT := to_unsigned(0, 16);               PREBITCLK <= not PREBITCLK;            else               CURCNT := CURCNT + 1;            end if;         end if;      end process;end Behavioral;

"USE"ing the library/package that defines BUFG helped.

Link to comment
Share on other sites

Thanks!

 

Neither the book I'm using, nor the Xilinx documentation on the BUFG component, actually mentioned this, so I would have been totally in the dark without this answer.

Actually, to make progress, I replaced the BUFG with a straight wire and lived with the "clock skew" warning, but now I can go back to the right way of doing it!

Link to comment
Share on other sites

Just to add some more information regarding this:
 
The BUFG component is indeed defined as having std_ulogic inputs and outputs. This is taken from the UNISIM library:

--------------------------------------------------------------------------------- Copyright (c) 1995/2004 Xilinx, Inc.-- All Right Reserved.---------------------------------------------------------------------------------   ____  ____--  /   /\/   /-- /___/  \  /    Vendor : Xilinx-- \   \   \/     Version : 11.1--  \   \         Description : Xilinx Functional Simulation Library Component--  /   /                  Global Clock Buffer-- /___/   /\     Filename : BUFG.vhd-- \   \  /  \    Timestamp : Thu Apr  8 10:55:15 PDT 2004--  \___\/\___\---- Revision:--    03/23/04 - Initial version.----- CELL BUFG -----library IEEE;use IEEE.STD_LOGIC_1164.all;entity BUFG is  port(    O : out std_ulogic;    I : in std_ulogic    );end BUFG;

So, I assume that if you do declare your BUFG the same way, it will work without the need to import the UNISIM lib.

Link to comment
Share on other sites

Probably you don't need to care :) But basically, the "std_logic" has a "resolve" function that defines what happens when more than one signal drives the line.

 

There's a PPT from a near-you Univesity that I think explains the difference very well:

 

https://www.cs.auckland.ac.nz/~jmor159/reconfig/ppt/ResolutionFunctions.ppt

 

What I found is that sometimes when your "declaration" and your "implementation" disagree on the types, or if you assign one to another, it may lead to confusion of the simulator. It also does not know about the types (they are not native)....

Link to comment
Share on other sites

Just to add some more information regarding this:

 

The BUFG component is indeed defined as having std_ulogic inputs and outputs. This is taken from the UNISIM library:

....

So, I assume that if you do declare your BUFG the same way, it will work without the need to import the UNISIM lib.

 

I just had to try it - it still has the following warning and doesn't work:

 

WARNING:Simulator:648 - "C:/Users/hamster/Projects/FPGA/help/bufg/work/../bufg_test.vhd" Line 23. Instance bufg is unbound
 
and the log no longer includes the following lines
 
Compiling package vcomponents
Compiling architecture bufg_v of entity BUFG [bufg_default]
 
Making me think it ignores the BUFG completely!
 
 
Link to comment
Share on other sites

It's much like "C": you can place the function prototype, but later you have to link with the library which provides it.

 

Hmm.

Without "pulling" the library, it actually synthesizes fine.

And, in C, if I'm missing a library, I get an obvious link error, not just silent failure. In fact, silent failure is i.m.o. THE WORST in any kind of engineering :-)

Link to comment
Share on other sites

He never mentioned bitfiles:

 

 

Without "pulling" the library, it actually synthesizes fine.

 

He is right, the synthesis process will go along fine. On this case, because the BUFG is indeed an internal FPGA primitive, it will use it and won't complain.

 

If it was not an FPGA primitive, then the synthesis tool will treat it as a "black box", but will be able to synthesize nonetheless. The blocks are assembled together after synthesis, during the translation and mapping process. This is very common when you use pre-synthesized IP cores - they are not available at synthesis time, but later on the system will "link" all together.

Link to comment
Share on other sites

Yes you're right, he never said that, but sometimes people don't really say what they mean. He did say:

 

And, in C, if I'm missing a library, I get an obvious link error, not just silent failure. In fact, silent failure is i.m.o. THE WORST in any kind of engineering :-)

 

The C compiler behaves no differently. If you have a set of C files that reference functions in an external library and you just compile them to object files, you'll get no error either. It's only in the final link step when the compiler wants to create an executable that it'll fail and tell you a library is missing by not being able to resolve the externals. In the case of the Xilinx tools, he never performed the "final link step", hence no error.

 

I don't see what the fuss is here, everything works as it should, nothing fails silently. And the warning messages are there for a reason, not just to fill up screen real estate. No one can blame Xilinx for not putting up enough warning messages :)

Link to comment
Share on other sites

Let me be clear. When I say "synthesize," I actually mean "synthesize, map, place&route, build bit file."

That all works, without pulling any library, when referencing a BUFG.

 

When I run in simulation, it compiles, links, and executes, without giving me any error; the end result is just I get faulty behavior.

This, to me, is a silent failure, which is the worst!

 

By comparison, if I use a C library, include the right header file (or pre-declare the prototype) but don't link with the library, I will get a link error, and it will not get to the "execute" (or even complete the "build excutable") part.

 

Regarding the warning I was talking about: I'm adding the BUFG because I got a warning that my derived clock signal may skew too much. (For that to be true, it would have to split my component into different distance implementation elements, but I guess that might happen if it was a very full design?)

So, I added the BUFG. And got a silent failure in simulation. Which was highly surprising.

 

So, to explain this surprising behavior, my mental model is now something like:

"The hardware synthesis path (all the way to bit file) is a totally separate tool chain than the software emulation path. The default libraries/components included do not perfectly match. And, for certain components, if you forget to include a particular library, you may get a silent failure that executes but doesn't give proper results, not an explicit link error like you'd get in C."

 

So, is there a way I can crank up the warnings/errors to actually get told what's missing in the simulation case?

Link to comment
Share on other sites

The simulator will report something similar to an 'unbound' component.

 

For example, GHDL will report these for a simulation of ZPUino on PPRo, where I have not imported the SigmaDelta sub-components:

../../../zpuino_sigmadelta.vhd:198:1:warning: component instance "chan0" is not bound../../../zpuino_sigmadelta.vhd:71:14:warning: (in default configuration of zpuino_sigmadelta(behave))../../../zpuino_sigmadelta.vhd:207:1:warning: component instance "chan1" is not bound../../../zpuino_sigmadelta.vhd:71:14:warning: (in default configuration of zpuino_sigmadelta(behave))

Not sure about other simulators. I hate visual IDEs, and the isim/ISE simulation is just plain horrible. But I assume you should see something similar to this on the output.

 

Alvie

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.