High Speed Frequency Counter

From Hamsterworks Wiki!

Jump to: navigation, search

This FPGA Project was completed in June 2014, and implemented on the Papilio Pro FPGA board.

Although I have already created a Frequency counter, it only works up to about 100 MHz. Most FPGAs are capable of receiving and processing much faster signals than that, especially on the 'clock' pins. So here is a design that will count over 500 MHz on a fast grade of Spartan 6 FPGA.

Fast freq test.jpg Fast freq console.jpg

The Papilio One on the right is generating the test signal, by using a DCM to multiply the 32 MHz clock by 10x, and then feeding that to the Papilio Pro. The Putty screenshot is the counted frequency - 319,989,082, about 35 ppm of the ideal 320 MHz.

My original frequency counter worked by sampling the test signal rapidly using a DDR register, then counting the number of rising transitions. This required the design to be clocked faster than the incoming signal, lowering the usable range.

The new design uses has the signal under test driving a small 5-bit counter, which is then sampled using the board's 32 MHz clock. The difference between two samples is the number of rising edges seen in the last 31.25 ns. Using the 5-bit counter is enough for signals of up to 31 edges *32 MHz = 992 MHz - way higher than the Spartan 6 FPGA can accept. However, nothing is every that simple. To take the count into the 32MHz clocking domain isn't easy. Even if the count is synchronized using cascaded flip-flops errors will still occur. For example, should the counter be sampled just as "11111" rolls over to "00000", all five sampled bits could be in either state.

The solution to this is pretty cunning. If the binary count is converted to Gray code, and the registers holding the Gray code is then sampled, at most only one bit can be in transition, and either result is equally valid. Once in the 32 MHz domain the count synchronized (to clear up any metastable registers) and then converted back to decimal. The differences between the current count and the last count gives a stream of deltas are then added for the gating time of one second. The total is converted to decimal and then set to a RS232 transmitter to be sent to the host.

The BCD to ASCII conversion is pretty crude - as it doesn't do leading zero suppression, but is enough for now.

Contents

Upgraded to 950 MHz!

By adding the following to the top module, then counting "prescaled" instead of "test_signal" the design should work to about 950MHz:

process(test_signal)
   begin
      if rising_edge(test_signal) then
         prescaled <= not prescaled;
      end if;
   end process;

You will also need the following timing constraints:

NET test_signal_p  LOC = "P51" | IOSTANDARD = LVDS_33 | PERIOD=1.051ns;
NET test_signal_n  LOC = "P50" | IOSTANDARD = LVDS_33;
NET "prescaled"  PERIOD=2.102;

I would also recommend using a clock faster than 32 MHz (e.g. 50MHz or 64MHz) for the slow clocking domain, as 31*32MHz is very close to allowing the gray counter to wrap around, and and there for dropping counts.

By extending the gate time to two seconds you can still keep 1Hz accuracy - see the constant (currently 31,999,999) in the "accumulator" module.

I don't have a reliable source for a signal to test - even using a Spartan 6's serializer can only generate about a 500 MHz clock), so if you do test this can you let me know how you geton.

Source files

All source files can be downloaded here File:Fast freq counter.zip

fast_freq_counter.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Module Name:    fast_freq_counter - Behavioral 
--
-- Description: A fast frequency counter, with RS232 output
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library unisim;
use unisim.vcomponents.all;

entity fast_freq_counter is
    Port ( clk32         : in  STD_LOGIC;
           test_signal_p : in  STD_LOGIC;
           test_signal_n : in  STD_LOGIC;
           tx            : out STD_LOGIC);
end fast_freq_counter;

architecture Behavioral of fast_freq_counter is
   component test_clock port (
      CLK_32in : in     std_logic;
      CLK_32   : out    std_logic;
      CLK_TEST : out    std_logic
   );
   end component;

   COMPONENT input_counter
   PORT(
      test_signal : IN std_logic;          
      gray_count : OUT std_logic_vector(4 downto 0)
      );
   END COMPONENT;

   COMPONENT sampler
   PORT(
      clk : IN std_logic;
      gray_count : IN std_logic_vector(4 downto 0);          
      jump : OUT std_logic_vector(4 downto 0)
      );
   END COMPONENT;

   COMPONENT accumulator
   PORT(
      clk       : IN  std_logic;
      jump      : IN  std_logic_vector(4 downto 0);          
      total     : OUT std_logic_vector(29 downto 0);
      new_total : OUT std_logic
      );
   END COMPONENT;

   COMPONENT binary_bcd
   PORT(
      clk         : IN std_logic;
      new_binary  : IN std_logic;
      binary      : IN std_logic_vector(29 downto 0);          
      d8          : OUT std_logic_vector(3 downto 0);
      d7          : OUT std_logic_vector(3 downto 0);
      d6          : OUT std_logic_vector(3 downto 0);
      d5          : OUT std_logic_vector(3 downto 0);
      d4          : OUT std_logic_vector(3 downto 0);
      d3          : OUT std_logic_vector(3 downto 0);
      d2          : OUT std_logic_vector(3 downto 0);
      d1          : OUT std_logic_vector(3 downto 0);
      d0          : OUT std_logic_vector(3 downto 0);
      new_decimal : OUT std_logic
      );
   END COMPONENT;

   COMPONENT output_uart
   PORT(
      clk : IN std_logic;
      d8 : IN std_logic_vector(3 downto 0);
      d7 : IN std_logic_vector(3 downto 0);
      d6 : IN std_logic_vector(3 downto 0);
      d5 : IN std_logic_vector(3 downto 0);
      d4 : IN std_logic_vector(3 downto 0);
      d3 : IN std_logic_vector(3 downto 0);
      d2 : IN std_logic_vector(3 downto 0);
      d1 : IN std_logic_vector(3 downto 0);
      d0 : IN std_logic_vector(3 downto 0);
      new_decimal : IN std_logic;          
      tx : OUT std_logic
      );
   END COMPONENT;

   signal test_signal                : std_logic;
   signal gray_count                 : std_logic_vector(4 downto 0);          
   signal jump                       : std_logic_vector(4 downto 0);
   signal total                      : std_logic_vector(29 downto 0);
   signal new_total,new_decimal      : std_logic;
   signal d8,d7,d6,d5,d4,d3,d2,d1,d0 : std_logic_vector(3 downto 0);

begin

  -- Input buffer
i_IBUFDS : IBUFDS
   generic map (
      DIFF_TERM => FALSE,
      IBUF_LOW_PWR => TRUE,
      IOSTANDARD => "DEFAULT")
   port map (
      O  => test_signal,
      I  => test_signal_p,
      IB => test_signal_n
   );
   
i_input_counter: input_counter PORT MAP(
      test_signal => test_signal,
      gray_count => gray_count
   );

i_sampler: sampler PORT MAP(
      clk => clk32,
      gray_count => gray_count,
      jump => jump
   );

i_accumulator: accumulator PORT MAP(
      clk       => clk32,
      jump      => jump,
      total     => total,
      new_total => new_total
   );

i_binary_bcd: binary_bcd PORT MAP(
      clk        => clk32,
      new_binary => new_total,
      binary     => total,
      d8         => d8,
      d7         => d7,
      d6         => d6,
      d5         => d5,
      d4         => d4,
      d3         => d3,
      d2         => d2,
      d1         => d1,
      d0         => d0,
      new_decimal => new_decimal
   );

i_output_uart : output_uart PORT MAP(
      clk        => clk32,
      d8         => d8,
      d7         => d7,
      d6         => d6,
      d5         => d5,
      d4         => d4,
      d3         => d3,
      d2         => d2,
      d1         => d1,
      d0         => d0,
      new_decimal => new_decimal,
      tx         => tx
   );

end Behavioral;

input_counter.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Module Name:    input_counter - Behavioral 
--
-- Description: Count rising edges, and output as a Gray count.
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity input_counter is
    Port ( test_signal : in  STD_LOGIC;
           gray_count : out  STD_LOGIC_VECTOR (4 downto 0));
end input_counter;

architecture Behavioral of input_counter is
   signal counter : unsigned(4 downto 0) := (others => '0');
begin

