-- Digital PLL based on the 74LS297 architecture -- uses jitter minimization library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity PLL1 is port ( clk: in STD_LOGIC; -- clock for k and id counter f_in: in STD_LOGIC; -- input signal f_out: inout STD_LOGIC -- output signal ); end PLL1; architecture PLL1_arch of PLL1 is -- enter PLL parameters here constant Kbit: integer:=12; -- bitwidth of the K_counter constant N_mod: integer:=5; -- modul of N_counter constant f_in_mod: integer:=8; -- modul of reference prescaler constant f_out_mod: integer:=8; -- modul of DCO_postscaler -- do not change source code below here ((uunless you know what you are doing) signal dn_up: std_logic; -- selects up or down counter of k_counter signal ca: std_logic; -- carry out of k_counter signal bo: std_logic; -- borrow out of k_counter signal N_cont: integer range 0 to N_mod-1; -- N counter signal f_in_scale: integer range 0 to f_in_mod-1; -- reference prescaler signal f_out_scale: integer range 0 to f_out_mod-1; -- DCO postscaler signal f_in_s, f_out_s: std_logic; -- prescaler outputs signal k_up: std_logic_vector (Kbit-1 downto 0); -- up counter in k_counter signal k_dn: std_logic_vector (Kbit-1 downto 0); -- down counter in k_counter signal c1,c2,c3,c4: std_logic; -- shift register of carry signal b1,b2,b3,b4: std_logic; -- shift register of borrow signal id_out: std_logic; -- output of id_counter signal ena:std_logic; -- enable for k-counter begin -- K_counter -- with jitter minimization ena<=f_out_s xor (not dn_up); k_cnt: process (clk) begin if clk='0' and clk'event then if ena='1' then if f_out_s='1' then k_dn<=k_dn+1; else k_up<=k_up+1; end if; end if; end if; end process; ca<=k_up(kbit-1); bo<=k_dn(kbit-1); -- ID_counter id_cnt: process (clk) begin if clk='0' and clk'event then c1<=ca; c2<=c1; c3<=c2; c4<= ( (not c1) and c2 and id_out ) or ( (not c2) and c3 and id_out ); -- in the schematic of the 74LS297 the c4 uses the invertet output -- for some strange reason we can not invert c4 here, this will eliminate 2 FFs b1<=bo; b2<=b1; b3<=b2; b4<= ( (not b1) and b2 and (not id_out) ) or ( (not b2) and b3 and (not id_out) ); -- here is a JK-FF, maybe we need a better construction in the future -- we use the inverted signals of c4 and b4 if c4='1' and b4='1' then id_out<=id_out; elsif c4='0' and b4='1' then id_out<='1'; elsif c4='1' and b4='0' then id_out<='0'; elsif c4='0' and b4='0' then id_out<= not id_out; end if; -- end of JK-FF end if; end process; -- The original schematics of the 74LS297 produces a gated clock, -- which may result in timing problems -- We better use id_out as an clock enable for the N counter -- ID-out is the inverted clock enable; clk is the inverted clk -- simple XOR phase detector -- dn_up<=f_in_s xor f_out_s; -- iff you want to use the EXOR PD, just uncomment this -- but think about the EXOR limitations!!!! -- edge controlled phase detector ECPD: block is signal pd1,pd2,rpd: std_logic; begin rpd<=pd2; dn_up<=pd1; process (rpd, f_out_s) -- a leading negative edge of begin -- f_out sets the phase detector if rpd='1' then pd1<='0'; elsif f_out_s='0' and f_out_s'event then pd1<='1'; end if; end process; process (rpd, f_in_s) -- a negative edge of f_in resets begin if rpd='1' then -- the phase detector pd2<='0'; elsif f_in_s='0' and f_in_s'event then pd2<='1'; end if; end process; end block; -- prescalers process (f_in) begin if f_in='1' and f_in'event then if f_in_scale=f_in_mod-1 then f_in_scale<=0; f_in_s<='0'; elsif f_in_scale>=(f_in_mod/2-1) then f_in_scale<=f_in_scale+1; f_in_s<='1'; else f_in_scale<=f_in_scale+1; f_in_s<='0'; end if; end if; end process; process (f_out) begin if f_out='1' and f_out'event then if f_out_scale=f_out_mod-1 then f_out_scale<=0; f_out_s<='0'; elsif f_out_scale>=(f_out_mod/2-1) then f_out_scale<=f_out_scale+1; f_out_s<='1'; else f_out_scale<=f_out_scale+1; f_out_s<='0'; end if; end if; end process; -- Divide by N counter -- this implementation differs a lot fromm the logic in the 74LS297 -- which uses a gated clock (ID output), tthat is deadly for very high clock rates -- (up to 180MHz in Spartan 2) -- here we use clock enable on the N counntter process (clk, id_out) begin if clk='0' and clk'event then if id_out='0' then if N_cont=N_mod-1 then N_cont<=0; f_out<='0'; elsif N_cont>=(N_mod/2-1) then N_cont<=N_cont+1; f_out<='1'; else N_cont<=N_cont+1; f_out<='0'; end if; end if; end if; end process; end PLL1_arch;