summaryrefslogtreecommitdiff
path: root/pb_logique_seq.srcs/sources_1/imports/new/synchro_zybo_v1.vhd
blob: 7feeaac440e193d3dee3512b13242471e7e00818 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
---------------------------------------------------------------------------------------------
-- synchro_zybo_v1.vhd
---------------------------------------------------------------------------------------------
-- Generation d'horloge et de signaux de synchronisation
---------------------------------------------------------------------------------------------
-- Université de Sherbrooke - Département de GEGI
-- 
-- Version          : 1.0
-- Nomenclature     : ref GRAMS
-- Date             : 30 octobre 2018, 7 novembre 2018, 4 janvier 2019, 24 janvier 2019
-- Auteur(s)        : Daniel Dalle
--  Technologie     : ZYNQ 7000 Zybo Z7-10 (xc7z010clg400-1)
--  Outils          : vivado 2018.2 64 bits
-- 
--------------------------------
-- Description
--------------------------------
-- Génération de signaux de synchronisation, incluant des "strobes"
-- (utilise un PLL)
-- Ref:
-- 7 Series Libraries Guide www.xilinx.com 418 UG953 (v2016.3) October 5, 2016
--   (pages 425 PLLE2_BASE)
--
-- revisions
-- mise a jour D Dalle 17 octobre 2019   nomenclature synchro_demo_codec_v4 devient synchro_zybo_v1
-- mise a jour D Dalle 24 janvier 2019   v4 strobe commentaires, élimination entrée reset
-- mise a jour D Dalle 7  janvier 2019   v3 strobe 1000Hz   validation / correction S_1Hz
-- mise a jour D Dalle 4  janvier 2019   v3 strobe 1000Hz   
-- mise a jour D Dalle 27 decembre 2018  v3 tous les strobes sur 50 MHz  
-- mise a jour D Dalle 17 decembre 2018 constantes horloges en Hz (pour coherence avec autres modules)
---------------------------------------------------------------------------------------------
-- À FAIRE:
---------------------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;     -- requis pour les constantes  etc.
use IEEE.STD_LOGIC_UNSIGNED.ALL;  -- pour les additions dans les compteurs

Library UNISIM;
use UNISIM.vcomponents.all;


entity synchro_zybo_v1 is
generic (const_CLK_syst_Hz: integer := 100_000_000); -- valeur par defaut fréquence de clkm
Port ( 
   sysclk      : in  STD_LOGIC; -- Entrée horloge maitre, typique 100 MHz (10 ns) ou 125 (8 ns)
   o_clk_0     : out STD_LOGIC; -- horloge via bufg 50.    MHz  (20 ns) 
   o_clk_1     : out STD_LOGIC; -- horloge via bufg 12.389 MHz  (80,714 ns)
   o_stb_1000Hz: out STD_LOGIC; -- strobe durée 1/o_clk_0 sync sur 1000Hz
   o_stb_1Hz   : out STD_LOGIC; -- strobe durée 1/o_clk_0 sync sur  1Hz
   o_S_1Hz     : out STD_LOGIC  -- Signal temoin 1 Hz
   );                   
end synchro_zybo_v1;


architecture Behavioral of synchro_zybo_v1 is

   component strb_gen is
         Port ( 
                CLK      : in STD_LOGIC;     -- Entrée  horloge maitre 
                i_don    : in  STD_LOGIC;   -- signal pour generer strobe au front montant          
                o_stb    : out  STD_LOGIC   -- strobe synchrone 
                );                          
     end component;
 
-- parametres pour constantes du PLL                                                          -- sim 125 MHz sysclk
 constant const_CLK_syst_MHz : integer := integer( real (const_CLK_syst_Hz) / 1000000.0);     -- verif 125
 constant c_CLKFBOUT_MULT    : integer := 56; -- Multiply value for all CLKOUT, (2-64)
 constant c_CLKIN1_PERIOD    : real := 1000.0 / real(const_CLK_syst_MHz) ;  -- Input clock period in ns to ps resolution 
                                                                            -- (i.e. 33.333 is 30 MHz).
-- constant c_DIVCLK_DIVIDE  : integer := 7;   -- Master division value, (1-56)
 constant c_DIVCLK_DIVIDE    : integer := 5;   -- Master division value, (1-56)
 -- CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: Divide amount for each CLKOUT (1-128)
 constant c_CLKOUT0_DIVIDE : integer := const_CLK_syst_MHz*c_CLKFBOUT_MULT/c_DIVCLK_DIVIDE/50 ; -- pour obtenir 50 MHz
                                                                                                -- verif 28
 constant c_CLKOUT1_DIVIDE : integer := const_CLK_syst_MHz*c_CLKFBOUT_MULT*1000/c_DIVCLK_DIVIDE/12289; -- pour obtenir 12.289 MHz
                                                                                                -- verif 113
 
  constant FRQ_exact_KHz : integer := 1000*const_CLK_syst_MHz*c_CLKFBOUT_MULT/c_DIVCLK_DIVIDE/c_CLKOUT0_DIVIDE ;
   -- calcul des constantes avec CLKOUT1 comme fréquence de base (12,2888 MHz)  **   CLKOUT1 CLKOUT1 CLKOUT1 CLKOUT1
                                                                                       -- verif 50_000
  constant FRQ_niv1_KHz_des :       integer := 200 ; -- KHz (clk intermediaire desiree pour compteurs)
                                                                                       -- verif 200
  constant ctmp1:  integer  :=(FRQ_exact_KHz/(FRQ_niv1_KHz_des)-1);  
                                                                                       -- verif 249 ( = x"0F9")
  constant cdiv1 : std_logic_vector(11  downto 0):= conv_std_logic_vector(ctmp1, 12); 
                                                                                       -- verif x"0F9"
  constant FRQ_niv1_KHz_exact : integer := FRQ_exact_KHz / ctmp1;

  constant FRQ_niv2_Hz_des :       integer := 2000 ; -- Hz (frq toggle intermediaire desiree )       --- **** valeur v3 modifiee
 -- constant ctmp2:  integer  :=(1000*FRQ_niv1_KHz_exact/(2*FRQ_niv2_Hz_des)-1);  -- calcul avec toggle
                                                                                              
  constant ctmp2:  integer  :=(1000*FRQ_niv1_KHz_exact/(FRQ_niv2_Hz_des)-1);  -- 
                                                                                      -- verif 99
  constant cdiv2 : std_logic_vector(11  downto 0):= conv_std_logic_vector(ctmp2, 12); -- 
  constant FRQ_niv2_Hz_exact : integer := 1000*FRQ_niv1_KHz_exact / (ctmp2);
                                                                                      -- verif 2020 
  --  
  constant FRQ_inter_3_Hz_des :       integer := 1 ; -- Hz (clk  desiree )
  constant ctmp3:  integer  :=(FRQ_niv2_Hz_exact/(2*FRQ_inter_3_Hz_des)-1);  
                                                                                      -- verif 1009 (= x"3F1")
  --constant ctmp3:  integer  :=(FRQ_niv2_Hz_exact/(FRQ_inter_3_Hz_des)-1); 
                                                                                             
  constant cdiv3 : std_logic_vector(11  downto 0):= conv_std_logic_vector(ctmp3, 12); 

 signal ValueCounter1      : std_logic_vector(11 downto 0)   := (others => '0');
 signal ValueCounter2      : std_logic_vector(11 downto 0)   := (others => '0');
 signal ValueCounter3      : std_logic_vector(11 downto 0)  := (others => '0');

 signal d_TC_ValueCounter1Hz : std_logic := '0';

 signal clk_0_interne      : std_logic := '0';
 signal clk_1_interne      : std_logic := '0';
 signal d_s1HzInt          : std_logic := '0' ;
 signal q_s1HzInt          : std_logic := '0' ;
 --signal d_200kHzInt   : std_logic := '0' ;
 signal d_s1000HzInt       : std_logic := '0' ;