process(test_signal)
   begin
      if rising_edge(test_signal) then
         -- convert the binary counter into the gray encoded output
         case counter is 
            when "00000" => gray_count <= "00000";
            when "00001" => gray_count <= "00001";
            when "00010" => gray_count <= "00011";
            when "00011" => gray_count <= "00010";
            when "00100" => gray_count <= "00110";
            when "00101" => gray_count <= "00111";
            when "00110" => gray_count <= "00101";
            when "00111" => gray_count <= "00100";
            when "01000" => gray_count <= "01100";
            when "01001" => gray_count <= "01101";
            when "01010" => gray_count <= "01111";
            when "01011" => gray_count <= "01110";
            when "01100" => gray_count <= "01010";
            when "01101" => gray_count <= "01011";
            when "01110" => gray_count <= "01001";
            when "01111" => gray_count <= "01000";
            when "10000" => gray_count <= "11000";
            when "10001" => gray_count <= "11001";
            when "10010" => gray_count <= "11011";
            when "10011" => gray_count <= "11010";
            when "10100" => gray_count <= "11110";
            when "10101" => gray_count <= "11111";
            when "10110" => gray_count <= "11101";
            when "10111" => gray_count <= "11100";
            when "11000" => gray_count <= "10100";
            when "11001" => gray_count <= "10101";
            when "11010" => gray_count <= "10111";
            when "11011" => gray_count <= "10110";
            when "11100" => gray_count <= "10010";
            when "11101" => gray_count <= "10011";
            when "11110" => gray_count <= "10001";
            when others  => gray_count <= "10000";
         end case;
         -- advance the counter
         counter <= counter+1;
      end if;
   end process;
end Behavioral;

sampler.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Module Name:    sampler - Behavioral 
--
-- Description: Sample the graycode count and convert back to binary
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

library UNISIM;
use UNISIM.VComponents.all;

entity sampler is
    Port ( clk        : in  STD_LOGIC;
           gray_count : in  STD_LOGIC_VECTOR (4 downto 0);
           jump       : out STD_LOGIC_VECTOR (4 downto 0));
end sampler;

architecture Behavioral of sampler is
	COMPONENT gray_to_bin
	PORT(
		gray : IN std_logic_vector(4 downto 0);          
		binary : OUT std_logic_vector(4 downto 0)
		);
	END COMPONENT;

   signal samples : std_logic_vector(19 downto 0) := (others => '0');
   signal last    : std_logic_vector(4 downto 0);          
   signal recent  : std_logic_vector(4 downto 0);          
begin

gray_to_bin_last: gray_to_bin PORT MAP(
		gray   => samples(19 downto 15),
		binary => last
	);
   
gray_to_bin_recent: gray_to_bin PORT MAP(
		gray   => samples(14 downto 10),
		binary => recent
	);
   

process(clk)
   begin
      if rising_edge(clk) then
         jump <= std_logic_vector(unsigned(recent) - unsigned(last));
         samples <= samples(14 downto 0) & gray_count;
      end if;
   end process;

end Behavioral;

gray_to_bin.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Module Name:    gray_to_bin - Behavioral 
--
-- Description: Convert 5-bit gray code to binary
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity gray_to_bin is
    Port ( gray : in  STD_LOGIC_VECTOR (4 downto 0);
           binary : out  STD_LOGIC_VECTOR (4 downto 0));
end gray_to_bin;

architecture Behavioral of gray_to_bin is

begin

process(gray)
   begin
      case gray is 
         when "00000" => binary <= "00000";
         when "00001" => binary <= "00001";
         when "00011" => binary <= "00010";
         when "00010" => binary <= "00011";
         when "00110" => binary <= "00100";
         when "00111" => binary <= "00101";
         when "00101" => binary <= "00110";
         when "00100" => binary <= "00111";
         when "01100" => binary <= "01000";
         when "01101" => binary <= "01001";
         when "01111" => binary <= "01010";
         when "01110" => binary <= "01011";
         when "01010" => binary <= "01100";
         when "01011" => binary <= "01101";
         when "01001" => binary <= "01110";
         when "01000" => binary <= "01111";
         when "11000" => binary <= "10000";
         when "11001" => binary <= "10001";
         when "11011" => binary <= "10010";
         when "11010" => binary <= "10011";
         when "11110" => binary <= "10100";
         when "11111" => binary <= "10101";
         when "11101" => binary <= "10110";
         when "11100" => binary <= "10111";
         when "10100" => binary <= "11000";
         when "10101" => binary <= "11001";
         when "10111" => binary <= "11010";
         when "10110" => binary <= "11011";
         when "10010" => binary <= "11100";
         when "10011" => binary <= "11101";
         when "10001" => binary <= "11110";
         when others  => binary <= "11111";
      end case;
   end process;

