Results 1 to 5 of 5

Thread: Dual Clock FIFO Implementation VHDL

  1. #1
    Join Date
    Jan 2017
    Posts
    2
    Rep Power
    1

    Default Dual Clock FIFO Implementation VHDL

    Hi,

    I'm pretty newto VHDL and I'm trying to implement a Dual Clock Synchronous FIFO but I'm getting loads of error mainly things like:
    • Error (10822): HDL error at FIFO.vhd(57): couldn't implement registers for assignments on this clock edge
    • Error (10820): Netlist error at FIFO.vhd(85): can't infer register for fifo_proc:Head[6] because its behavior depends on the edges of multiple distinct clocks
    • Error (10821): HDL error at FIFO.vhd(86): can't infer register for "fifo_proc:Head[6]" because its behavior does not match any supported register model

    I think it has something to do with trying to run two clocks at the same time.

    Any help resolving this/ pointers in the right direction would be appreciated, I've pasted the code below.

    Thanks in advance!

    Code:
    library IEEE;
    USE IEEE.STD_LOGIC_1164.ALL;
    USE IEEE.NUMERIC_STD.ALL;
    
    entity FIFO is
        Generic (
            constant DATA_WIDTH  : positive := 8;
            constant FIFO_DEPTH    : positive := 256
        );
        Port ( 
    --        CLK     :    in    STD_LOGIC;
            WriteCLK    : in  STD_LOGIC;
            ReadCLK    : in    STD_LOGIC;
            RST        : in  STD_LOGIC;
            WriteEn    : in  STD_LOGIC;
            DataIn    : in  STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
            ReadEn    : in  STD_LOGIC;
            DataOut    : out STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
            Empty    : out STD_LOGIC;
            Full    : out STD_LOGIC
        );
    end FIFO;
    
    architecture Behavioral of FIFO is
    
    begin
    
        -- Memory Pointer Process
        fifo_proc : process (WriteCLK, ReadCLK, RST, ReadEn, WriteEn)
        
        type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0);
        variable Memory : FIFO_Memory;
            
        variable Head : natural range 0 to FIFO_DEPTH - 1;
        variable Tail : natural range 0 to FIFO_DEPTH - 1;
            
        variable Looped : boolean;
    
        --Read_proc : process(ReadCLK)
        begin
            --Reset device on ReadCLK only
            if rising_edge(ReadCLK) then
                if RST = '1' then
                    Head := 0;
                    Tail := 0;
                    
                    Looped := false;
                    
                    Full  <= '0';
                    Empty <= '1';
                elsif ReadEn = '1' then
                    --Read Functionality
                    --if (ReadEn = '1') then
                        if ((Looped = true) or (Head /= Tail)) then
                            -- Update data output
                            DataOut <= Memory(Tail);
                            
                            -- Update Tail pointer as needed
                            if (Tail = FIFO_DEPTH - 1) then
                                Tail := 0;
                                
                                Looped := false;
                            else
                                Tail := Tail + 1;
                            end if;
                        end if;
                end if;
            end if;
                    
            if rising_edge(WriteCLK) then
                if (WriteEn = '1') then
                    if ((Looped = false) or (Head /= Tail)) then
                        -- Write Data to Memory
                        Memory(Head) := DataIn;
                        
                            -- Increment Head pointer as needed
                            if (Head = FIFO_DEPTH - 1) then
                                Head := 0;
                            
                                Looped := true;
                            else
                                Head := Head + 1;
                            end if;
                    end if;
                end if;
            end if;
                    
                    -- Update Empty and Full flags
            if (Head = Tail) then
                if Looped then
                    Full <= '1';
                else
                    Empty <= '1';
                end if;
            else
                Empty    <= '0';
                Full    <= '0';
            end if;
            
        end process;
    end Behavioral;

  2. #2
    Tricky is online now Moderator **Forum Master**
    Join Date
    Oct 2008
    Posts
    5,472
    Rep Power
    1

    Default Re: Dual Clock FIFO Implementation VHDL

    This looks very much like a software approach to digital electronics - it will not work. You cannot have a register that is clocked from two clocks in FPGAs. And reading registers in one clock domain that is registered in another clock domain is very poor practice unless you're doing safe clock domain crossing.

    Altera already provides a dual clock FIFO for free - check out the IP catalog.

  3. #3
    Join Date
    Aug 2015
    Posts
    91
    Rep Power
    1

    Default Re: Dual Clock FIFO Implementation VHDL

    Hi,

    there are a lot of peculiarities about your code; nothing out of the common when you say you're new with VHDL, though.

    The following changes are recommended, some even necessary:
    • use signals instead of variables
    • make sure each signal is only accessed by a single clock
    • only use one clock/reset-sensitive IF per process


    I'm not 100% sure, but I think variables don't map to physical wires or registers, but I could be wrong (I never use variables for the purpose you use it for). Use a variable as a "helper" only, not for things that must be remembered between clocks. All of your variables should map to signals.

    Then, look at "Looped". Its written both on the rising edge of ReadCLK, and on the rising edge of WriteCLK. Maybe other signals have this problem too, I didn't look into it that deep. That's my second point in my above list.

    Then, for the sake of clarity: use one process per clock, i.e. the following pattern always applies:
    Code:
    process(rst, clk) is
    begin
      if(rst = '1') then
        -- reset code
      elsif(rising_edge(clk)) then
        -- synchronous code
      end if;
    end process;
    This is the pattern that you will find almost anywhere, and everybody familiar with VHDL will understand it. Multiple clocks per process just lead to confusion.

    Also, the sensitivity list of your process is wrong. It should contain the reset and the clock, and only those. Your code won't simulate correctly.

    Finally, since you're going to implement a dual-clock FIFO, you need to learn about synchronization between crossing clock domains. I can't see any. Such FIFOs are typically built with gray counters, to avoid problems, and proper synchronization is a must. Just google about "VHDL clock domain crossing". Or just google for dual clock FIFOs and see how they do it. Without that understanding, your FIFO will work perfectly in simulation, and most of the time perfectly in reality, but sometimes just mess up your data.


    Best regards,
    GooGooCluster

  4. #4
    Tricky is online now Moderator **Forum Master**
    Join Date
    Oct 2008
    Posts
    5,472
    Rep Power
    1

    Default Re: Dual Clock FIFO Implementation VHDL

    Quote Originally Posted by GooGooCluster View Post
    I'm not 100% sure, but I think variables don't map to physical wires or registers, but I could be wrong (I never use variables for the purpose you use it for). Use a variable as a "helper" only, not for things that must be remembered between clocks. All of your variables should map to signals.
    Variables can map to anything that signals can map to. But it can be less obvious what that may be. Hence why it is highly recommended that you use signals for everything. There is nothing you cant do with a signal (for logic implementation).

  5. #5
    Join Date
    Jan 2017
    Posts
    2
    Rep Power
    1

    Default Re: Dual Clock FIFO Implementation VHDL

    Thanks for the information guys, sorry for the late reply.

    All of this is very useful, I'll see what I can do with it.

Similar Threads

  1. Linux -> mSGDMA -> Dual Clock FIFO
    By tomek160191 in forum SoC Device Discussion
    Replies: 1
    Last Post: December 27th, 2016, 09:55 AM
  2. Slack issue in dual clock FIFO
    By hatter in forum Quartus II and EDA Tools Discussion
    Replies: 9
    Last Post: March 8th, 2015, 07:51 AM
  3. Replies: 7
    Last Post: June 8th, 2014, 06:14 PM
  4. Dual-Clock FIFO (DCFIFO) not behaving
    By hygren in forum Quartus II and EDA Tools Discussion
    Replies: 3
    Last Post: February 6th, 2012, 09:31 PM
  5. Dual-Clock FIFO with clear in Cyclone III
    By Jonas Lindén in forum FPGA, Hardcopy, and CPLD Discussion
    Replies: 2
    Last Post: September 23rd, 2008, 07:06 AM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •