SURF  1.0
SyncClockFreq.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : SyncClockFreq.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2014-04-17
5 -- Last update: 2014-04-17
6 -------------------------------------------------------------------------------
7 -- Description: This module measures the frequency of an input clock
8 -- with respect to a stable reference clock.
9 -------------------------------------------------------------------------------
10 -- This file is part of 'SLAC Firmware Standard Library'.
11 -- It is subject to the license terms in the LICENSE.txt file found in the
12 -- top-level directory of this distribution and at:
13 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
14 -- No part of 'SLAC Firmware Standard Library', including this file,
15 -- may be copied, modified, propagated, or distributed except according to
16 -- the terms contained in the LICENSE.txt file.
17 -------------------------------------------------------------------------------
18 
19 library ieee;
20 use ieee.std_logic_1164.all;
21 use ieee.std_logic_unsigned.all;
22 use ieee.std_logic_arith.all;
23 
24 use work.StdRtlPkg.all;
25 
26 --! @see entity
27  --! @ingroup base_sync
28 entity SyncClockFreq is
29  generic (
30  TPD_G : time := 1 ns; -- Simulation FF output delay
31  USE_DSP48_G : string := "no"; -- "no" for no DSP48 implementation, "yes" to use DSP48 slices
32  REF_CLK_FREQ_G : real := 200.0E+6;-- Reference Clock frequency, units of Hz
33  REFRESH_RATE_G : real := 1.0E+3; -- Refresh rate, units of Hz
34  CLK_LOWER_LIMIT_G : real := 159.0E+6;-- Lower Limit for clock lock, units of Hz
35  CLK_UPPER_LIMIT_G : real := 161.0E+6;-- Lower Limit for clock lock, units of Hz
36  CNT_WIDTH_G : positive := 32); -- Counters' width
37  port (
38  -- Frequency Measurement and Monitoring Outputs (locClk domain)
39  freqOut : out slv(CNT_WIDTH_G-1 downto 0);-- units of Hz
40  freqUpdated : out sl;
41  locked : out sl; -- '1' CLK_LOWER_LIMIT_G < clkIn < CLK_UPPER_LIMIT_G
42  tooFast : out sl; -- '1' when clkIn > CLK_UPPER_LIMIT_G
43  tooSlow : out sl; -- '1' when clkIn < CLK_LOWER_LIMIT_G
44  -- Clocks
45  clkIn : in sl; -- Input clock to measure
46  locClk : in sl; -- System clock
47  refClk : in sl);-- Stable Reference Clock
48 end SyncClockFreq;
49 
50 architecture rtl of SyncClockFreq is
51 
52  constant REFRESH_MAX_CNT_C : natural := getTimeRatio(REF_CLK_FREQ_G, REFRESH_RATE_G);
53  constant CLK_LOWER_LIMIT_C : natural := getTimeRatio(CLK_LOWER_LIMIT_G, 1.0E+0); -- lower limit
54  constant CLK_UPPER_LIMIT_C : natural := getTimeRatio(CLK_UPPER_LIMIT_G, 1.0E+0); -- upper limit
55 
56  signal updated,
57  lockedDet,
58  tooFastDet,
59  tooSlowDet,
60  wrEn,
61  doneAccum : sl;
62 
63  signal freqHertz,
64  cntIn,
65  cntOut,
66  cntStable,
67  cntAccum,
68  accum,
69  cntOutDly,
70  diffCnt : slv(CNT_WIDTH_G-1 downto 0);
71 
72  -- Attribute for XST
73  attribute use_dsp48 : string;
74  attribute use_dsp48 of cntIn : signal is USE_DSP48_G;
75  attribute use_dsp48 of cntStable : signal is USE_DSP48_G;
76  attribute use_dsp48 of cntAccum : signal is USE_DSP48_G;
77  attribute use_dsp48 of accum : signal is USE_DSP48_G;
78  attribute use_dsp48 of diffCnt : signal is USE_DSP48_G;
79  attribute use_dsp48 of freqHertz : signal is USE_DSP48_G;
80 
81 begin
82 
83  freqOut <= freqHertz;
84  freqUpdated <= updated;
85  locked <= lockedDet;
86  tooFast <= tooFastDet;
87  tooSlow <= tooSlowDet;
88 
89  ---------------------------
90  -- Free Running Counter
91  ---------------------------
92  process(clkIn)
93  begin
94  if rising_edge(clkIn) then
95  -- Increment the counter
96  cntIn <= cntIn + 1 after TPD_G;
97  end if;
98  end process;
99 
100  ------------------------------------------------
101  -- Calculate the frequency of the input clock
102  ------------------------------------------------
103  SynchronizerFifo_In : entity work.SynchronizerFifo
104  generic map (
105  TPD_G => TPD_G,
107  port map (
108  --Write Ports (wr_clk domain)
109  wr_clk => clkIn,
110  din => cntIn,
111  --Read Ports (rd_clk domain)
112  rd_clk => refClk,
113  dout => cntOut);
114 
115  process(refClk)
116  begin
117  if rising_edge(refClk) then
118  -- Reset the strobe
119  wrEn <= '0' after TPD_G;
120  -- Increment the Counter
121  cntStable <= cntStable + 1 after TPD_G;
122  -- Check if we have reached the targeted refresh rate
123  if cntStable = REFRESH_MAX_CNT_C then
124  -- Reset the Counter
125  cntStable <= (others => '0') after TPD_G;
126  cntAccum <= (others => '0') after TPD_G;
127  accum <= (others => '0') after TPD_G;
128  -- Calculate the new frequency
129  diffCnt <= (cntOut - cntOutDly) after TPD_G;
130  -- Save the current count value for next refresh cycle
131  cntOutDly <= cntOut after TPD_G;
132  -- Reset the done flag
133  doneAccum <= '0' after TPD_G;
134  -- Check if we are accumulating
135  elsif doneAccum = '0' then
136  -- Check for accumulation counter
137  if cntAccum = toSlv(integer(REFRESH_RATE_G), CNT_WIDTH_G) then
138  -- Write the accumulated value to the output FIFO
139  wrEn <= '1' after TPD_G;
140  -- Set the done flag
141  doneAccum <= '1' after TPD_G;
142  else
143  -- Increment the counter
144  cntAccum <= cntAccum + 1 after TPD_G;
145  -- Accumulate the value
146  accum <= accum + diffCnt after TPD_G;
147  end if;
148  end if;
149  end if;
150  end process;
151 
152  SynchronizerFifo_Out : entity work.SynchronizerFifo
153  generic map (
154  TPD_G => TPD_G,
156  port map (
157  --Write Ports (wr_clk domain)
158  wr_clk => refClk,
159  wr_en => wrEn,
160  din => accum,
161  --Read Ports (rd_clk domain)
162  rd_clk => locClk,
163  valid => updated,
164  dout => freqHertz);
165 
166  ---------------------------
167  -- Clock Monitoring Process
168  ---------------------------
169  process(locClk)
170  begin
171  if rising_edge(locClk) then
172  -- Update locked flag
173  if (tooFastDet = '0') and (tooSlowDet = '0') then
174  lockedDet <= '1' after TPD_G;
175  else
176  lockedDet <= '0' after TPD_G;
177  end if;
178  -- Check for too fast input clock
179  if freqHertz > CLK_UPPER_LIMIT_C then
180  tooFastDet <= '1' after TPD_G;
181  else
182  tooFastDet <= '0' after TPD_G;
183  end if;
184  -- Check for too slow input clock
185  if freqHertz < CLK_LOWER_LIMIT_C then
186  tooSlowDet <= '1' after TPD_G;
187  else
188  tooSlowDet <= '0' after TPD_G;
189  end if;
190  end if;
191  end process;
192 
193 end rtl;
TPD_Gtime := 1 ns
USE_DSP48_Gstring := "no"
std_logic sl
Definition: StdRtlPkg.vhd:28
in dinslv( DATA_WIDTH_G- 1 downto 0)
REF_CLK_FREQ_Greal := 200.0E+6
CNT_WIDTH_Gpositive := 32
out doutslv( DATA_WIDTH_G- 1 downto 0)
out freqOutslv( CNT_WIDTH_G- 1 downto 0)
out freqUpdatedsl
REFRESH_RATE_Greal := 1.0E+3
CLK_LOWER_LIMIT_Greal := 159.0E+6
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
CLK_UPPER_LIMIT_Greal := 161.0E+6