end Behavioral;

accumulator.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Module Name:    accumulator - Behavioral 
--
-- Description: Accumulate 32,000,000 5-bit values
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity accumulator is
    Port ( clk       : in  STD_LOGIC;
           jump      : in  STD_LOGIC_VECTOR (4 downto 0);
           total     : out STD_LOGIC_VECTOR (29 downto 0);
           new_total : out STD_LOGIC);
end accumulator;

architecture Behavioral of accumulator is
   signal i : unsigned(24 downto 0) := (others => '0');
   signal t : unsigned(29 downto 0) := (others => '0');
begin
   
process(clk)
   begin
      if rising_edge(clk) then
         -- has a second past?
         if i = 31999999 then
            -- yep - output the total
            total <= std_logic_vector(t);
            new_total <= '1';
            t <= (others => '0');
            t(4 downto 0) <= unsigned(jump);
            i <= (others => '0');
         else
            -- nope - keep accumulating
            new_total <= '0';
            t <= t + unsigned(jump);
            i <= i + 1;
         end if;
      end if;
   end process;

end Behavioral;

binary_bcd.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Module Name:    binary_bcd - Behavioral 
--
-- Description: Convert 30-bit binary value into into nine decimal digits
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity binary_bcd is
    Port ( clk         : in  STD_LOGIC;
           new_binary  : in  STD_LOGIC;
           binary      : in  STD_LOGIC_VECTOR (29 downto 0);
           d8          : out std_logic_vector(3 downto 0);
           d7          : out std_logic_vector(3 downto 0);
           d6          : out std_logic_vector(3 downto 0);
           d5          : out std_logic_vector(3 downto 0);
           d4          : out std_logic_vector(3 downto 0);
           d3          : out std_logic_vector(3 downto 0);
           d2          : out std_logic_vector(3 downto 0);
           d1          : out std_logic_vector(3 downto 0);
           d0          : out std_logic_vector(3 downto 0);
           new_decimal : out STD_LOGIC);
end binary_bcd;