-- signal q_s100HzInt       : std_logic := '0' ;
-- signal qq_s100HzInt       : std_logic := '0' ;
 signal d_strobe_1000HzInt : std_logic := '0' ;
 signal d_strobe_1HzInt    : std_logic := '0' ;
 
 signal CLKOUT0 : std_logic := '0' ;
 signal CLKOUT1 : std_logic := '0' ; 
 signal CLKOUT2 : std_logic := '0' ; -- non utilisee
 signal CLKOUT3 : std_logic := '0' ; -- non utilisee
 signal CLKOUT4 : std_logic := '0' ; -- non utilisee
 signal CLKOUT5 : std_logic := '0' ; -- non utilisee

 signal CLKFBOUT : std_logic;     -- 1-bit output: Feedback clock
 signal LOCKED   : std_logic;     -- 1-bit output: LOCK
 signal clk_in   : std_logic;     -- 1-bit input: Input clock 


begin

PLLE2_BASE_inst : PLLE2_BASE
 generic map (
 BANDWIDTH => "OPTIMIZED",  -- OPTIMIZED, HIGH, LOW
 CLKFBOUT_MULT  => c_CLKFBOUT_MULT,       -- Multiply value for all CLKOUT, (2-64)
 CLKFBOUT_PHASE => 0.0,     -- Phase offset in degrees of CLKFB, (-360.000-360.000).
 CLKIN1_PERIOD  => c_CLKIN1_PERIOD,     -- Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz).
 -- CLKOUT0_DIVIDE - CLKOUT5_DIVIDE: Divide amount for each CLKOUT (1-128)
 CLKOUT0_DIVIDE => c_CLKOUT0_DIVIDE,
 CLKOUT1_DIVIDE => c_CLKOUT1_DIVIDE,
 CLKOUT2_DIVIDE => 1,
 CLKOUT3_DIVIDE => 1,
 CLKOUT4_DIVIDE => 1,
 CLKOUT5_DIVIDE => 1,
 -- CLKOUT0_DUTY_CYCLE - CLKOUT5_DUTY_CYCLE: Duty cycle for each CLKOUT (0.001-0.999).
 CLKOUT0_DUTY_CYCLE => 0.5,
 CLKOUT1_DUTY_CYCLE => 0.5,
 CLKOUT2_DUTY_CYCLE => 0.5,
 CLKOUT3_DUTY_CYCLE => 0.5,
 CLKOUT4_DUTY_CYCLE => 0.5,
 CLKOUT5_DUTY_CYCLE => 0.5,
 -- CLKOUT0_PHASE - CLKOUT5_PHASE: Phase offset for each CLKOUT (-360.000-360.000).
 CLKOUT0_PHASE => 0.0,
 CLKOUT1_PHASE => 0.0,
 CLKOUT2_PHASE => 0.0,
 CLKOUT3_PHASE => 0.0,
 CLKOUT4_PHASE => 0.0,
 CLKOUT5_PHASE => 0.0,
 DIVCLK_DIVIDE => c_DIVCLK_DIVIDE, -- Master division value, (1-56)
 REF_JITTER1   => 0.01, -- Reference input jitter in UI, (0.000-0.999).
 STARTUP_WAIT  => "FALSE" -- Delay DONE until PLL Locks, ("TRUE"/"FALSE")
 )
 port map (
-- Clock Outputs: 1-bit (each) output: User configurable clock outputs
CLKOUT0 => CLKOUT0, -- 1-bit output: CLKOUT0
CLKOUT1 => CLKOUT1, -- 1-bit output: CLKOUT1
CLKOUT2 => CLKOUT2, -- 1-bit output: CLKOUT2
CLKOUT3 => CLKOUT3, -- 1-bit output: CLKOUT3
CLKOUT4 => CLKOUT4, -- 1-bit output: CLKOUT4
CLKOUT5 => CLKOUT5, -- 1-bit output: CLKOUT5
-- Feedback Clocks: 1-bit (each) output: Clock feedback ports
CLKFBOUT => CLKFBOUT,     -- 1-bit output: Feedback clock
LOCKED => LOCKED,         -- 1-bit output: LOCK
CLKIN1 => sysclk,         -- 1-bit input: Input clock
-- Control Ports: 1-bit (each) input: PLL control ports
PWRDWN => '0',       -- 1-bit input: Power-down
--RST => i_rst, -- 1-bit input: Reset
RST =>'0', -- 1-bit input: Reset
-- Feedback Clocks: 1-bit (each) input: Clock feedback ports
CLKFBIN => CLKFBOUT      -- 1-bit input: Feedback clock
 );
 
