top of page
Writer's pictureAdam Taylor

MicroZed Chronicles: Accessing the Configuration Clock

Normally, we clock the logic within our FPGA design using clocks either provided externally or generated internally using MMCMs, PLLs, or other logic structures, e.g., counters. Using these internal or external clocks ensures we know the frequency, tolerance, and, of course, jitter.


However, there are instances when we might want to use the configuration clock in our designs. The configuration clock provides the clock for the configuration of the device when operating in master mode, unless an external configuration clock is provided.

The configuration clock is generated internally within the FPGA using a ring oscillator. As such, it is not really suitable for most applications, as they require a stable clock and a known clock frequency.


The nominal frequency of the clock is stated within the relevant datasheet. For the Spartan 7, it is 100MHz; however, it has a tolerance of ±50%. The configuration clock frequency will vary with process, voltage, and temperature. As such, we cannot use it for things where we need to know the exact frequency.


Normally, this configuration clock is not accessible to the user logic design; however, if desired, we can access the configuration clock in the user logic.


We access this configuration clock in the user logic by using the STARTUP2E primitive in 7-series devices and STARTUPE3 primitives in the UltraScale and UltraScale+ families.

If we want to instantiate the primitive within our FPGA, we can use the template provided by the language templates in the Vivado editor or those defined within the family's library guides (e.g., UG953 for 7-series or UG974 for UltraScale or UltraScale+ families).

STARTUPE2_inst : STARTUPE2
   generic map (
      PROG_USR => "FALSE",  -- Activate program event security feature. Requires encrypted bitstreams.
      SIM_CCLK_FREQ => 0.0  -- Set the Configuration Clock Frequency(ns) for simulation.
   )
   port map (
      CFGCLK => CFGCLK,       -- 1-bit output: Configuration main clock output
      CFGMCLK => CFGMCLK,     -- 1-bit output: Configuration internal oscillator clock output
      EOS => EOS,             -- 1-bit output: Active high output signal indicating the End Of Startup.
      PREQ => PREQ,           -- 1-bit output: PROGRAM request to fabric output
      CLK => CLK,             -- 1-bit input: User start-up clock input
      GSR => GSR,             -- 1-bit input: Global Set/Reset input (GSR cannot be used for the port name)
      GTS => GTS,             -- 1-bit input: Global 3-state input (GTS cannot be used for the port name)
      KEYCLEARB => KEYCLEARB, -- 1-bit input: Clear AES Decrypter Key input from Battery-Backed RAM (BBRAM)
      PACK => PACK,           -- 1-bit input: PROGRAM acknowledge input
      USRCCLKO => USRCCLKO,   -- 1-bit input: User CCLK input
                              -- For Zynq-7000 devices, this input must be tied to GND
      USRCCLKTS => USRCCLKTS, -- 1-bit input: User CCLK 3-state enable input
                              -- For Zynq-7000 devices, this input must be tied to VCC
      USRDONEO => USRDONEO,   -- 1-bit input: User DONE pin output control
      USRDONETS => USRDONETS  -- 1-bit input: User DONE 3-state enable output
   );

Having accessed the configuration clock, what is it useful for? One of the things I have used it for in previous projects has been to help me select between primary and redundant clocks being input into a device.


In this instance, I used the configuration clock to clock a glitch filter on the clock selection input to ensure there were no glitches or noise on the clock selection input.


I also used it to generate a reset signal, which can be later synchronised with the selected clock to reset the downstream logic.


This approach ensures the glitch filter is being clocked independently and will not be impacted by changes in the clock.


We can also use the configuration clock to detect if one of the clocks is missing or stopped. However, we will not be able to easily or accurately determine the frequency of the clock being monitored.


It is possible, however, to detect whether the monitored clocks are incrementing and have not stopped.


The RTL to create the above system can be seen below:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library UNISIM;
use UNISIM.VComponents.all;

entity int_ext_clk is
Port (
	clk_ext : in std_logic;
	clk_select : in std_logic;
	led_sel : out std_logic; 
	led_clk : out std_logic;
	clk_op  : out std_logic
     );
end int_ext_clk; 

architecture Behavioral of int_ext_clk is
    signal s_delay_line   : std_ulogic_vector(7 downto 0);
    signal s_delay_and    : std_ulogic;
    signal s_delay_nor    : std_ulogic;
    signal s_output_clean : std_ulogic;
    signal s_cclk         : std_ulogic;
begin
 STARTUPE2_inst : STARTUPE2
   generic map (
      PROG_USR => "FALSE",  
      SIM_CCLK_FREQ => 10.0  
   )
   port map (
      CFGCLK => open,      
      CFGMCLK => s_cclk,    
      EOS => open,          
      PREQ => open,       
      CLK => '0',           
      GSR => '0',             
      GTS => '0',           
      KEYCLEARB => '0',   
      PACK => '0',         
      USRCCLKO => '0',               
      USRCCLKTS => '0',                         
	 USRDONEO => '1',   -- 1-bit input: User DONE pin output control
	 USRDONETS => '1'  -- 1-bit input: User DONE 3-state enable outpu
);
   BUFGMUX_inst : BUFGMUX
	port map (
		O => clk_op,   -- 1-bit output: Clock output
		I0 => s_cclk, -- 1-bit input: Clock input (S=0)
		I1 => clk_ext, -- 1-bit input: Clock input (S=1)
		S => s_output_clean    -- 1-bit input: Clock select
);

--*** switch interface 
    --Delay disctete using delay line
    synchroniser_process : process (s_cclk) begin
        if rising_edge(s_cclk) then
            s_delay_line <= s_delay_line(6 downto 0) &                           		   
            clk_select;
		end if;
	end process;

    --Generate AND and NOR of delay line bits
    s_delay_and <= '1' when to_01(s_delay_line) = 
                            (s_delay_line'range => '1') else '0';
    s_delay_nor <= '1' when to_01(s_delay_line) = 
                            (s_delay_line'range => '0') else '0';
 
   --Set discrete based on delay line
    output_process : process (s_cclk) begin
        if rising_edge(s_cclk) then
            if s_delay_nor = '1' then
                s_output_clean <= '0';
            elsif s_delay_and = '1' then
                s_output_clean <= '1';
            end if;
        end if;
    end process;

led_sel <= s_output_clean;
end Behavioral;

While not one of the more often-used approaches, it can be useful to understand how we can access the configuration clock and a few of the approaches we might want to use it for.


Workshops and Webinars


If you enjoyed the blog why not take a look at the free webinars, workshops and training courses we have created over the years. Highlights include



Boards

Get an Adiuvo development board



Embedded System Book   


Do you want to know more about designing embedded systems from scratch? Check out our book on creating embedded systems. This book will walk you through all the stages of requirements, architecture, component selection, schematics, layout, and FPGA / software design. We designed and manufactured the board at the heart of the book! The schematics and layout are available in Altium here   Learn more about the board (see previous blogs on Bring up, DDR validation, USB, Sensors) and view the schematics here.



0 comments

Recent Posts

See All

留言


bottom of page