Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16556 Discussions

Dual Clock FIFO Implementation VHDL

Altera_Forum
Honored Contributor II
4,302 Views

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
  • Error (10821): HDL error at FIFO.vhd(86): can't infer register for "fifo_proc:Head
 

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! 

 

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;
0 Kudos
4 Replies
Altera_Forum
Honored Contributor II
2,219 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
2,219 Views

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: 

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
0 Kudos
Altera_Forum
Honored Contributor II
2,219 Views

 

--- Quote Start ---  

 

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. 

 

--- Quote End ---  

 

 

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).
0 Kudos
Altera_Forum
Honored Contributor II
2,219 Views

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.
0 Kudos
Reply