I had to put a frequency meter into an FPGA and used the following method, which you alluded to in your question...
You have a logic clock, CLK, and a clock to be measured, CLK_MEAS.
- Reduce CLK_MEAS using a divider counter. This is the only logic not clocked by CLK.
- Bring the divider's MSB into the CLK domain
- Detect MSB rising edges.
- Count the number of CLKs between MSB edges.
Below is some example VHDL of the sort of thing I did. Mine had to measure 40..430 MHz. The example uses a 4-bit divider and 8-bit result but just to illustrate the idea. You can choose whatever bit-sizes are necessary.
------------------------------------------------------------------------------
-- pResetMEAS. Produce the CLK_MEAS domain reset.
------------------------------------------------------------------------------
pFMEASReset : process(RST, CLK_MEAS) is
begin
if (RST = '1') then
rstMeasSR <= "111";
elsif rising_edge(CLK_MEAS) then
rstMeasSR <= rstMeasSR( 1 downto 0) & '0';
end if;
end process pFMEASReset;
rstMeas <= rstMeasSR(2);
------------------------------------------------------------------------------
-- pPrescaler. Divide the CLK_MEAS frequency down by 16.
------------------------------------------------------------------------------
pPrescaler : process(rstMeas, CLK_MEAS) is
begin
if (rstMeas = '1') then
clkMeasDivCtr <= "0000";
elsif rising_edge(CLK_MEAS) then
clkMeasDivCtr <= clkMeasDivCtr + "0001";
end if;
end process pPrescaler;
clkMeasDivCtrMSB <= clkMeasDivCtr(3);
------------------------------------------------------------------------------
-- pFreqCounter. Measure CLKs between divided FMEAS rising edges.
------------------------------------------------------------------------------
pFreqCounter : process(RST, CLK) is
begin
if (RST = '1') then
divCtrMSBSR <= "01010";
divCtrMSBRise <= '0';
freqCtr <= X"00";
freqCount <= freqCtr;
freqCountValid <= divCtrMSBRise;
elsif rising_edge(CLK) then
--------------------------------------------------------------------------
-- Bring the divider counter's MSB into the CLK domain.
--------------------------------------------------------------------------
divCtrMSBSR <= divCtrMSBSR( 3 downto 0) & clkMeasDivCtrMSB;
if (divCtrMSBSR( 4 downto 1) = "0011") then
divCtrMSBRise <= '1';
else
divCtrMSBRise <= '0';
end if;
--------------------------------------------------------------------------
-- Count CLKs between the divider MSB's rising edges, stopping at 255.
--------------------------------------------------------------------------
if (divCtrMSBRise = '1') then
freqCtr <= X"00";
freqCount <= freqCtr;
elsif (freqCtr = X"FF") then
freqCount <= freqCtr;
else
freqCtr <= freqCtr + X"01";
end if;
-- Indicate when a new result is available.
freqCountValid <= divCtrMSBRise;
end if;
end process pFreqCounter;