architecture Behavioral of binary_bcd is
   signal busy : std_logic_vector(binary'high+1 downto 0);
   signal t8   : unsigned(3 downto 0);
   signal t7   : unsigned(3 downto 0);
   signal t6   : unsigned(3 downto 0);
   signal t5   : unsigned(3 downto 0);
   signal t4   : unsigned(3 downto 0);
   signal t3   : unsigned(3 downto 0);
   signal t2   : unsigned(3 downto 0);
   signal t1   : unsigned(3 downto 0);
   signal t0   : unsigned(3 downto 0);
   signal work : STD_LOGIC_VECTOR (binary'high downto 0);
   
begin

process(clk)
   begin
      if rising_edge(clk) then
         case t8 is
            when "0000" => t8 <= "0000";
            when "0001" => t8 <= "0010";
            when "0010" => t8 <= "0100";
            when "0011" => t8 <= "0110";
            when "0100" => t8 <= "1000";
            when "0101" => t8 <= "0000";
            when "0110" => t8 <= "0010";
            when "0111" => t8 <= "0100";
            when "1000" => t8 <= "0110";
            when "1001" => t8 <= "1000";
            when others => t8 <= "0000";
         end case;         
         if t7 > 4 then
            t8(0) <= '1';
         else
            t8(0) <= '0';
         end if;

         case t7 is
            when "0000" => t7 <= "0000";
            when "0001" => t7 <= "0010";
            when "0010" => t7 <= "0100";
            when "0011" => t7 <= "0110";
            when "0100" => t7 <= "1000";
            when "0101" => t7 <= "0000";
            when "0110" => t7 <= "0010";
            when "0111" => t7 <= "0100";
            when "1000" => t7 <= "0110";
            when "1001" => t7 <= "1000";
            when others => t7 <= "0000";
         end case;         
         if t6 > 4 then
            t7(0) <= '1';
         else
            t7(0) <= '0';
         end if;

         case t6 is
            when "0000" => t6 <= "0000";
            when "0001" => t6 <= "0010";
            when "0010" => t6 <= "0100";
            when "0011" => t6 <= "0110";
            when "0100" => t6 <= "1000";
            when "0101" => t6 <= "0000";
            when "0110" => t6 <= "0010";
            when "0111" => t6 <= "0100";
            when "1000" => t6 <= "0110";
            when "1001" => t6 <= "1000";
            when others => t6 <= "0000";
         end case;         
         if t5 > 4 then
            t6(0) <= '1';
         else
            t6(0) <= '0';
         end if;

         case t5 is
            when "0000" => t5 <= "0000";
            when "0001" => t5 <= "0010";
            when "0010" => t5 <= "0100";
            when "0011" => t5 <= "0110";
            when "0100" => t5 <= "1000";
            when "0101" => t5 <= "0000";
            when "0110" => t5 <= "0010";
            when "0111" => t5 <= "0100";
            when "1000" => t5 <= "0110";
            when "1001" => t5 <= "1000";
            when others => t5 <= "0000";
         end case;         
         if t4 > 4 then
            t5(0) <= '1';
         else
            t5(0) <= '0';
         end if;

         case t4 is
            when "0000" => t4 <= "0000";
            when "0001" => t4 <= "0010";
            when "0010" => t4 <= "0100";
            when "0011" => t4 <= "0110";
            when "0100" => t4 <= "1000";
            when "0101" => t4 <= "0000";
            when "0110" => t4 <= "0010";
            when "0111" => t4 <= "0100";
            when "1000" => t4 <= "0110";
            when "1001" => t4 <= "1000";
            when others => t4 <= "0000";
         end case;         
         if t3 > 4 then
            t4(0) <= '1';
         else
            t4(0) <= '0';
         end if;

         case t3 is
            when "0000" => t3 <= "0000";
            when "0001" => t3 <= "0010";
            when "0010" => t3 <= "0100";
            when "0011" => t3 <= "0110";
            when "0100" => t3 <= "1000";
            when "0101" => t3 <= "0000";
            when "0110" => t3 <= "0010";
            when "0111" => t3 <= "0100";
            when "1000" => t3 <= "0110";
            when "1001" => t3 <= "1000";
            when others => t3 <= "0000";
         end case;         
         if t2 > 4 then
            t3(0) <= '1';
         else
            t3(0) <= '0';
         end if;

         case t2 is
            when "0000" => t2 <= "0000";
            when "0001" => t2 <= "0010";
            when "0010" => t2 <= "0100";
            when "0011" => t2 <= "0110";
            when "0100" => t2 <= "1000";
            when "0101" => t2 <= "0000";
            when "0110" => t2 <= "0010";
            when "0111" => t2 <= "0100";
            when "1000" => t2 <= "0110";
            when "1001" => t2 <= "1000";
            when others => t2 <= "0000";
         end case;         
         if t1 > 4 then
            t2(0) <= '1';
         else
            t2(0) <= '0';
         end if;

         case t1 is
            when "0000" => t1 <= "0000";
            when "0001" => t1 <= "0010";
            when "0010" => t1 <= "0100";
            when "0011" => t1 <= "0110";
            when "0100" => t1 <= "1000";
            when "0101" => t1 <= "0000";
            when "0110" => t1 <= "0010";
            when "0111" => t1 <= "0100";
            when "1000" => t1 <= "0110";
            when "1001" => t1 <= "1000";
            when others => t1 <= "0000";
         end case;         
         if t0 > 4 then
            t1(0) <= '1';
         else
            t1(0) <= '0';
         end if;
         

         case t0 is
            when "0000" => t0 <= "0000";
            when "0001" => t0 <= "0010";
            when "0010" => t0 <= "0100";
            when "0011" => t0 <= "0110";
            when "0100" => t0 <= "1000";
            when "0101" => t0 <= "0000";
            when "0110" => t0 <= "0010";
            when "0111" => t0 <= "0100";
            when "1000" => t0 <= "0110";
            when "1001" => t0 <= "1000";
            when others => t0 <= "0000";
         end case;         
         t0(0) <= work(work'high);

         work <= work(work'high-1 downto 0) & '0';
         busy <= '0' & busy(busy'high downto 1);

         new_decimal <= '0';
         if busy(0) = '0' then
            -- start a new conversion
            if new_binary = '1' then
               t8   <= (others => '0');
               t7   <= (others => '0');
               t6   <= (others => '0');
               t5   <= (others => '0');
               t4   <= (others => '0');
               t3   <= (others => '0');
               t2   <= (others => '0');
               t1   <= (others => '0');
               t0   <= (others => '0');
               busy <= (others => '1');
               work <= binary;
            end if;
         else
            if busy(1) = '0' then
               -- conversion complete
               d8 <= std_logic_vector(t8);
               d7 <= std_logic_vector(t7);
               d6 <= std_logic_vector(t6);
               d5 <= std_logic_vector(t5);
               d4 <= std_logic_vector(t4);
               d3 <= std_logic_vector(t3);
               d2 <= std_logic_vector(t2);
               d1 <= std_logic_vector(t1);
               d0 <= std_logic_vector(t0);  
               new_decimal <= '1';
            end if;
         end if;
      end if;
   end process;
end Behavioral;

output_uart.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
--
-- Module Name:    output_uart - Behavioral 
--
-- Description: Send 9 decimal digits out an RS232 port
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity output_uart is
    Port ( clk         : in  STD_LOGIC;
           d8          : in  STD_LOGIC_VECTOR (3 downto 0);
           d7          : in  STD_LOGIC_VECTOR (3 downto 0);
           d6          : in  STD_LOGIC_VECTOR (3 downto 0);
           d5          : in  STD_LOGIC_VECTOR (3 downto 0);
           d4          : in  STD_LOGIC_VECTOR (3 downto 0);
           d3          : in  STD_LOGIC_VECTOR (3 downto 0);
           d2          : in  STD_LOGIC_VECTOR (3 downto 0);
           d1          : in  STD_LOGIC_VECTOR (3 downto 0);
           d0          : in  STD_LOGIC_VECTOR (3 downto 0);
           new_decimal : in  STD_LOGIC;
           tx          : out STD_LOGIC);
end output_uart;

architecture Behavioral of output_uart is
   signal sr : std_logic_vector(128 downto 0) := (others => '1');
   signal count : unsigned(12 downto 0);
begin

process(clk)
   begin
      if rising_edge(clk) then
         if count = 32000000/19200-1 then
            tx <= sr(0);
            sr <= '1' & sr(sr'high downto 1);
            count <= (others => '0');
         else
            count <= count + 1;
         end if;
         
         if new_decimal = '1' then
            sr <=  "000011010" &   -- Carriage return
                  "1000010100" &   -- Line Feed
                  "10011" & d0 & "0" &
                  "10011" & d1 & "0" &
                  "10011" & d2 & "0" &
                  "1001011000" &   -- comma
                  "10011" & d3 & "0" &
                  "10011" & d4 & "0" &
                  "10011" & d5 & "0" &
                  "1001011000" &   -- comma
                  "10011" & d6 & "0" &
                  "10011" & d7 & "0" &
                  "10011" & d8 & "0";
         end if;
      end if;
   end process;
end Behavioral;

fast_freq_counter.ucf

NET clk32 LOC="P94"  | IOSTANDARD=LVTTL | PERIOD=31.25ns;      # CLK
NET TX    LOC="P105" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=SLOW; # TX
NET test_signal_p  LOC = "P51" | IOSTANDARD = LVDS_33 | PERIOD=2.0ns;
NET test_signal_n  LOC = "P50" | IOSTANDARD = LVDS_33;

Test project

Here's the project files used to generate the test signal. It shouldn't really work as the IO bank voltage (Vcco) is 3.3V, but the pins default to LVDS_25. However it does work!

freq_counter_test.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hasmter@snap.net.nz>
-- 
-- Module Name:    freq_counter_test - Behavioral 
--
-- Description: Generate a fast test signal
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library UNISIM;
use UNISIM.VComponents.all;

entity freq_counter_test is
    Port ( clk32 : in  STD_LOGIC;
           test_p : out  STD_LOGIC;
           test_n : out  STD_LOGIC);
end freq_counter_test;

architecture Behavioral of freq_counter_test is
   signal test_sig   : std_logic;
   signal clk_test   : std_logic;
   signal clk_test_n : std_logic;
   signal clk_fb     : std_logic;
begin

OBUFDS_inst : OBUFDS
   generic map (
      IOSTANDARD => "DEFAULT")
   port map (
      O  => test_p,     -- Diff_p output (connect directly to top-level port)
      OB => test_n,   -- Diff_n output (connect directly to top-level port)
      I  => test_sig      -- Buffer input 
   );
 
   ODDR2_inst : ODDR2
   generic map(DDR_ALIGNMENT => "NONE", INIT => '0', SRTYPE => "SYNC") 
   port map (
      Q  => test_sig,   -- 1-bit output data
      C0 => clk_test,   -- 1-bit clock input
      C1 => clk_test_n, -- 1-bit clock input
      CE => '1',        -- 1-bit clock enable input
      D0 => '0',        -- 1-bit data input (associated with C0)
      D1 => '1',        -- 1-bit data input (associated with C1)
      R  => '0',        -- 1-bit reset input
      S  => '0'         -- 1-bit set input
   );
  
   DCM_SP_inst : DCM_SP
   generic map (
      CLKDV_DIVIDE   => 2.0, --  Divide by: 1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5
                             --     7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0
      CLKFX_DIVIDE   => 1,   --  Can be any interger from 1 to 32
      CLKFX_MULTIPLY => 10, --  Can be any integer from 1 to 32
      CLKIN_DIVIDE_BY_2 => FALSE, --  TRUE/FALSE to enable CLKIN divide by two feature
      CLKIN_PERIOD => 31.25, --  Specify period of input clock
      CLKOUT_PHASE_SHIFT => "NONE", --  Specify phase shift of "NONE", "FIXED" or "VARIABLE" 
      CLK_FEEDBACK => "1X",         --  Specify clock feedback of "NONE", "1X" or "2X" 
      DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS", -- "SOURCE_SYNCHRONOUS", "SYSTEM_SYNCHRONOUS" or
                                             --     an integer from 0 to 15
      DLL_FREQUENCY_MODE => "LOW",     -- "HIGH" or "LOW" frequency mode for DLL
      DUTY_CYCLE_CORRECTION => TRUE, --  Duty cycle correction, TRUE or FALSE
      PHASE_SHIFT => 0,        --  Amount of fixed phase shift from -255 to 255
      STARTUP_WAIT => FALSE) --  Delay configuration DONE until DCM_SP LOCK, TRUE/FALSE
   port map (
      CLK0     => CLK_FB,     -- 0 degree DCM CLK ouptput
      CLK180   => open,       -- 180 degree DCM CLK output
      CLK270   => open,       -- 270 degree DCM CLK output
      CLK2X    => open,       -- 2X DCM CLK output
      CLK2X180 => open,       -- 2X, 180 degree DCM CLK out
      CLK90    => open,       -- 90 degree DCM CLK output
      CLKDV    => open,       -- Divided DCM CLK out (CLKDV_DIVIDE)
      CLKFX    => clk_test,   -- DCM CLK synthesis out (M/D)
      CLKFX180 => clk_test_n, -- 180 degree CLK synthesis out
      LOCKED   => open,       -- DCM LOCK status output
      PSDONE   => open,       -- Dynamic phase adjust done output
      STATUS   => open,       -- 8-bit DCM status bits output
      CLKFB    => CLK_FB,     -- DCM clock feedback
      CLKIN    => clk32,      -- Clock input (from IBUFG, BUFG or DCM)
      PSCLK    => '0',        -- Dynamic phase adjust clock input
      PSEN     => '0',        -- Dynamic phase adjust enable input
      PSINCDEC => '0',        -- Dynamic phase adjust increment/decrement
      RST      => '0'         -- DCM asynchronous reset input
   );
end Behavioral;

freq_counter_test.ucf

NET "clk32" PERIOD=31.25 ns | LOC=P89;
NET "test_p" LOC="P15";
NET "test_n" LOC="P16";

Personal tools