--===========================================================================-- -- Design units : DPLL (Entity and architecture) -- -- File name : dpll.vhd -- -- Purpose : Digital 32 stage phase locked loop -- recover data clock and dcd signal -- -- Note : NON-COMMERCIAL USAGE ONLY -- -- Limitations : -- -- Errors : -- -- Library : -- -- Dependencies : -- -- Author : Juergen Hasch, hasch@t-online.de -- Meisenstr. 23 -- 73066 Uhingen -- Germany -- -- Synthesis : Xilinx Foundation 1.4 ------------------------------------------------------------------------------- -- Revision list -- Version Author Date Changes -- 1.0 JH 13 Mar 98 File created -- -- ------------------------------------------------------------------------------- Library ieee; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity dpll is port( datain: in std_logic; -- raw data input clock: in std_logic; -- 64*bit clock rx_clock: out std_logic; -- recovered rx clock dataout: out std_logic; -- received data output clrdcd: in std_logic; -- clear dcd when 8 ones are detected in hdlcdec dcd: out std_logic); -- data carrier detect output end dpll; architecture behaviour of dpll is signal counter: std_logic_vector(4 downto 0); -- counter 0..31 signal dcd_cntr: std_logic_vector(5 downto 0); -- counter 0..127 signal edge: std_logic; -- edge detector output: data decision changed signal dly_data: std_logic; -- delayed data for edge detector signal ql: std_logic; -- late clock signal qe: std_logic; -- early clock signal enable: std_logic; -- gets toggled every clock or when clock has to be adjusted signal increment: std_logic; signal decrement: std_logic; signal clear_dcd: std_logic; signal reset_dcd: std_logic; begin -- -- recovered rx clock for followning stages -- rx_clock <= counter(4); process(clock,clrdcd,reset_dcd) begin if (clock'event and clock='1' ) then clear_dcd <= reset_dcd or clrdcd; end if; end process; -- -- clock in new data -- process(clock,datain) begin if (clock'event and clock='1' ) then dataout <= datain; end if; end process; -- -- rx clock counter -- process(clock,enable,clrdcd) begin --if ( clrdcd='1') then -- reset for illegal data at hdlcdec -- counter <= (others => '0'); if (clock'event and clock='1' ) then if (enable='1') then counter <= counter+1; -- increase counter else counter <= counter; end if; end if; end process; -- -- set early and late clocks -- process(counter) begin if (counter="10000" or counter ="01111" ) then ql <= '0'; qe <= '0'; elsif (counter(4)='1') then -- late clock when counter > 32 ql <= '1'; qe <= '0'; else ql <= '0'; -- early clock when counter < 31 qe <= '1'; end if; end process; -- -- adjst rx clock -- this is done by changing the enable signal for the rx clock counter -- enable gets toggled every clock event. It gets set additionally when -- the clock counter should be incremented and cleared when clock should -- be decremented. -- process(clock,enable,clrdcd) begin -- if ( clrdcd='1') then -- enable<='0'; -- increment <='0'; -- decrement <='0'; if (clock'event and clock='1') then if (qe='1' and edge='1') then increment <='1'; -- increment clock when edge detect end if; -- during early clock if (ql='1' and edge='1') then decrement <='1'; -- decrement clock when edge detect end if; -- during late clock if (enable ='1') then if (increment ='1') then increment <='0'; -- clear after one increment step enable <='1'; else enable <='0'; end if; else if (decrement ='1') then decrement<='0'; -- clear after one decrement step enable <= '0'; else enable <='1'; end if; end if; end if; end process; -- -- dcd detection -- process(clock,edge,counter,clear_dcd) begin if ( clear_dcd='1') then dcd_cntr<= (others => '0'); dcd <= '0'; reset_dcd <='0'; elsif (counter(4)'event and counter(4)='0') then if ( edge='0' ) then -- sample at rising edge, if no data change increase counter if (dcd_cntr = 63) then dcd <= '1'; -- assert dcd if dcd counter is at max dcd_cntr <= dcd_cntr; else dcd <= '0'; dcd_cntr <= dcd_cntr+1; end if; else reset_dcd <='1'; end if; end if; end process; -- -- edge detector, input data has changed -- process(clock,datain) begin if (clock'event and clock='1') then edge <= dly_data xor datain; dly_data <= datain; end if; end process; end behaviour; --============================ End of dpll ==================================--