I am using coregen to generate FIFOs for my design and get typically 77LUTs and 38Registers for a 1 BLOCK RAM FIFO. Seems like a lot. I remember using Cypress parts and all the addressing and such for a FIFO was already pretty much incorporated into the Channel RAM, no logic was used outside the Channel RAM to do the basic RAM functions including FIFO. Am I doing Xilinx right? Is there some primitive I should be using instead? Brad Smallridge b r a d @ a i v i s i o n . c o m
Xilinx FIFO
Started by ●December 15, 2004
Reply by ●December 15, 20042004-12-15
In the new Virtex-4 devices, we incorporate a FIFO controller in every BlockRAM,so the controller is free, and it can handle asynchronous clocks at up to 500 MHz. The high logic count for the controller that you quoted may be due to elaborate design tricks to cope with fast asynchronous clocks, and the need to generate a reliable EMPTY and FULL signal, even at very high speed. And perhaps also a partial FULL/EMPTY output. That requires duplicated Binary and Gray counters with sophisticated comparators and special precautions against metastability problems (All of which we did in the hidden controller in Virtex-4). If you are not running so fast, some of this can be eliminated in your Virtex-II or Spartan design, but you have to be careful. Asynchronous clocks can bite you, unless you really know what you are doing... Peter Alfke
Reply by ●December 15, 20042004-12-15
No, as far as I know I picked the Synchronous option. And there seems to be no way to elliminate the Empty and Full flag outputs, which I don't think I will be using, left them open in the instantiation. There also is no relative placing of the support counters, either with respect to each other or close to the RAM block. Nice to know that the Virtex has some of this stuff built in. Brad
Reply by ●December 15, 20042004-12-15
Brad, if your FIFO uses one common clock for write and read, and you really do not care about FULL or EMPTY (because your system design takes care of or avoids that situation), then just ignore the core generator and simply hook two counters to the two address ports, and declare one port the write input side, and the other one the read output side. That means you need one slice per two address bits, and totally exactly as many slices as your addressing is wide, i.e. 16 max. Most of the complexity (and trouble and frustration...) of a FIFO design is due to the asynchronous nature of the two clocks, while reliable EMPTY/FULL signals must be decoded. Peter Alfke
Reply by ●December 16, 20042004-12-16
I just read the V4 user guide, UG070. It seems the really tricky bit is making sure the FULL signal goes high when the FIFO is full. Not one write clock cycle later. ;-) Cheers, Syms. "Peter" <peter@xilinx.com> wrote in message news:1103155097.582753.217240@c13g2000cwb.googlegroups.com...> Most of the complexity (and trouble and frustration...) of a FIFO > design is due to the asynchronous nature of the two clocks, while > reliable EMPTY/FULL signals must be decoded. > Peter Alfke >
Reply by ●December 17, 20042004-12-17
Symon wrote:> I just read the V4 user guide, UG070. It seems the really tricky bitis> making sure the FULL signal goes high when the FIFO is full. Not onewrite> clock cycle later. ;-) > Cheers, Syms. >That's unfortunately true. Came too late for me to catch... The user should select the almost FULL output instead. FULL is not as critical a signal as EMPTY. A well-designed FIFO system should never go FULL, and the exact "full-ness" level is not so important. Hardly anybody cares whether the FIFO can hold 1024, 1023 or 1020 entries. But the user often really wants to empty the FIFO content completely. That's why reliable EMPTY decoding is more important than exact FULL decoding. Nevertheless, it's a cosmetic flaw that will be fixed next time around. Peter Alfke (FIFO is my middle name)
Reply by ●December 20, 20042004-12-20
Thanks Peter, I took your advice and I attached the code below. It's for a 9 bit input, 9 bit output, 2K deep FIFO. Seems to simulate OK.> Brad, if your FIFO uses one common clock for write and read, and you > really do not care about FULL or EMPTY (because your system design > takes care of or avoids that situation), then just ignore the core > generator and simply hook two counters to the two address ports, and > declare one port the write input side, and the other one the read > output side. That means you need one slice per two address bits, and > totally exactly as many slices as your addressing is wide, i.e. 16 max. > > Most of the complexity (and trouble and frustration...) of a FIFO > design is due to the asynchronous nature of the two clocks, while > reliable EMPTY/FULL signals must be decoded. > Peter Alfkelibrary IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; library UNISIM; use UNISIM.VComponents.all; entity fifo9 is port( clk : in std_logic; reset : in std_logic; fifowren : in std_logic; fiforden : in std_logic; fifoin : in std_logic_vector(8 downto 0); fifoout: out std_logic_vector(8 downto 0) ); end fifo9; architecture Behavioral of fifo9 is component RAMB16_S9_S9 generic ( WRITE_MODE_A : string := "READ_FIRST"; WRITE_MODE_B : string := "READ_FIRST"; INIT_A : bit_vector := X"000"; SRVAL_A : bit_vector := X"000"; INIT_B : bit_vector := X"000"; SRVAL_B : bit_vector := X"000"; INITP_00 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INITP_01 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INITP_02 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INITP_03 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INITP_04 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INITP_05 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INITP_06 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INITP_07 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_00 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_01 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_02 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_03 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_04 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_05 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_06 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_07 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_08 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_09 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_0A : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_0B : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_0C : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_0D : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_0E : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_0F : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_10 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_11 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_12 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_13 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_14 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_15 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_16 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_17 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_18 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_19 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_1A : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_1B : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_1C : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_1D : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_1E : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_1F : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_20 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_21 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_22 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_23 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_24 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_25 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_26 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_27 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_28 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_29 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_2A : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_2B : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_2C : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_2D : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_2E : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_2F : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_30 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_31 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_32 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_33 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_34 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_35 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_36 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_37 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_38 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_39 : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_3A : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_3B : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_3C : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_3D : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_3E : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000"; INIT_3F : bit_vector(255 downto 0) := X"0000000000000000000000000000000000000000000000000000000000000000" ); port (DIA : in STD_LOGIC_VECTOR (7 downto 0); DIB : in STD_LOGIC_VECTOR (7 downto 0); DIPA : in STD_LOGIC_VECTOR (0 downto 0); DIPB : in STD_LOGIC_VECTOR (0 downto 0); ENA : in STD_logic; ENB : in STD_logic; WEA : in STD_logic; WEB : in STD_logic; SSRA : in STD_logic; SSRB : in STD_logic; CLKA : in STD_logic; CLKB : in STD_logic; ADDRA : in STD_LOGIC_VECTOR (10 downto 0); ADDRB : in STD_LOGIC_VECTOR (10 downto 0); DOA : out STD_LOGIC_VECTOR (7 downto 0); DOB : out STD_LOGIC_VECTOR (7 downto 0); DOPA : out STD_LOGIC_VECTOR (0 downto 0); DOPB : out STD_LOGIC_VECTOR (0 downto 0) ); end component; signal fifowraddr : std_logic_vector(10 downto 0); signal fifordaddr : std_logic_vector(10 downto 0); begin bram00 : RAMB16_S9_S9 port map ( DIA => fifoin(7 downto 0), DIB => (others=>'0'), DIPA => fifoin(8 downto 8), DIPB => (others=>'0'), ENA => '1', ENB => '1', WEA => fifowren, WEB => '0', SSRA => '0', SSRB => '0', CLKA => clk, CLKB => clk, ADDRA => fifowraddr, ADDRB => fifordaddr, DOA => open, DOB => fifoout(7 downto 0), DOPA => open, DOPB => fifoout(8 downto 8) ); fifocnt: process(clk) begin if(clk'event and clk='1') then if(reset='1') then fifowraddr<=(others=>'0'); fifordaddr<=(others=>'0'); else if(fifowren='1') then fifowraddr<=fifowraddr+1; end if; if(fiforden='1') then fifordaddr<=fifordaddr+1; end if; end if; end if; end process; end Behavioral;