--  buffer horloge 
ClockBuf0: bufg
port map(
   I  => CLKOUT0,
   O  => clk_0_interne
   ); 
o_clk_0  <= clk_0_interne ; -- 
                          
ClockBufer1: bufg
    port map(
        I    => CLKOUT1,
        O    => clk_1_interne
        );

o_clk_1      <= clk_1_interne ; --     
o_S_1Hz      <= d_s1HzInt;
o_stb_1000Hz <= d_strobe_1000HzInt;
o_stb_1Hz    <= d_strobe_1HzInt;

-- gestion des compteurs  (estimes de durees calcules pour sysclk = 125 MHz) --V3
process(clk_0_interne)           -- avec 50 MHz
--
begin                                                     -- Estimation avec clk1 = 12,288 
                                                          --     (12,389 selon calcul avec sysclk =125 MHz)
                                                          --
   if(clk_0_interne'event and clk_0_interne = '1') then   -- evenement se produit aux 81 ns approx
       ValueCounter1 <= ValueCounter1 + 1;
       if (ValueCounter1 = cdiv1) then                    -- evenement se produit aux 5 us approx
            ValueCounter1 <= "000000000000"; 
            ValueCounter2 <= ValueCounter2 + 1;
            if (ValueCounter2 = cdiv2) then
               d_s1000HzInt <= Not d_s1000HzInt;           -- evenement se produit aux 500 us approx (2 KHz)
               ValueCounter2 <= "000000000000";            -- la periode de d_s1000HzInt est alors ~ 1 ms
               ValueCounter3 <= ValueCounter3 + 1;
               if (ValueCounter3 = cdiv3) then             -- evenement se produit aux 500 ms approx (2 Hz)
                   ValueCounter3 <= "000000000000";
                     d_s1HzInt <= Not d_s1HzInt;           -- ici on fait un toggle donc 2*500 ms  
                                                           --     -> 1 sec.  pour frequence de d_s1HzInt;
               end if;
            end if;                 
      end if;
   end if;
end process;



inst_strb_1000Hz : strb_gen 
     -- les strobes sont synchronisés sur l'horloge clk_1_interne
         Port map ( 
                CLK     =>  clk_0_interne,
                i_don   =>  d_s1000HzInt,     
                o_stb   =>  d_strobe_1000HzInt
                ); 
 
inst_strb_1Hz : strb_gen 
     -- les strobes sont synchronisés sur l'horloge clk_1_interne
         Port map ( 
                CLK     =>  clk_0_interne,
                i_don   =>  d_s1HzInt,     
                o_stb   =>  d_strobe_1HzInt
                );                          
                 

--process(CLKOUT1, q_s100HzInt)   -- bascule synchro de l entree
--begin
-- if(CLKOUT1'event and CLKOUT1 = '1') then
--     qq_s100HzInt <= q_s100HzInt;
-- end if;
--end process;

--process(q_s100HzInt, qq_s100HzInt)   -- sortie impulsion synchrone
--begin
--    d_strobe_100HzInt <= q_s100HzInt and not(qq_s100HzInt);
--end process;


end Behavioral;