Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20873 Discussions

Crossing clock domains?

Altera_Forum
Honored Contributor II
1,459 Views

I'm just learning about FPGAs (using VHDL) and have encountered metastability problems which I'm fairly certain are due to crossing clock domains. 

 

I have made a VGA controller (on a DE1 Cyclone II board) and am trying to interface it to an old 8 bit micro (directly into its memory map), and it almost works. 

 

My 8 bit micro is running at ~0.9MHz, and the VGA controller is running at 108MHz. When in 'standalone' test mode, the VGA controller is great, but when connected to the micro, I get flickering and other weird effects. 

 

Currently, I have the 108MHz FPGA clock running state machines etc, with the CPU clock directly interacting with them to affect state transitions. I believe this is a big crime (forgive me, I'm still learning)! (Debugging with a logic analyser shows things like the state machines ending up in weird and unexpected states) 

 

So, to solve the problem of crossing clock domains, would it be OK to just pass the micro's CPU clock signals through a couple of clocked (using the 108MHz clock) registers? I'd end up with ~20ns delay, but to a 1MHz CPU that's not going to be a problem :-) Would that reduce the metastability problems substantially? 

 

I don't think I need anything more complicated, such as proper 'handshaking' 

 

I don't think I'll need to synchronise the micro's address/data bus etc because they're all guaranteed to be set up before the CPU clock anyway.
0 Kudos
7 Replies
Altera_Forum
Honored Contributor II
492 Views

 

--- Quote Start ---  

I'm just learning about FPGAs (using VHDL) and have encountered metastability problems which I'm fairly certain are due to crossing clock domains. 

--- Quote End ---  

 

 

You are already ahead of the game if you at least know about metastability! Good job! 

 

 

--- Quote Start ---  

 

Currently, I have the 108MHz FPGA clock running state machines etc, with the CPU clock directly interacting with them to affect state transitions. I believe this is a big crime (forgive me, I'm still learning)! (Debugging with a logic analyser shows things like the state machines ending up in weird and unexpected states) 

 

--- Quote End ---  

 

 

I'll forgive you this time :) 

 

 

--- Quote Start ---  

 

So, to solve the problem of crossing clock domains, would it be OK to just pass the micro's CPU clock signals through a couple of clocked (using the 108MHz clock) registers? I'd end up with ~20ns delay, but to a 1MHz CPU that's not going to be a problem :-) Would that reduce the metastability problems substantially? 

 

I don't think I need anything more complicated, such as proper 'handshaking' 

 

--- Quote End ---  

 

 

It depends on what signals are crossing, and how the are used. 

 

If you just have say one "Enable" signal, a single double or triple register synchronizer may be all you need. 

 

In general if you have and address/data bus, the full bus needs to be synchronized. This can be through a dual port/dual clock fifo, or through special a special handshake where you register the bus in one domain, and send a single signal to the other domain that registers the bus in the other domain. 

 

 

--- Quote Start ---  

 

I don't think I'll need to synchronise the micro's address/data bus etc because they're all guaranteed to be set up before the CPU clock anyway. 

--- Quote End ---  

 

 

It depends on how it is used. If the bus goes to the other domain the individual bits can be interpreted (registered) at different high speed clocks, unless the "Enable" signal is properly synchronized. 

 

Pete
0 Kudos
Altera_Forum
Honored Contributor II
492 Views

OK. It's a 6809E processor. I know that, for instance, on the falling edge of the 'Q' clock, the Address bus has been set up for around 500ns and the Data bus has been set up for around 200ns. The hold time is going to be around 200-300ns. 

 

So, if I want the FPGA to read the address/data bus, it looks like I could just clock them into registers on the falling edge of the synchronised Q clock. The address/data bus (and R/W etc) should be very stable by that moment, and not going to change for a while, so they shouldn't need more synchronisation. 

 

If the CPU was going at a similar speed to the FPGA clock, then I can see that I may need more synchronisation, but because the speeds are so vastly different, I'm not sure it's needed. Also if I was trying to squeeze every ns out of it by running close to the timing limits of the 6809, but I'm not. 

 

(It's not a timing problem to synchronise them, just using lots of registers unnecessarily AFAICS).
0 Kudos
Altera_Forum
Honored Contributor II
492 Views

Yes. Based on your description, you can synchronize your Q clock signal and generate an "Enable" pulse in the fast clock domain. This should be sufficient because you CPU hold time is very long. and less than the time required to synchronize the Q Clock and detect an edge. 

 

If the address/data hold time was < than the time required to synchronize the control signal, then you need to register the bus in the slow domain first, so you can ensure it is stable. 

 

Pete
0 Kudos
Altera_Forum
Honored Contributor II
492 Views

Thanks. That's what I thought - I just wanted to check I was understanding the problem reasonably correctly. I'm not entirely sure how to solve the problem in all cases, but I think I've got it for this particular case. 

 

I've just got to try and rework my design to be less combinational and more synchronous against a single clock (hopefully without having to start from scratch) :-)
0 Kudos
Altera_Forum
Honored Contributor II
492 Views

The easiest way to fix this would be to run the CPU at 108MHz, but generate a 0.9Mhz enable signal, so that the CPU is only active at the correct clock speed. Then there is only 1 clock domain and there are no clock domain crossing issues.

0 Kudos
Altera_Forum
Honored Contributor II
492 Views

I had thought of that, but the CPU clock is generated elsewhere and that's not easy/possible to change, and it may vary - it might actually be 0.888625 MHz, or it might be 0.894886 MHz depending on the original computer model (or it may occasionally be double that if running in 'fast' mode), so I can't even easily generate a 'fake' clock in the FPGA and sync it with the actual clock. 

 

(I'm not building my own 6809 computer with an FPGA attached - I'm using the FPGA as a plug-in peripheral for an existing 6809-based 1980's computer (Dragon 32/64/Tandy Coco))
0 Kudos
Altera_Forum
Honored Contributor II
492 Views

Ok - thats fair enough 

Because the CPU clock is so much slower than the FPGA clock, you could easily just sample the CPU clock and detect rising edges as enables in the FPGA clock domain (as anakha has already suggested). 

 

 

signal cpu_clk_resync : std_logic_vector(3 downto 0); signal cpu_clk_en : std_logic; process(fpga_clk) begin if rising_edge(fpga_clk) then cpu_clk_resync <= cpu_clk_resync(2 downto 0) & cpu_clk; if cpu_clk_resync(2) = '1' and cpu_clk_resync(3) = '0' and cpu_clk_resync(1) = '1' -- ensure it really is stable and not metastable/bouncing then cpu_clk_en <= '1'; end if; end if; end process;  

 

Then you can safely use any properly synchronised data
0 Kudos
Reply