Languages/VHDL/Examples/SynchronousBusXilinx

From UIT
Revision as of 10:44, 7 February 2013 by Pim (Talk | contribs)
Jump to: navigation, search

Contents

Synchronous pass through for Xilinx FPGA

Here is an example of a synchronous pass through for a fast bus, implement in a Xilinx Spartan6 using Xilinx tools. This example is inspired by a real industrial design [fixme:reference+link], where we have a 20 bit synchronous bus flowing through an (well filled) FPGA at 150 MHz.

Of course, doing some computing on the data is possible, but this example will emphasis connections outside the FPGA.

               _________
              |         |
clock_input ->|         |-> clock_output
              |  FPGA   |
 data_input =>|         |=> data_output
              |_________|

Here is what our input and output signals looks like:

              __________________________                                  __________________________
             /                          \                                /                          \
clock ...___/                            \______________________________/                            \_______________...
 
      ..._______________________________  ___________________________________________________________  ____________...
                                        \/                                                           \/
                  value(t-1)            |                     value(t)                               |
data  ..._______________________________/\___________________________________________________________/\____________...

We can see the data is changing around the falling edge, and it is really stable on the rising edge.

VHDL entity

Here is a trivial part.

library ieee;
	use ieee.std_logic_1164.all;
	use ieee.numeric_std.all;
 
entity pass_through is
	port
	(
		reset		: in	std_logic;
 
		clock_input	: in	std_logic;
		data_input	: in	std_logic_vector(19 downto 0);
 
		clock_output	: out	std_logic;
		data_output 	: out	std_logic_vector(19 downto 0)
	);
end pass_through;


Synchronous input

[fixme: drawing (rising edge, data, ...]

Principles

  • You MUST use a GCLK pin for clock input, on the same bank as the input data.
  • If possible, try to put all your bus and clock input on the same half-bank <ref name="ug625">Template:Cite web</ref>.
  • Use the D flip-flop integrated into the input PAD
    • This can be achieved by using the "iob" attribute in the VHDL code or by placer options.
  • There is a dedicated clock routing structure named BUFIO2 for sampling input pins.

Single BUFIO VHDL example

Timing constraints - UCF

What if the timing is not met ?

[fixme : explain how to find which flip-flops should be placed manually]

Inside the FPGA

  • Use pipelining
    • Synthesis of fast signals through a FPGA can be difficult (the more the FPGA is full, the more it is difficult), and we're not interested in the delay introduced by our pass through.
  • The synthesizer should not try to replace our pipeline by a shift-register.
 * This can be forced by the VHDL shreg_extract attribute.
  • If the timing between the internal stages and the output is not met, you can try to add stages to the pipelines.
  • Use the DIVCLK clock provided by the BUFIO.

Synchronous output

Principles

  • Use a ODDR2 for clock output
    • The ODDR2 uses a clock and it's counter clock, so if the clock is really fast or has not a 50% duty cycle, use a PLL (DCM) for generating clock and not_clock.
    • We want to change the data on the clock falling edge, so they will be stable on the rising edge, so we invert the clock.
  • Use the D flip-flop integrated into the output PAD

Inverting clock output

Here is how to output a clock from a spartan 6 device. This code has absolutely no hardware cost, since every FPGA output pad has a ODDR2 block inside it.

library ieee;
	use ieee.std_logic_1164.all;
	use ieee.numeric_std.all;
 
library unisim;
	use unisim.vcomponents.all;
 
entity clock_output_inverting_xilinx is
	port
	(
		clock_in			: in	std_logic;
		clock_out			: out	std_logic
	);
end clock_output_inverting_xilinx;
 
architecture rtl of clock_output_inverting_xilinx is
	signal clock_in_not	: std_logic;
begin
 
    -------------------------------------------------------------------------------
    -- Clock forwarding
    --
    -- The oddr2 is used to output a clock, so we can add constraint between this
    -- output and the others audio signals
    -------------------------------------------------------------------------------
    clock_in_not <= not clock_in;
 
    i_oddr : oddr2
    generic map
    (
        ddr_alignment => "c1",    -- sets output alignment to "none", "c0", "c1"
        init          => '0',     -- sets initial state of the q output to '0' or '1'
        srtype        => "async"  -- specifies "sync" or "async" set/reset
    )
    port map
    (
        q  => clock_out,
        c0 => clock_in,
        c1 => clock_in_not,
        ce => '1',
        d0 => '1',
        d1 => '0',
        r  => '0',
        s  => '0'
    );
 
end architecture rtl;

Timing constraints - UCF

Here is the joke, if the data output flip-flops are placed into the PADs and the clock comes from a global clock buffer, there is nothing more to do. Here is the timing constraint that we can use for verifying the skew in the "Timing report"

Timing report example

Possible problems

Over-constrained design

  • possible causes
    • Your input signals are split in two half bank and can't be sampled using the same IOBUF2

References

Template:Reflist template or <references />

Personal tools
Namespaces
Variants
Actions
Navigation
Browse
Toolbox