[FPGA][clocking] Reset a counter on a fast clock domain from a slow clock domain - Page 1
Forum section: electronics / general

author: gauravmp
author_rank: Regular Contributor
timestamp: November 13, 2016, 02:04:32 am
content: Hi all,Is there a way i could run a counter on a fast clock domain (say 100MHz) and a slow clock domain (say 10MHz) and have the rising edge of the 10MHz clock reset a counter which counts up every positive edge on the 100MHz? I'll have both these clocks coming out of PLL which has phase alignment, so they should be synchronous for the most part.Sorry if I've avoided any info. I'm more so asking a general questionThanks.

author: kc8apf
author_rank: Regular Contributor
timestamp: November 13, 2016, 02:24:17 am
content: Sample the 10Mhz clock on every 100Mhz clock. Shift the samples through two registers so you have the current and previous samples cleanly aligned to the 100Mhz clock. Look for the rising edge by comparing the two samples.Sent from my K88 using Tapatalk

author: hamster_nz
author_rank: Super Contributor
timestamp: November 13, 2016, 02:37:24 am
content: You can't directly use 10MHz clock to reset the 100MHz counter. The flipflops can only be sensitive to one clock edge (although the can drive the async set or reset signals)Why not just run everything in the 100MHz domain?The other option is to toggle a flipflop in the slow domain, and watch that from the fast domain - when it changed 9 cycles ago you know it is about to change.

author: ataradov
author_rank: Super Contributor
timestamp: November 13, 2016, 02:52:58 am
content: Quote from: hamster_nz on November 13, 2016, 02:37:24 amWhy not? 10 MHz will be a reset signal, not another counting signal.

author: Someone
author_rank: Super Contributor
timestamp: November 13, 2016, 03:07:58 am
content: Quote from: ataradov on November 13, 2016, 02:52:58 amExactly, when the clocks have a known relationship the timing tools will happily cross signals between them while keeping the timing happy. Though this seems to be rather similar to the previous question:https://www.eevblog.com/forum/microcontrollers/(fpga)(verilog)-how-to-detect-synchronized-edges-of-two-different-signals/

author: hamster_nz
author_rank: Super Contributor
timestamp: November 13, 2016, 04:48:34 am
content: Quote from: ataradov on November 13, 2016, 02:52:58 amThe important bit of the OP's question is:QuoteThat implies this VHDL:Code:if rising_edge(a) thenif rising_edge(b) thencount_out <= counter;counter <= (others =>'0');elsecounter <= counter + 1;end if;end if;You can look at it a few different ways:- Outside of simulation, two different clocks cannot be guaranteed to rise at exactly the same time, so something like this can't be guaranteed to work.- In FPGA fabrics (and in general), the flip-flops have a single clock input. So you can't physically wire both signals to the same flipflop,so code like this can't be made implemented in such a fabric (unless 'a' and 'b' are aliases of the same signal):Code:if rising_edge(a) thenif rising_edge(b) then....end if;end if;- If you connect signals to the async resets of the flipflops then it is level sensitive, not edge sensitive, which is not what the OP wants.I can't see why you would want to do this, but the best way I see would be something like this:Code:-- Might need to be 10 bits long-- simulate to double check!signal shift_reg : std_logic_vector(8 downto 0) := (others => '0');signal toggle : std_logic := '0';process(clk10Mhz)beginif rising_edge(clk10MHz) then-- toggle a single flip-flop so the the fast domain can sync with the 10MHz clocktoggle <= not toggle;end if;end process;process(clk100Mhz)beginif rising_edge(clk100MHz) then-- Detect a clock edge in the 10MHz domain 9 cycles ago.if shift_reg(shift_reg'high) XOR shift_reg(shift_reg'high-1) ='1' then---------------------------------------- Detected the cycle where the 10MHz-- domain's clock edge will be aligned-- with the rising edge of the 100MHz clock-----------------------------------------.... do the tricky stuff that needs to be aligned in both domains.....end if;shift_reg <= shiftreg(shift_reg'high-1 downto 0) & toggle;end if;end process;It will give the impression of the tricky stuff happening on both edges.However, I can see almost no reason WHY you would want to do this - why not just use the 100MHz clock with a 1-in-10 clock enable for the 10MHz logic. The only reason I can see is to maybe allow the fast domain to have its clock gated off when not is use, reducing power.

author: Someone
author_rank: Super Contributor
timestamp: November 13, 2016, 05:31:12 am
content: Quote from: hamster_nz on November 13, 2016, 04:48:34 amYes, and?Code:process (clock100M)beginif rising_edge(clock100M) thenclock_10M_d <= clock10M;if (clock10M = '1' and clock_10M_d = '0') thencounter <= (others =>'0');elsecounter <= counter + 1;end if;end if;end processIts still possible to route clocks onto general logic resources and the timing will be safe, but you won't be sure exactly which side of the rising edge your counter will reset on and it may vary from build to build.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 13, 2016, 05:47:04 am
content: Quote from: Someone on November 13, 2016, 05:31:12 amIf you look a it very closely, or simulate it, your counter is getting incremented one cycle *after* the rising edge of clock10M, as clock10M is already '1'.

author: Someone
author_rank: Super Contributor
timestamp: November 13, 2016, 06:25:53 am
content: Quote from: hamster_nz on November 13, 2016, 05:47:04 amAnd now you're getting into terse arguments about the intent of the OPs vague request. So a sequence of 1,2,3..,8,9,10 vs 0,1,2..,7,8,9 which can be chosen by changing the preload of the counter, they're synchronous clocks so no trickery is needed. But the real answer is to do it all in a single domain, there should be no need for a 10MHz clock domain that is aligned and synchronous to a 100MHz clock domain.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 13, 2016, 08:11:33 am
content: Agreed that it shouldn't be needed, but I have no idea of the OP's requirement either - here is something that resets the 100MHz counter on the rising edge of a synchronous 10MHz clock:Code:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.NUMERIC_STD.ALL;entity mixed_clocks isPort ( clk10Mhz : in STD_LOGIC;clk100Mhz : in STD_LOGIC;counter_out : out STD_LOGIC_VECTOR (4 downto 0));end mixed_clocks;architecture Behavioral of mixed_clocks issignal shift_reg : std_logic_vector(9 downto 0) := (others => '0');signal toggle : std_logic := '0';signal counter : unsigned(4 downto 0) := (others => '0');beginprocess(clk10Mhz)beginif rising_edge(clk10MHz) thentoggle <= not toggle;end if;end process;process(clk100Mhz)beginif rising_edge(clk100MHz) then-- Detect a clock edge in the 10MHz domain 9 cycles ago.if (shift_reg(shift_reg'high) XOR shift_reg(shift_reg'high-1)) = '1' then---------------------------------------- This will run when the 10MHz-- domain's clock edge will be aligned-- with the rising edge of the 100MHz clock-----------------------------------------counter <= (others => '0');counter_out <= std_logic_vector(counter + 1);elsecounter <= counter +1;end if;shift_reg <= shift_reg(shift_reg'high-1 downto 0) & toggle;end if;end process;end Behavioral;And snap of the simulation output is attached.

author: nctnico
author_rank: Super Contributor
timestamp: November 13, 2016, 11:10:41 am
content: Quote from: hamster_nz on November 13, 2016, 02:37:24 amHaving multiple clock domains is a good thing to do in an FPGA because slower logic is easier to route and you'll get better device utilisation. If the clocks come from the same PLL the FPGA routing software will automatically setup timing constraints between the two of them so you don't need extra clock domain crossing logic. A bigger problem will be using the 10MHz clock as an input. The FPGA logic usually doesn't allow this and the solution is to make a flip-flop toggle (output rate 5MHz) and use both edges to reset the counter in the 100MHz domain.