Revert "demo: add HPLL and serial_dac design files from White Rabbit r1344"

This reverts commit 1a2cb362.
parent 6553bd46
- integrator with anti-windup
- frequency error overflow checking/clamping (no recovery after loss-of-lock event)
- clock multiplexing: allow for UP0/UP1/local reference clock dynamic switching
#!/bin/bash
mkdir -p doc
wbgen2 -D ./doc/wrsw_helper_pll.html -V hpll_wb_slave.vhd -C ../../../software/include/hw/hpll_regs.h --cstyle defines --lang vhdl -K ../../sim/hpll_wb_regs.v hpll_wb.wb
\ No newline at end of file
-------------------------------------------------------------------------------
-- Title : DMTD Helper PLL (HPLL) - bang-bang phase/frequency detector
-- Project : White Rabbit Switch
-------------------------------------------------------------------------------
-- File : hpll_bangbang_pd.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-06-14
-- Last update: 2011-01-14
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: Bang-bang type phase detector. clk_ref_i and clk_fbck_i clocks
-- are divided by hpll_divr_div_ref_i and hpll_divr_div_fb_i respectively and
-- compared. The phase error is outputted every (2^hpll_pcr_pd_gate_i + 10)
-- clk_fbck_i cycles. Divider counters can be synchronized at any moment
-- by pulsing the sync_dividers_p_i signal.
-------------------------------------------------------------------------------
-- Copyright (c) 2010 Tomasz Wlostowski
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-06-14 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.common_components.all;
entity hpll_bangbang_pd is
port (
-------------------------------------------------------------------------------
-- Clocks & resets
-------------------------------------------------------------------------------
-- reference clock
clk_ref_i : in std_logic;
-- fed-back (VCO) clock
clk_fbck_i : in std_logic;
-- system clock (wishbone and I/O)
clk_sys_i : in std_logic;
-- reset signals (the same reset synced to different clocks)
rst_n_refclk_i : in std_logic;
rst_n_fbck_i : in std_logic;
rst_n_sysclk_i : in std_logic;
-------------------------------------------------------------------------------
-- I/O
-------------------------------------------------------------------------------
sync_dividers_p_i : in std_logic;
phase_err_o : out std_logic_vector(11 downto 0);
phase_err_stb_p_o : out std_logic;
-------------------------------------------------------------------------------
-- Wishbone regs
-------------------------------------------------------------------------------
-- phase counter gating
hpll_pcr_pd_gate_i : in std_logic_vector(2 downto 0);
-- reference divider
hpll_divr_div_ref_i : in std_logic_vector(15 downto 0);
-- feedback divider
hpll_divr_div_fb_i : in std_logic_vector(15 downto 0);
-------------------------------------------------------------------------------
-- Debug outputs
-------------------------------------------------------------------------------
dbg_ref_divided_o : out std_logic;
dbg_fbck_divided_o : out std_logic;
dbg_pd_up_o : out std_logic;
dbg_pd_down_o : out std_logic
);
attribute rom_extract: string;
attribute rom_extract of hpll_bangbang_pd : entity is "no";
end hpll_bangbang_pd;
architecture rtl of hpll_bangbang_pd is
constant c_COUNTER_BITS : integer := 18;
constant c_ONES : std_logic_vector(63 downto 0) := (others => '1');
constant c_ZEROS : std_logic_vector(63 downto 0) := (others => '0');
signal gate_counter : unsigned(c_COUNTER_BITS-1 downto 0);
signal gate_p : std_logic;
signal updown_counter : signed(c_COUNTER_BITS-1 downto 0);
-- phase error clamping stuff
signal ph_err_sign : std_logic;
signal ph_err_extrabits : std_logic_vector(c_COUNTER_BITS - 12 downto 0);
signal ph_err_clamp_plus : std_logic;
signal ph_err_clamp_minus : std_logic;
signal ph_sreg_delay : std_logic_vector(4 downto 0);
signal ph_err : signed(c_COUNTER_BITS-1 downto 0);
signal ph_err_p : std_logic;
signal ph_err_avg_slv : std_logic_vector(11 downto 0);
signal ph_err_avg_p : std_logic;
signal clk_ref_div2 : std_logic; -- reference clock/2
-- phase detector input signals (after division)
signal pd_in_ref : std_logic;
signal pd_in_fbck : std_logic;
-- phase detector outputs
signal pd_a, pd_b, pd_t, pd_ta : std_logic;
signal pd_up, pd_down : std_logic;
signal atb_together : std_logic_vector(2 downto 0);
-- divider counters
signal div_ctr_ref : unsigned(15 downto 0); -- max N = 65535
signal div_ctr_fbck : unsigned(15 downto 0); -- max N = 65535
-- counter sync signals
signal sync_dividers_ref_p : std_logic;
signal sync_dividers_fbck_p : std_logic;
-- disable RAM extraction (XST is trying to implement the phase detector in a
-- RAM)
-- attribute ram_extract of pd_down : signal is "no";
begin -- rtl
sync_ffs_sync_dividers_ref : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_ref_i,
rst_n_i => rst_n_refclk_i,
data_i => sync_dividers_p_i,
synced_o => open,
npulse_o => open,
ppulse_o => sync_dividers_ref_p);
sync_ffs_sync_dividers_fbck : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_fbck_i,
rst_n_i => rst_n_fbck_i,
data_i => sync_dividers_p_i,
synced_o => open,
npulse_o => open,
ppulse_o => sync_dividers_fbck_p);
-- divide the reference clock by 2 - the reference clock must be 2x slower
-- than the VCO clock for proper operation of the BB detector
divide_ref_2 : process(clk_ref_i, rst_n_refclk_i)
begin
if rising_edge(clk_ref_i) then
if rst_n_refclk_i = '0' then
clk_ref_div2 <= '0';
else
clk_ref_div2 <= not clk_ref_div2;
end if;
end if;
end process;
-- Divides the reference clock by DIV_REF, output signal: pd_in_ref.
divide_ref_N : process (clk_ref_i, rst_n_refclk_i)
begin -- process
if rising_edge(clk_ref_i) then
if rst_n_refclk_i = '0' or sync_dividers_ref_p = '1' then
div_ctr_ref <= to_unsigned(1, div_ctr_ref'length);
pd_in_ref <= '0';
else
if(clk_ref_div2 = '1') then -- reference clock must be at the half rate of
-- the VCO clock
if (div_ctr_ref = unsigned(hpll_divr_div_ref_i)) then
div_ctr_ref <= to_unsigned(1, div_ctr_ref'length);
pd_in_ref <= not pd_in_ref; -- divide the clock :)
else
div_ctr_ref <= div_ctr_ref + 1;
end if;
end if;
end if;
end if;
end process;
-- Divides the VCO clock by DIV_FB, output signal: pd_in_fbck
divide_fbck_N : process (clk_fbck_i, rst_n_fbck_i)
begin -- process
if rising_edge(clk_fbck_i) then
if rst_n_fbck_i = '0' or sync_dividers_fbck_p = '1' then
div_ctr_fbck <= to_unsigned(1, div_ctr_fbck'length);
pd_in_fbck <= '0';
else
if (div_ctr_fbck = unsigned(hpll_divr_div_fb_i)) then
div_ctr_fbck <= to_unsigned(1, div_ctr_fbck'length);
pd_in_fbck <= not pd_in_fbck; -- divide the clock :)
else
div_ctr_fbck <= div_ctr_fbck + 1;
end if;
end if;
end if;
end process;
-------------------------------------------------------------------------------
-- Bang-bang PD
-------------------------------------------------------------------------------
bb_pd_negedge : process(pd_in_fbck)
begin
if falling_edge(pd_in_fbck) then
pd_ta <= pd_in_ref;
end if;
end process;
bb_pd_posedge : process(pd_in_fbck)
begin
if rising_edge(pd_in_fbck) then
pd_b <= pd_in_ref;
pd_a <= pd_b;
pd_t <= pd_ta;
end if;
end process;
atb_together <= pd_a & pd_t & pd_b;
decode_bangbang : process(atb_together)
begin
case (atb_together) is
when "000" => -- no transition
pd_up <= '0';
pd_down <= '0';
when "001" => -- too fast
pd_up <= '0';
pd_down <= '1';
when "010" => -- invalid
pd_up <= '1';
pd_down <= '1';
when "011" => -- too slow
pd_up <= '1';
pd_down <= '0';
when "100" => -- too slow
pd_up <= '1';
pd_down <= '0';
when "101" => -- invalid
pd_up <= '1';
pd_down <= '1';
when "110" => -- too fast
pd_up <= '0';
pd_down <= '1';
when "111" => -- no transition
pd_up <= '0';
pd_down <= '0';
when others => null;
end case;
end process;
-- decodes the PD_GATE field from PCR register and generates the gating pulse
-- on gate_p.
phase_gating_decode : process (hpll_pcr_pd_gate_i, gate_counter)
begin
case hpll_pcr_pd_gate_i is
when "000" => gate_p <= gate_counter(10); -- gating: 1024
when "001" => gate_p <= gate_counter(11); -- gating: 2048
when "010" => gate_p <= gate_counter(12); -- gating: 4096
when "011" => gate_p <= gate_counter(13); -- gating: 8192
when "100" => gate_p <= gate_counter(14); -- gating: 16384
when "101" => gate_p <= gate_counter(15); -- gating: 32768
when "110" => gate_p <= gate_counter(16); -- gating: 65536
when "111" => gate_p <= gate_counter(17); -- gating: 131072
when others => null;
end case;
end process;
-- error counter: accumulates UP/DOWN pulses from the phase detector in
-- updown_counter. The counter value is outputted to ph_err when there's a
-- pulse on gate_p signal and then the accumulating counter is reset.
count_updown : process(clk_fbck_i, rst_n_fbck_i)
begin
if rising_edge(clk_fbck_i) then
if rst_n_fbck_i = '0' then
ph_err <= (others => '0');
ph_sreg_delay <= (others => '0');
updown_counter <= (others => '0');
gate_counter <= to_unsigned(1, gate_counter'length);
else
if(gate_p = '1') then
-- got a gating pulse? output the new phase value
gate_counter <= to_unsigned(1, gate_counter'length);
ph_sreg_delay <= (others => '1');
-- check if we have a up/down pulse during counter reset
if(pd_up = '1' and pd_down = '0') then
updown_counter <= to_signed(1, updown_counter'length);
elsif (pd_up = '0' and pd_down = '1') then
updown_counter <= to_signed(-1, updown_counter'length);
else
updown_counter <= (others => '0');
end if;
ph_err <= updown_counter;
else
gate_counter <= gate_counter + 1;
ph_sreg_delay <= '0' & ph_sreg_delay (ph_sreg_delay'length -1 downto 1);
-- count the PD detector pulses
if(pd_up = '1' and pd_down = '0') then
updown_counter <= updown_counter + 1;
elsif (pd_up = '0' and pd_down = '1') then
updown_counter <= updown_counter - 1;
end if;
end if;
end if;
end if;
end process;
-- sync chain (from clk_fbck_i to clk_sys_i) for the new phase error pulse (ph_err_p).
sync_ffs_phase_p : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_sys_i,
rst_n_i => rst_n_sysclk_i,
data_i => ph_sreg_delay(0),
synced_o => open,
npulse_o => open,
ppulse_o => ph_err_p);
-- phase error clamping stuff:
ph_err_sign <= std_logic(ph_err(ph_err'length-1));
ph_err_extrabits <= std_logic_vector(ph_err(ph_err'length-1 downto phase_err_o'length-1));
ph_err_clamp_minus <= '1' when ph_err_sign = '1' and (ph_err_extrabits /= c_ONES(ph_err_extrabits'length-1 downto 0)) else '0';
ph_err_clamp_plus <= '1' when ph_err_sign = '0' and (ph_err_extrabits /= c_ZEROS(ph_err_extrabits'length-1 downto 0)) else '0';
error_output : process (clk_sys_i, rst_n_sysclk_i)
begin -- process
if rising_edge(clk_sys_i) then
if (rst_n_sysclk_i = '0') then
ph_err_avg_slv <= (others => '0');
ph_err_avg_p <= '0';
else
-- got new value of the phase error? output it with clamping:)
if(ph_err_clamp_minus = '1') then
ph_err_avg_slv <= '1' & c_ZEROS(phase_err_o'length-2 downto 0);
elsif (ph_err_clamp_plus = '1') then
ph_err_avg_slv <= '0' & c_ONES(phase_err_o'length-2 downto 0);
else
ph_err_avg_slv <= std_logic_vector(ph_err(phase_err_o'length-1 downto 0));
end if;
ph_err_avg_p <= ph_err_p;
end if;
end if;
end process;
phase_err_o <= ph_err_avg_slv;
phase_err_stb_p_o <= ph_err_avg_p;
-- drive the "debug" outputs
dbg_pd_down_o <= pd_down;
dbg_pd_up_o <= pd_up;
dbg_fbck_divided_o <= pd_in_fbck;
dbg_ref_divided_o <= pd_in_ref;
end rtl;
-------------------------------------------------------------------------------
-- Title : DMTD Helper PLL (HPLL) - programmable PI controller
-- Project : White Rabbit Switch
-------------------------------------------------------------------------------
-- File : hpll_controller.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-06-14
-- Last update: 2010-06-21
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: Dual, programmable PI controller:
-- - first channel processes the frequency error (gain defined by P_KP/P_KI)
-- - second channel processes the phase error (gain defined by F_KP/F_KI)
-- The PI controller starts in the frequency lock mode (using 1st channel).
-- After locking on the frequency, it switches to phase mode (2nd channel).
-------------------------------------------------------------------------------
-- Copyright (c) 2010 Tomasz Wlostowski
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-06-14 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity hpll_controller is
generic(
g_error_bits : integer := 12;
g_dacval_bits : integer := 16;
g_output_bias : integer := 32767;
g_integrator_fracbits : integer := 16;
g_integrator_overbits : integer := 6;
g_coef_bits : integer := 16
);
port (
clk_sys_i : in std_logic;
rst_n_sysclk_i : in std_logic;
-------------------------------------------------------------------------------
-- Phase & frequency error inputs
-------------------------------------------------------------------------------
phase_err_i : in std_logic_vector(g_error_bits-1 downto 0);
phase_err_stb_p_i : in std_logic;
freq_err_i : in std_logic_vector(g_error_bits-1 downto 0);
freq_err_stb_p_i : in std_logic;
-------------------------------------------------------------------------------
-- DAC Output
-------------------------------------------------------------------------------
dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0);
dac_val_stb_p_o : out std_logic;
sync_dividers_p_o : out std_logic;
-------------------------------------------------------------------------------
-- Wishbone regs
-------------------------------------------------------------------------------
-- PLL enable
hpll_pcr_enable_i : in std_logic;
-- PI force freq mode. '1' causes the PI to stay in frequency lock mode all the
-- time.
hpll_pcr_force_f_i : in std_logic;
-- Frequency Kp/Ki
hpll_fbgr_f_kp_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_fbgr_f_ki_i : in std_logic_vector(g_coef_bits-1 downto 0);
-- Phase Kp/Ki
hpll_pbgr_p_kp_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_pbgr_p_ki_i : in std_logic_vector(g_coef_bits-1 downto 0);
-- Lock detect
hpll_ldcr_ld_thr_i : in std_logic_vector(7 downto 0);
hpll_ldcr_ld_samp_i : in std_logic_vector(7 downto 0);
-- Flags: frequency lock
hpll_psr_freq_lk_o : out std_logic;
-- Flags: phase lock
hpll_psr_phase_lk_o : out std_logic;
-- Flags: loss-of-lock indicator
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_load_i : in std_logic;
-- phase/freq error recording FIFO
hpll_rfifo_wr_req_o : out std_logic;
hpll_rfifo_wr_full_i : in std_logic;
hpll_rfifo_fp_mode_o : out std_logic;
hpll_rfifo_err_val_o : out std_logic_vector(g_error_bits-1 downto 0);
hpll_rfifo_dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0)
);
end hpll_controller;
architecture behavioral of hpll_controller is
component hpll_lock_detect
port (
rst_n_sysclk_i : std_logic;
clk_sys_i : std_logic;
phase_err_i : in std_logic_vector(11 downto 0);
phase_err_stb_p_i : in std_logic;
freq_err_i : in std_logic_vector(11 downto 0);
freq_err_stb_p_i : in std_logic;
hpll_ldcr_ld_samp_i : in std_logic_vector(7 downto 0);
hpll_ldcr_ld_thr_i : in std_logic_vector(7 downto 0);
hpll_psr_freq_lk_o : out std_logic;
hpll_psr_phase_lk_o : out std_logic;
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_load_i : in std_logic;
freq_mode_o : out std_logic);
end component;
type t_hpll_state is (HPLL_WAIT_SAMPLE, HPLL_MUL_KI, HPLL_INTEGRATE, HPLL_MUL_KP, HPLL_CALC_SUM, HPLL_ROUND_SUM);
-- integrator size: 12 error bits + 16 coefficient bits + 6 overflow bits
constant c_INTEGRATOR_BITS : integer := g_error_bits + g_integrator_overbits + g_coef_bits;
constant c_ZEROS : unsigned (63 downto 0) := (others => '0');
constant c_ONES : unsigned (63 downto 0) := (others => '1');
-- DAC DC bias (extended by c_INTEGRATOR_FRACBITS). By default it's half of the
-- output voltage scale.
constant c_OUTPUT_BIAS : signed(g_dacval_bits + g_integrator_fracbits-1 downto 0) := to_signed(g_output_bias, g_dacval_bits) & to_signed(0, g_integrator_fracbits);
-- Multiplier size. A = error value, B = coefficient value
constant c_MUL_A_BITS : integer := g_error_bits;
constant c_MUL_B_BITS : integer := g_coef_bits;
-- the integrator
signal i_reg : signed(c_INTEGRATOR_BITS-1 downto 0);
-- multiplier IO
signal mul_A : signed(c_MUL_A_BITS - 1 downto 0);
signal mul_B : signed(c_MUL_B_BITS - 1 downto 0);
signal mul_OUT : signed(c_MUL_A_BITS + c_MUL_B_BITS - 1 downto 0);
signal mul_out_reg : signed(c_MUL_A_BITS + c_MUL_B_BITS - 1 downto 0);
signal pi_state : t_hpll_state;
-- 1: we are in the frequency mode, 0: we are in phase mode.
signal freq_mode : std_logic;
signal freq_mode_ld : std_logic;
signal output_val : unsigned(c_INTEGRATOR_BITS-1 downto 0);
signal output_val_unrounded : unsigned(g_dacval_bits-1 downto 0);
signal output_val_round_up : std_logic;
signal dac_val_int : std_logic_vector(g_dacval_bits-1 downto 0);
begin -- behavioral
LOCK_DET : hpll_lock_detect
port map (
rst_n_sysclk_i => rst_n_sysclk_i,
clk_sys_i => clk_sys_i,
phase_err_i => phase_err_i,
phase_err_stb_p_i => phase_err_stb_p_i,
freq_err_i => freq_err_i,
freq_err_stb_p_i => freq_err_stb_p_i,
hpll_ldcr_ld_samp_i => hpll_ldcr_ld_samp_i,
hpll_ldcr_ld_thr_i => hpll_ldcr_ld_thr_i,
hpll_psr_freq_lk_o => hpll_psr_freq_lk_o,
hpll_psr_phase_lk_o => hpll_psr_phase_lk_o,
hpll_psr_lock_lost_i => hpll_psr_lock_lost_i,
hpll_psr_lock_lost_o => hpll_psr_lock_lost_o,
hpll_psr_lock_lost_load_i => hpll_psr_lock_lost_load_i,
freq_mode_o => freq_mode_ld);
-- shared multiplier
multiplier : process (mul_A, mul_B)
begin -- process
mul_OUT <= mul_A * mul_B;
end process;
output_val_unrounded <= output_val(g_integrator_fracbits + g_dacval_bits - 1 downto g_integrator_fracbits);
output_val_round_up <= std_logic(output_val(g_integrator_fracbits - 1));
main_fsm : process (clk_sys_i, rst_n_sysclk_i)
begin -- process
if rising_edge(clk_sys_i) then
if rst_n_sysclk_i = '0' then
i_reg <= (others => '0');
freq_mode <= '1'; -- start in frequency lock mode
pi_state <= HPLL_WAIT_SAMPLE;
dac_val_stb_p_o <= '0';
dac_val_int <= (others => '0');
sync_dividers_p_o <= '0';
freq_mode <= '1';
else
if hpll_pcr_enable_i = '0' then
pi_state <= HPLL_WAIT_SAMPLE;
dac_val_stb_p_o <= '0';
freq_mode <= '1';
else
case pi_state is
-------------------------------------------------------------------------------
-- State: HPLL wait for input sample. When a frequency error (or phase error)
-- sample arrives from the detector, start the PI update.
-------------------------------------------------------------------------------
when HPLL_WAIT_SAMPLE =>
dac_val_stb_p_o <= '0';
hpll_rfifo_wr_req_o <= '0';
-- frequency lock mode, got a frequency sample
if(freq_mode = '1' and freq_err_stb_p_i = '1') then
pi_state <= HPLL_MUL_KI;
mul_A <= signed(freq_err_i);
mul_B <= signed(hpll_fbgr_f_ki_i);
-- phase lock mode, got a phase sample
elsif (freq_mode = '0' and phase_err_stb_p_i = '1') then
pi_state <= HPLL_MUL_KI;
mul_A <= signed(phase_err_i);
mul_B <= signed(hpll_pbgr_p_ki_i);
end if;
-------------------------------------------------------------------------------
-- State: HPLL multiply by Ki: multiples the phase/freq error by an appropriate
-- Kp/Ki coefficient, set up the multipler for (error * Kp) operation.
-------------------------------------------------------------------------------
when HPLL_MUL_KI =>
sync_dividers_p_o <= '0';
if(freq_mode = '1') then
mul_B <= signed(hpll_fbgr_f_kp_i);
else
mul_B <= signed(hpll_pbgr_p_kp_i);
end if;
mul_out_reg <= mul_OUT; -- just keep the result
pi_state <= HPLL_INTEGRATE;
-------------------------------------------------------------------------------
-- State: HPLL integrate: add the (Error * Ki) to the integrator register
-------------------------------------------------------------------------------
when HPLL_INTEGRATE =>
i_reg <= i_reg + mul_out_reg;
pi_state <= HPLL_MUL_KP;
-------------------------------------------------------------------------------
-- State: HPLL multiply by Kp: does the same as HPLL_MUL_KI but for the proportional
-- branch.
-------------------------------------------------------------------------------
when HPLL_MUL_KP =>
mul_out_reg <= mul_OUT;
pi_state <= HPLL_CALC_SUM;
when HPLL_CALC_SUM =>
output_val <= unsigned(c_OUTPUT_BIAS + resize(mul_out_reg, output_val'length) + resize(i_reg, output_val'length));
pi_state <= HPLL_ROUND_SUM;
-------------------------------------------------------------------------------
-- State: HPLL round sum: calculates the final DAC value, with 0.5LSB rounding.
-- Also checks for the frequency lock.
-------------------------------------------------------------------------------
when HPLL_ROUND_SUM =>
dac_val_stb_p_o <= '1';
-- +-0.5 rounding of the output value
if(output_val_round_up = '1') then
dac_val_int <= std_logic_vector(output_val_unrounded + 1);
else
dac_val_int <= std_logic_vector(output_val_unrounded);
end if;
pi_state <= HPLL_WAIT_SAMPLE;
if(hpll_pcr_force_f_i = '0') then
freq_mode <= freq_mode_ld;
else
freq_mode <= '1';
end if;
if(freq_mode = '1' and freq_mode_ld = '0') then
sync_dividers_p_o <= '1';
end if;
hpll_rfifo_wr_req_o <= not hpll_rfifo_wr_full_i;
when others => null;
end case;
end if;
end if;
end if;
end process;
-- record some diagnostic stuff (error, dac val) into a FIFO
hpll_rfifo_fp_mode_o <= freq_mode;
hpll_rfifo_dac_val_o <= dac_val_int;
hpll_rfifo_err_val_o <= phase_err_i when freq_mode = '0' else freq_err_i;
dac_val_o <= dac_val_int;
end behavioral;
-------------------------------------------------------------------------------
-- Title : DMTD Helper PLL (HPLL) - lock detection logic
-- Project : White Rabbit Switch
-------------------------------------------------------------------------------
-- File : hpll_controller.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-06-14
-- Last update: 2010-08-23
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description:
-------------------------------------------------------------------------------
-- Copyright (c) 2010 Tomasz Wlostowski
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-06-14 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity hpll_lock_detect is
port (
rst_n_sysclk_i : std_logic;
clk_sys_i : std_logic;
phase_err_i : in std_logic_vector(11 downto 0);
phase_err_stb_p_i : in std_logic;
freq_err_i : in std_logic_vector(11 downto 0);
freq_err_stb_p_i : in std_logic;
hpll_ldcr_ld_samp_i : in std_logic_vector(7 downto 0);
hpll_ldcr_ld_thr_i : in std_logic_vector(7 downto 0);
-- Flags: frequency lock
hpll_psr_freq_lk_o : out std_logic;
-- Flags: phase lock
hpll_psr_phase_lk_o : out std_logic;
-- Flags: loss-of-lock indicator
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_load_i : in std_logic;
-- PI frequency/phase mode select
freq_mode_o : out std_logic
);
end hpll_lock_detect;
architecture syn of hpll_lock_detect is
type t_lock_detect_state is (LD_WAIT_FREQ_LOCK, LD_WAIT_PHASE_LOCK, LD_LOCKED);
signal ph_err_sign_d0 : std_logic;
signal ph_err_sign : std_logic;
signal ph_err_valid : std_logic;
signal ph_err_duty_cntr : unsigned(7 downto 0);
signal ph_err_lock_cntr : unsigned(7 downto 0);
signal f_err_lock_cntr : unsigned(7 downto 0);
signal phase_lock : std_logic;
signal freq_lock : std_logic;
signal state : t_lock_detect_state;
signal f_err_int : integer;
begin
ph_err_sign <= phase_err_i(phase_err_i'length-1);
lock_detect_phase : process (clk_sys_i, rst_n_sysclk_i)
begin
if rising_edge(clk_sys_i) then
if(rst_n_sysclk_i = '0') then
ph_err_valid <= '0';
ph_err_sign_d0 <= '0';
ph_err_valid <= '0';
ph_err_duty_cntr <= (others => '0');
ph_err_lock_cntr <= (others => '0');
phase_lock <= '0';
else
-- new phase error value arrived
if(phase_err_stb_p_i = '1') then
ph_err_sign_d0 <= ph_err_sign;
-- the sign of the phase error has changed, check how long it will
-- take to flip again
if(ph_err_sign /= ph_err_sign_d0) then
ph_err_duty_cntr <= (others => '0');
-- if the phase error has been changing its sign frequent enough
-- for a given number of samples, we assume the PLL is locked
if(std_logic_vector(ph_err_lock_cntr) = hpll_ldcr_ld_samp_i) then
phase_lock <= '1';
else
ph_err_lock_cntr <= ph_err_lock_cntr + 1;
phase_lock <= '0';
end if;
else
-- if the phase error remains positive or negative for too long,
-- we are out of lock
if(std_logic_vector(ph_err_duty_cntr) = hpll_ldcr_ld_thr_i) then
ph_err_lock_cntr <= (others => '0');
phase_lock <= '0';
else
ph_err_duty_cntr <= ph_err_duty_cntr + 1;
end if;
end if;
end if;
end if;
end if;
end process;
f_err_int <= to_integer(signed(freq_err_i));
lock_detect_freq : process(clk_sys_i, rst_n_sysclk_i)
begin
if rising_edge(clk_sys_i) then
if(rst_n_sysclk_i = '0') then
freq_lock <= '0';
f_err_lock_cntr <= (others => '0');
else
if(freq_err_stb_p_i = '1') then
if(f_err_int > -300 and f_err_int < 300) then
if(std_logic_vector(f_err_lock_cntr) = hpll_ldcr_ld_samp_i) then
freq_lock <= '1';
else
f_err_lock_cntr <= f_err_lock_cntr + 1;
freq_lock <= '0';
end if;
else
f_err_lock_cntr <= (others => '0');
freq_lock <= '0';
end if;
end if;
end if;
end if;
end process;
lock_fsm : process(clk_sys_i, rst_n_sysclk_i)
begin -- process
if rising_edge(clk_sys_i) then
if (rst_n_sysclk_i = '0') then
state <= LD_WAIT_FREQ_LOCK;
freq_mode_o <= '1';
hpll_psr_lock_lost_o <= '0';
else
if(hpll_psr_lock_lost_load_i = '1' and hpll_psr_lock_lost_i = '1') then
hpll_psr_lock_lost_o <= '0';
end if;
case state is
when LD_WAIT_FREQ_LOCK =>
if(freq_lock = '1') then
state <= LD_WAIT_PHASE_LOCK;
freq_mode_o <= '0';
else
freq_mode_o <= '1';
end if;
when LD_WAIT_PHASE_LOCK =>
if(phase_lock = '1') then
state <= LD_LOCKED;
end if;
when LD_LOCKED =>
if(phase_lock = '0' or freq_lock = '0') then
hpll_psr_lock_lost_o <= '1';
end if;
if(phase_lock = '0') then
state <= LD_WAIT_PHASE_LOCK;
elsif freq_lock = '0' then
state <= LD_WAIT_FREQ_LOCK;
end if;
when others => null;
end case;
end if;
end if;
end process;
hpll_psr_phase_lk_o <= phase_lock;
hpll_psr_freq_lk_o <= freq_lock;
end syn;
-------------------------------------------------------------------------------
-- Title : DMTD Helper PLL (HPLL) - linear frequency/period detector.
-- Project : White Rabbit Switch
-------------------------------------------------------------------------------
-- File : hpll_period_detect.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-06-14
-- Last update: 2011-04-08
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: Simple linear frequency detector with programmable error
-- setpoint and gating period. The measured clocks are: clk_ref_i and clk_fbck_i.
-- The error value is outputted every 2^(hpll_fbcr_fd_gate_i + 14) cycles on a
-- freq_err_o. A pulse is produced on freq_err_stb_p_o every time freq_err_o
-- is updated with a new value. freq_err_o value is:
-- - positive when clk_fbck_i is slower than selected frequency setpoint
-- - negative when clk_fbck_i is faster than selected frequency setpoint
-------------------------------------------------------------------------------
-- Copyright (c) 2010 Tomasz Wlostowski
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2010-06-14 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.common_components.all;
entity hpll_period_detect is
generic(
g_freq_err_frac_bits: integer);
port (
-------------------------------------------------------------------------------
-- Clocks & resets
-------------------------------------------------------------------------------
-- reference clocks
clk_ref_i : in std_logic;
-- fed-back (VCO) clock
clk_fbck_i : in std_logic;
-- system clock (wishbone and I/O)
clk_sys_i : in std_logic;
-- reset signals (the same reset synced to different clocks)
rst_n_refclk_i : in std_logic;
rst_n_fbck_i : in std_logic;
rst_n_sysclk_i : in std_logic;
-------------------------------------------------------------------------------
-- Outputs
-------------------------------------------------------------------------------
-- frequency error value (signed)
freq_err_o : out std_logic_vector(11 downto 0);
-- frequency error valid pulse
freq_err_stb_p_o : out std_logic;
-------------------------------------------------------------------------------
-- Wishbone regs
-------------------------------------------------------------------------------
-- gating period:
hpll_fbcr_fd_gate_i : in std_logic_vector(2 downto 0);
-- frequency error setpoint:
hpll_fbcr_ferr_set_i : in std_logic_vector(11 downto 0)
);
end hpll_period_detect;
architecture rtl of hpll_period_detect is
-- derived from the maximum gating period (2 ^ 21 + 1 "safety" bit)
constant c_COUNTER_BITS : integer := 22;
-- number of fractional bits in the frequency error output
-- constant c_FREQ_ERR_FRAC_BITS : integer := 7;
-- frequency counters: feedback clock & gating counter
signal counter_fb : unsigned(c_COUNTER_BITS-1 downto 0);
signal counter_gate : unsigned(c_COUNTER_BITS-1 downto 0);
-- clock domain synchronization stuff...
signal gate_sreg : std_logic_vector(3 downto 0);
signal pstb_sreg : std_logic_vector(3 downto 0);
signal gate_p, period_p : std_logic;
signal gate_cntr_bitsel : std_logic;
signal desired_freq : unsigned(c_COUNTER_BITS-1 downto 0);
signal cur_freq : unsigned(c_COUNTER_BITS-1 downto 0);
signal delta_f: signed(11 downto 0);
begin -- rtl
-- decoding FD gating field from FBCR register:
decode_fd_gating : process(hpll_fbcr_fd_gate_i, counter_gate)
begin
case hpll_fbcr_fd_gate_i is
when "000" => gate_cntr_bitsel <= std_logic(counter_gate(14)); -- div: 16384
desired_freq <= to_unsigned(16384, desired_freq'length);
when "001" => gate_cntr_bitsel <= std_logic(counter_gate(15)); -- ....
desired_freq <= to_unsigned(32768, desired_freq'length);
when "010" => gate_cntr_bitsel <= std_logic(counter_gate(16));
desired_freq <= to_unsigned(65536, desired_freq'length);
when "011" => gate_cntr_bitsel <= std_logic(counter_gate(17));
desired_freq <= to_unsigned(131072, desired_freq'length);
when "100" => gate_cntr_bitsel <= std_logic(counter_gate(18));
desired_freq <= to_unsigned(262144, desired_freq'length);
when "101" => gate_cntr_bitsel <= std_logic(counter_gate(19));
desired_freq <= to_unsigned(524288, desired_freq'length);
when "110" => gate_cntr_bitsel <= std_logic(counter_gate(20)); -- ....
desired_freq <= to_unsigned(1048576, desired_freq'length);
when "111" => gate_cntr_bitsel <= std_logic(counter_gate(21)); -- div: 2097152
desired_freq <= to_unsigned(2097152, desired_freq'length);
when others => null;
end case;
end process;
-------------------------------------------------------------------------------
-- Gating counter: produces a gating pulse on gate_p (clk_fbck_i domain) with
-- period configured by FD_GATE field in FBCR register
-------------------------------------------------------------------------------
gating_counter : process(clk_ref_i, rst_n_refclk_i)
begin
if rising_edge(clk_ref_i) then
if(rst_n_refclk_i = '0') then
counter_gate <= to_unsigned(1, counter_gate'length);
gate_sreg <= (others => '0');
else
if(gate_cntr_bitsel = '1') then
-- counter bit selected by hpll_fbcr_fd_gate_i changed from 0 to 1?
-- reset the counter and generate the gating signal for feedback counter
counter_gate <= to_unsigned(1, counter_gate'length);
gate_sreg <= (others => '1');
else
-- advance the counter and generate a longer pulse on gating signal
-- using a shift register so the sync chain will always work regardless of
-- the clock frequency.
counter_gate <= counter_gate + 1;
gate_sreg <= '0' & gate_sreg(gate_sreg'length-1 downto 1);
end if;
end if;
end if;
end process;
-- sync logic for the gate_p pulse (from clk_ref_i to clk_fbck_i)
sync_gating_pulse : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_fbck_i,
rst_n_i => rst_n_fbck_i,
data_i => gate_sreg(0),
synced_o => open,
npulse_o => open,
ppulse_o => gate_p);
-------------------------------------------------------------------------------
-- Main period/frequency measurement process: Takes a snapshot of the counter_fb
-- every time there's a pulse on gate_p. The capture of new frequency value
-- is indicated by pulsing period_p.
-------------------------------------------------------------------------------
period_detect : process(clk_fbck_i, rst_n_fbck_i)
begin
if rising_edge(clk_fbck_i) then
if rst_n_fbck_i = '0' then
counter_fb <= to_unsigned(1, counter_fb'length);
cur_freq <= (others => '0');
pstb_sreg <= (others => '0');
else
if(gate_p = '1') then
counter_fb <= to_unsigned(1, counter_fb'length);
cur_freq <= counter_fb;
pstb_sreg <= (others => '1');
else
counter_fb <= counter_fb + 1;
pstb_sreg <= '0' & pstb_sreg(pstb_sreg'length-1 downto 1);
end if;
end if;
end if;
end process;
-- synchronization logic for period_p (from clk_fbck_i to clk_sys_i)
sync_period_pulse : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_sys_i,
rst_n_i => rst_n_sysclk_i,
data_i => pstb_sreg(0),
synced_o => open,
npulse_o => open,
ppulse_o => period_p);
-- calculate the frequency difference, padded by some fractional bits
delta_f <= resize(signed(desired_freq) - signed(cur_freq), delta_f'length-g_freq_err_frac_bits) & to_signed(0, g_freq_err_frac_bits);
-------------------------------------------------------------------------------
-- Calculates the phase error by taking the difference between reference and
-- measured frequency and subtracting the error setpoint from FERR_SET field
-- in FBCR register.
-------------------------------------------------------------------------------
freq_err_output : process(clk_sys_i, rst_n_sysclk_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_sysclk_i = '0' then
freq_err_stb_p_o <= '0';
freq_err_o <= (others => '0');
else
if(period_p = '1') then
freq_err_o <= std_logic_vector(resize(delta_f - signed (hpll_fbcr_ferr_set_i), freq_err_o'length));
end if;
freq_err_stb_p_o <= period_p;
end if;
end if;
end process;
end rtl;
-- -*- Mode: LUA; tab-width: 2 -*-
peripheral
{
name = "DMTD Helper PLL";
description = "PLL controller for generating the DMTD offset clock.";
prefix = "HPLL";
hdl_entity = "hpll_wb_slave";
reg {
name = "HPLL Control Register";
description = "HPLL Control register";
prefix = "PCR";
field {
name = "PLL Enable";
description = "1: PLL is enabled \
0: PLL is disabled";
type = BIT;
prefix = "ENABLE";
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "PLL Force Freq mode";
type = BIT;
prefix = "FORCE_F";
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "DAC serial clock select";
description = "Selects the DAC serial clock frequency: \
0: f = refclk / 8 (~ 16 MHz) \
1: f = refclk / 16 (~ 8 MHz) \
2: f = refclk / 32 (~ 4 MHz) \
3: f = refclk / 64 (~ 2 MHz) \
4: f = refclk / 128 (~ 1 MHz) \
5: f = refclk / 256 (~ 500 kHz) \
6: f = refclk / 512 (~ 250 kHz) \
7: f = refclk / 1024 (~ 125 kHz)";
prefix = "DAC_CLKSEL";
align = 4;
type = SLV;
size = 3;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Phase detector gating period";
description = "Gating period for the phase detector: \
0: period = 1024 \
1: period = 2048 \
2: period = 4096 \
3: period = 8192 \
4: period = 16384 \
5: period = 32768 \
6: period = 65536 \
7: period = 131072";
prefix = "PD_GATE";
type = SLV;
size = 3;
align = 4;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Reference clock input select";
description = "00: local reference (from TCXO)\
01: uplink 0 recovered clock\
10: uplink 1 recovered clock";
size = 2;
type = SLV;
prefix = "REFSEL";
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "PLL Reset";
descritpion = "write 1: causes PLL reset\nwrite 0: no effect";
type = MONOSTABLE;
prefix = "SWRST";
access_bus = READ_WRITE;
access_dev = READ_ONLY;
align=31;
};
};
reg {
name = "HPLL Divider Register";
description = "Register controlling the frequency PLL frequency divider. The output frequency is f_ref * (DIV_FB / DIV_REF)";
prefix = "DIVR";
field {
name = "Reference divider";
prefix = "DIV_REF";
size = 16;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Feedback divider";
prefix = "DIV_FB";
size = 16;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "HPLL Frequency Branch Gain Register";
description = "Register containing the PI gain factors for the frequency branch.";
prefix = "FBGR";
field {
name = "Proportional gain (Kp)";
prefix = "F_KP";
size = 16;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Integral gain (Ki)";
prefix = "F_KI";
size = 16;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "HPLL Phase Branch Gain Register";
prefix = "PBGR";
field {
name = "Proportional gain (Kp)";
prefix = "P_KP";
size = 16;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Integral gain (Ki)";
prefix = "P_KI";
size = 16;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "HPLL Lock Detect Control Register";
prefix = "LDCR";
field {
name = "Phase Lock detect threshold";
prefix = "LD_THR";
description = "A maximum time between bang-bang PD phase error sign changes that keeps the PLL locked";
type = SLV;
size = 8;
align = 4;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Lock detect samples";
prefix = "LD_SAMP";
description = "Number of subsequent phase error samples smaller than LD_THR or frequency error samples in (-1, 1) after which the PLL assumes to be locked.";
type =SLV;
size = 8;
align = 8;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "HPLL Frequency branch control register";
prefix = "FBCR";
field {
name = "Frequency detector gating period";
description = "Gating period for the frequency detector: \
0: period = 16384 \
1: period = 32768 \
2: period = 65536 \
3: period = 131072 \
4: period = 262144 \
5: period = 524288 \
6: period = 1048576 \
7: period = 2097152";
prefix = "FD_GATE";
type = SLV;
size = 3;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
align =4;
};
field {
name = "Frequency error setpoint";
description = "Value of desired frequency error in the lock state. Computed as: f_err = FD_GATE[real value] * (1 - (N / (N+DELTA)))";
prefix = "FERR_SET";
align = 4;
size = 12;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "HPLL Status Register";
description = "Register containing the current status of the PLL";
prefix = "PSR";
field {
name = "Frequency lock";
type = BIT;
prefix = "FREQ_LK";
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "Phase lock";
type = BIT;
prefix = "PHASE_LK";
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "Loss-of-lock indicator";
description = "read 0: PLL is locked\
read 1: PLL has lost the lock since the last poll of this bit\
write 0: no effect\
write 1: clears the field";
type = BIT;
prefix = "LOCK_LOST";
access_bus = READ_WRITE;
access_dev = READ_WRITE;
load = LOAD_EXT;
};
};
fifo_reg {
name = "HPLL Phase/Output record FIFO";
description = "A FIFO recording the phase/freq error, the DAC output and other PLL parameters for debugging/optimization purposes";
prefix = "RFIFO";
direction = CORE_TO_BUS;
size = 1024;
flags_bus = {FIFO_EMPTY};
flags_dev = {FIFO_FULL};
field {
name = "Freq/phase error";
description = "Current frequency/phase error value";
prefix = "ERR_VAL";
type = SLV;
size = 12;
};
field {
name = "Freq/phase mode";
description = "1: frequency mode operation,\n 0: phase mode operation";
prefix = "FP_MODE";
type = BIT;
align = 15;
size = 1;
};
field {
name = "DAC output";
description = "Current DAC output value";
prefix = "DAC_VAL";
type = SLV;
size = 16;
align = 16;
};
};
};
\ No newline at end of file
---------------------------------------------------------------------------------------
-- Title : Wishbone slave core for DMTD Helper PLL
---------------------------------------------------------------------------------------
-- File : hpll_wb_slave.vhd
-- Author : auto-generated by wbgen2 from hpll_wb.wb
-- Created : Mon Jun 21 14:16:43 2010
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE hpll_wb.wb
-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library wbgen2;
use wbgen2.wbgen2_pkg.all;
entity hpll_wb_slave is
port (
rst_n_i : in std_logic;
wb_clk_i : in std_logic;
wb_addr_i : in std_logic_vector(3 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
-- Port for BIT field: 'PLL Enable' in reg: 'HPLL Control Register'
hpll_pcr_enable_o : out std_logic;
-- Port for BIT field: 'PLL Force Freq mode' in reg: 'HPLL Control Register'
hpll_pcr_force_f_o : out std_logic;
-- Port for std_logic_vector field: 'DAC serial clock select' in reg: 'HPLL Control Register'
hpll_pcr_dac_clksel_o : out std_logic_vector(2 downto 0);
-- Port for std_logic_vector field: 'Phase detector gating period' in reg: 'HPLL Control Register'
hpll_pcr_pd_gate_o : out std_logic_vector(2 downto 0);
-- Port for std_logic_vector field: 'Reference clock input select' in reg: 'HPLL Control Register'
hpll_pcr_refsel_o : out std_logic_vector(1 downto 0);
-- Port for MONOSTABLE field: 'PLL Reset' in reg: 'HPLL Control Register'
hpll_pcr_swrst_o : out std_logic;
-- Port for std_logic_vector field: 'Reference divider' in reg: 'HPLL Divider Register'
hpll_divr_div_ref_o : out std_logic_vector(15 downto 0);
-- Port for std_logic_vector field: 'Feedback divider' in reg: 'HPLL Divider Register'
hpll_divr_div_fb_o : out std_logic_vector(15 downto 0);
-- Port for std_logic_vector field: 'Proportional gain (Kp)' in reg: 'HPLL Frequency Branch Gain Register'
hpll_fbgr_f_kp_o : out std_logic_vector(15 downto 0);
-- Port for std_logic_vector field: 'Integral gain (Ki)' in reg: 'HPLL Frequency Branch Gain Register'
hpll_fbgr_f_ki_o : out std_logic_vector(15 downto 0);
-- Port for std_logic_vector field: 'Proportional gain (Kp)' in reg: 'HPLL Phase Branch Gain Register'
hpll_pbgr_p_kp_o : out std_logic_vector(15 downto 0);
-- Port for std_logic_vector field: 'Integral gain (Ki)' in reg: 'HPLL Phase Branch Gain Register'
hpll_pbgr_p_ki_o : out std_logic_vector(15 downto 0);
-- Port for std_logic_vector field: 'Phase Lock detect threshold' in reg: 'HPLL Lock Detect Control Register'
hpll_ldcr_ld_thr_o : out std_logic_vector(7 downto 0);
-- Port for std_logic_vector field: 'Lock detect samples' in reg: 'HPLL Lock Detect Control Register'
hpll_ldcr_ld_samp_o : out std_logic_vector(7 downto 0);
-- Port for std_logic_vector field: 'Frequency detector gating period' in reg: 'HPLL Frequency branch control register'
hpll_fbcr_fd_gate_o : out std_logic_vector(2 downto 0);
-- Port for std_logic_vector field: 'Frequency error setpoint' in reg: 'HPLL Frequency branch control register'
hpll_fbcr_ferr_set_o : out std_logic_vector(11 downto 0);
-- Port for BIT field: 'Frequency lock' in reg: 'HPLL Status Register'
hpll_psr_freq_lk_i : in std_logic;
-- Port for BIT field: 'Phase lock' in reg: 'HPLL Status Register'
hpll_psr_phase_lk_i : in std_logic;
-- Ports for BIT field: 'Loss-of-lock indicator' in reg: 'HPLL Status Register'
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_load_o : out std_logic;
-- FIFO write request
hpll_rfifo_wr_req_i : in std_logic;
-- FIFO full flag
hpll_rfifo_wr_full_o : out std_logic;
hpll_rfifo_err_val_i : in std_logic_vector(11 downto 0);
hpll_rfifo_fp_mode_i : in std_logic;
hpll_rfifo_dac_val_i : in std_logic_vector(15 downto 0)
);
end hpll_wb_slave;
architecture syn of hpll_wb_slave is
signal hpll_pcr_enable_int : std_logic ;
signal hpll_pcr_force_f_int : std_logic ;
signal hpll_pcr_dac_clksel_int : std_logic_vector(2 downto 0);
signal hpll_pcr_pd_gate_int : std_logic_vector(2 downto 0);
signal hpll_pcr_refsel_int : std_logic_vector(1 downto 0);
signal hpll_pcr_swrst_dly0 : std_logic ;
signal hpll_pcr_swrst_int : std_logic ;
signal hpll_divr_div_ref_int : std_logic_vector(15 downto 0);
signal hpll_divr_div_fb_int : std_logic_vector(15 downto 0);
signal hpll_fbgr_f_kp_int : std_logic_vector(15 downto 0);
signal hpll_fbgr_f_ki_int : std_logic_vector(15 downto 0);
signal hpll_pbgr_p_kp_int : std_logic_vector(15 downto 0);
signal hpll_pbgr_p_ki_int : std_logic_vector(15 downto 0);
signal hpll_ldcr_ld_thr_int : std_logic_vector(7 downto 0);
signal hpll_ldcr_ld_samp_int : std_logic_vector(7 downto 0);
signal hpll_fbcr_fd_gate_int : std_logic_vector(2 downto 0);
signal hpll_fbcr_ferr_set_int : std_logic_vector(11 downto 0);
signal hpll_rfifo_in_int : std_logic_vector(28 downto 0);
signal hpll_rfifo_out_int : std_logic_vector(28 downto 0);
signal hpll_rfifo_rdreq_int : std_logic ;
signal hpll_rfifo_rdreq_int_d0 : std_logic ;
signal hpll_rfifo_empty_int : std_logic ;
signal ack_sreg : std_logic_vector(9 downto 0);
signal rddata_reg : std_logic_vector(31 downto 0);
signal wrdata_reg : std_logic_vector(31 downto 0);
signal bwsel_reg : std_logic_vector(3 downto 0);
signal rwaddr_reg : std_logic_vector(3 downto 0);
signal ack_in_progress : std_logic ;
signal wr_int : std_logic ;
signal rd_int : std_logic ;
signal bus_clock_int : std_logic ;
signal allones : std_logic_vector(31 downto 0);
signal allzeros : std_logic_vector(31 downto 0);
begin
-- Some internal signals assignments. For (foreseen) compatibility with other bus standards.
wrdata_reg <= wb_data_i;
bwsel_reg <= wb_sel_i;
bus_clock_int <= wb_clk_i;
rd_int <= wb_cyc_i and (wb_stb_i and (not wb_we_i));
wr_int <= wb_cyc_i and (wb_stb_i and wb_we_i);
allones <= (others => '1');
allzeros <= (others => '0');
--
-- Main register bank access process.
process (bus_clock_int, rst_n_i)
begin
if (rst_n_i = '0') then
ack_sreg <= "0000000000";
ack_in_progress <= '0';
rddata_reg <= "00000000000000000000000000000000";
hpll_pcr_enable_int <= '0';
hpll_pcr_force_f_int <= '0';
hpll_pcr_dac_clksel_int <= "000";
hpll_pcr_pd_gate_int <= "000";
hpll_pcr_refsel_int <= "00";
hpll_pcr_swrst_int <= '0';
hpll_divr_div_ref_int <= "0000000000000000";
hpll_divr_div_fb_int <= "0000000000000000";
hpll_fbgr_f_kp_int <= "0000000000000000";
hpll_fbgr_f_ki_int <= "0000000000000000";
hpll_pbgr_p_kp_int <= "0000000000000000";
hpll_pbgr_p_ki_int <= "0000000000000000";
hpll_ldcr_ld_thr_int <= "00000000";
hpll_ldcr_ld_samp_int <= "00000000";
hpll_fbcr_fd_gate_int <= "000";
hpll_fbcr_ferr_set_int <= "000000000000";
hpll_psr_lock_lost_load_o <= '0';
hpll_rfifo_rdreq_int <= '0';
elsif rising_edge(bus_clock_int) then
-- advance the ACK generator shift register
ack_sreg(8 downto 0) <= ack_sreg(9 downto 1);
ack_sreg(9) <= '0';
if (ack_in_progress = '1') then
if (ack_sreg(0) = '1') then
hpll_pcr_swrst_int <= '0';
hpll_psr_lock_lost_load_o <= '0';
ack_in_progress <= '0';
else
hpll_psr_lock_lost_load_o <= '0';
end if;
else
if ((wb_cyc_i = '1') and (wb_stb_i = '1')) then
case rwaddr_reg(3 downto 0) is
when "0000" =>
if (wb_we_i = '1') then
hpll_pcr_enable_int <= wrdata_reg(0);
hpll_pcr_force_f_int <= wrdata_reg(1);
hpll_pcr_dac_clksel_int <= wrdata_reg(6 downto 4);
hpll_pcr_pd_gate_int <= wrdata_reg(10 downto 8);
hpll_pcr_refsel_int <= wrdata_reg(12 downto 11);
hpll_pcr_swrst_int <= wrdata_reg(31);
else
rddata_reg(0) <= hpll_pcr_enable_int;
rddata_reg(1) <= hpll_pcr_force_f_int;
rddata_reg(6 downto 4) <= hpll_pcr_dac_clksel_int;
rddata_reg(10 downto 8) <= hpll_pcr_pd_gate_int;
rddata_reg(12 downto 11) <= hpll_pcr_refsel_int;
rddata_reg(2) <= 'X';
rddata_reg(3) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
end if;
ack_sreg(2) <= '1';
ack_in_progress <= '1';
when "0001" =>
if (wb_we_i = '1') then
hpll_divr_div_ref_int <= wrdata_reg(15 downto 0);
hpll_divr_div_fb_int <= wrdata_reg(31 downto 16);
else
rddata_reg(15 downto 0) <= hpll_divr_div_ref_int;
rddata_reg(31 downto 16) <= hpll_divr_div_fb_int;
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "0010" =>
if (wb_we_i = '1') then
hpll_fbgr_f_kp_int <= wrdata_reg(15 downto 0);
hpll_fbgr_f_ki_int <= wrdata_reg(31 downto 16);
else
rddata_reg(15 downto 0) <= hpll_fbgr_f_kp_int;
rddata_reg(31 downto 16) <= hpll_fbgr_f_ki_int;
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "0011" =>
if (wb_we_i = '1') then
hpll_pbgr_p_kp_int <= wrdata_reg(15 downto 0);
hpll_pbgr_p_ki_int <= wrdata_reg(31 downto 16);
else
rddata_reg(15 downto 0) <= hpll_pbgr_p_kp_int;
rddata_reg(31 downto 16) <= hpll_pbgr_p_ki_int;
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "0100" =>
if (wb_we_i = '1') then
hpll_ldcr_ld_thr_int <= wrdata_reg(7 downto 0);
hpll_ldcr_ld_samp_int <= wrdata_reg(15 downto 8);
else
rddata_reg(7 downto 0) <= hpll_ldcr_ld_thr_int;
rddata_reg(15 downto 8) <= hpll_ldcr_ld_samp_int;
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "0101" =>
if (wb_we_i = '1') then
hpll_fbcr_fd_gate_int <= wrdata_reg(2 downto 0);
hpll_fbcr_ferr_set_int <= wrdata_reg(15 downto 4);
else
rddata_reg(2 downto 0) <= hpll_fbcr_fd_gate_int;
rddata_reg(15 downto 4) <= hpll_fbcr_ferr_set_int;
rddata_reg(3) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "0110" =>
if (wb_we_i = '1') then
hpll_psr_lock_lost_load_o <= '1';
else
rddata_reg(0) <= hpll_psr_freq_lk_i;
rddata_reg(1) <= hpll_psr_phase_lk_i;
rddata_reg(2) <= hpll_psr_lock_lost_i;
rddata_reg(3) <= 'X';
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "0111" =>
if (wb_we_i = '1') then
else
if (hpll_rfifo_rdreq_int_d0 = '0') then
hpll_rfifo_rdreq_int <= not hpll_rfifo_rdreq_int;
else
rddata_reg(11 downto 0) <= hpll_rfifo_out_int(11 downto 0);
rddata_reg(15) <= hpll_rfifo_out_int(12);
rddata_reg(31 downto 16) <= hpll_rfifo_out_int(28 downto 13);
ack_in_progress <= '1';
ack_sreg(0) <= '1';
end if;
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
end if;
when "1000" =>
if (wb_we_i = '1') then
else
rddata_reg(17) <= hpll_rfifo_empty_int;
rddata_reg(0) <= 'X';
rddata_reg(1) <= 'X';
rddata_reg(2) <= 'X';
rddata_reg(3) <= 'X';
rddata_reg(4) <= 'X';
rddata_reg(5) <= 'X';
rddata_reg(6) <= 'X';
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when others =>
-- prevent the slave from hanging the bus on invalid address
ack_in_progress <= '1';
ack_sreg(0) <= '1';
end case;
end if;
end if;
end if;
end process;
-- Drive the data output bus
wb_data_o <= rddata_reg;
-- PLL Enable
hpll_pcr_enable_o <= hpll_pcr_enable_int;
-- PLL Force Freq mode
hpll_pcr_force_f_o <= hpll_pcr_force_f_int;
-- DAC serial clock select
hpll_pcr_dac_clksel_o <= hpll_pcr_dac_clksel_int;
-- Phase detector gating period
hpll_pcr_pd_gate_o <= hpll_pcr_pd_gate_int;
-- Reference clock input select
hpll_pcr_refsel_o <= hpll_pcr_refsel_int;
-- PLL Reset
process (bus_clock_int, rst_n_i)
begin
if (rst_n_i = '0') then
hpll_pcr_swrst_dly0 <= '0';
hpll_pcr_swrst_o <= '0';
elsif rising_edge(bus_clock_int) then
hpll_pcr_swrst_dly0 <= hpll_pcr_swrst_int;
hpll_pcr_swrst_o <= hpll_pcr_swrst_int and (not hpll_pcr_swrst_dly0);
end if;
end process;
-- Reference divider
hpll_divr_div_ref_o <= hpll_divr_div_ref_int;
-- Feedback divider
hpll_divr_div_fb_o <= hpll_divr_div_fb_int;
-- Proportional gain (Kp)
hpll_fbgr_f_kp_o <= hpll_fbgr_f_kp_int;
-- Integral gain (Ki)
hpll_fbgr_f_ki_o <= hpll_fbgr_f_ki_int;
-- Proportional gain (Kp)
hpll_pbgr_p_kp_o <= hpll_pbgr_p_kp_int;
-- Integral gain (Ki)
hpll_pbgr_p_ki_o <= hpll_pbgr_p_ki_int;
-- Phase Lock detect threshold
hpll_ldcr_ld_thr_o <= hpll_ldcr_ld_thr_int;
-- Lock detect samples
hpll_ldcr_ld_samp_o <= hpll_ldcr_ld_samp_int;
-- Frequency detector gating period
hpll_fbcr_fd_gate_o <= hpll_fbcr_fd_gate_int;
-- Frequency error setpoint
hpll_fbcr_ferr_set_o <= hpll_fbcr_ferr_set_int;
-- Frequency lock
-- Phase lock
-- Loss-of-lock indicator
hpll_psr_lock_lost_o <= wrdata_reg(2);
-- extra code for reg/fifo/mem: HPLL Phase/Output record FIFO
hpll_rfifo_in_int(11 downto 0) <= hpll_rfifo_err_val_i;
hpll_rfifo_in_int(12) <= hpll_rfifo_fp_mode_i;
hpll_rfifo_in_int(28 downto 13) <= hpll_rfifo_dac_val_i;
hpll_rfifo_INST : wbgen2_fifo_sync
generic map (
g_size => 1024,
g_width => 29,
g_usedw_size => 10
)
port map (
wr_req_i => hpll_rfifo_wr_req_i,
wr_full_o => hpll_rfifo_wr_full_o,
rd_full_o => open,
rd_empty_o => hpll_rfifo_empty_int,
rd_usedw_o => open,
rd_req_i => hpll_rfifo_rdreq_int,
clk_i => bus_clock_int,
wr_data_i => hpll_rfifo_in_int,
rd_data_o => hpll_rfifo_out_int
);
-- extra code for reg/fifo/mem: FIFO 'HPLL Phase/Output record FIFO' data output register 0
process (bus_clock_int, rst_n_i)
begin
if (rst_n_i = '0') then
hpll_rfifo_rdreq_int_d0 <= '0';
elsif rising_edge(bus_clock_int) then
hpll_rfifo_rdreq_int_d0 <= hpll_rfifo_rdreq_int;
end if;
end process;
rwaddr_reg <= wb_addr_i;
-- ACK signal generation. Just pass the LSB of ACK counter.
wb_ack_o <= ack_sreg(0);
end syn;
files = [ "hpll_controller.vhd",
"wrsw_helper_pll.vhd",
"hpll_lock_detect.vhd",
"hpll_bangbang_pd.vhd",
"hpll_wb_slave.vhd",
"hpll_period_detect.vhd",
"wr_helper_pll.vhd"];
-------------------------------------------------------------------------------
-- Title : Serial DAC interface
-- Project : White Rabbit Switch
-------------------------------------------------------------------------------
-- File : serial_dac.vhd
-- Author : paas, slayer
-- Company : CERN BE-Co-HT
-- Created : 2010-02-25
-- Last update: 2010-06-21
-- Platform : fpga-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: The dac unit provides an interface to a 16 bit serial Digita to Analogue converter (max5441, SPI?/QSPI?/MICROWIRE? compatible)
--
-------------------------------------------------------------------------------
-- Copyright (c) 2010 CERN
-------------------------------------------------------------------------------
-- Revisions :1
-- Date Version Author Description
-- 2009-01-24 1.0 paas Created
-- 2010-02-25 1.1 slayer Modified for rev 1.1 switch
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity serial_dac is
generic (
g_num_data_bits : integer := 16;
g_num_extra_bits : integer := 8
);
port (
-- clock & reset
clk_i : in std_logic;
rst_n_i : in std_logic;
-- channel 1 value and value load strobe
value1_i : in std_logic_vector(g_num_data_bits-1 downto 0);
value1_stb_i : in std_logic;
-- channel 2 value and value load strobe
value2_i : in std_logic_vector(g_num_data_bits-1 downto 0);
value2_stb_i : in std_logic;
-- channel select: 0 = channel 1, 1 = channel 2
driver_sel_i : in std_logic;
-- SCLK divider: 000 = clk_i/8 ... 111 = clk_i/1024
sclk_divsel_i : in std_logic_vector(2 downto 0);
-- DAC I/F
dac_cs_n_o : out std_logic;
dac_sclk_o : out std_logic;
dac_sdata_o : out std_logic
);
end serial_dac;
architecture syn of serial_dac is
signal divider : unsigned(11 downto 0);
signal dataSh : std_logic_vector(g_num_data_bits + g_num_extra_bits-1 downto 0);
signal bitCounter : std_logic_vector(g_num_data_bits + g_num_extra_bits+1 downto 0);
signal endSendingData : std_logic;
signal sendingData : std_logic;
signal iDacClk : std_logic;
signal iValidValue : std_logic;
signal divider_muxed : std_logic;
begin
select_divider : process (divider, sclk_divsel_i)
begin -- process
case sclk_divsel_i is
when "000" => divider_muxed <= divider(1); -- sclk = clk_i/8
when "001" => divider_muxed <= divider(2); -- sclk = clk_i/16
when "010" => divider_muxed <= divider(3); -- sclk = clk_i/32
when "011" => divider_muxed <= divider(4); -- sclk = clk_i/64
when "100" => divider_muxed <= divider(5); -- sclk = clk_i/128
when "101" => divider_muxed <= divider(6); -- sclk = clk_i/256
when "110" => divider_muxed <= divider(7); -- sclk = clk_i/512
when "111" => divider_muxed <= divider(8); -- sclk = clk_i/1024
when others => null;
end case;
end process;
iValidValue <= value1_stb_i when driver_sel_i = '0' else value2_stb_i;
process(clk_i, rst_n_i)
begin
if rst_n_i = '0' then
sendingData <= '0';
elsif rising_edge(clk_i) then
if iValidValue = '1' and sendingData = '0' then
sendingData <= '1';
elsif endSendingData = '1' then
sendingData <= '0';
end if;
end if;
end process;
process(clk_i)
begin
if rising_edge(clk_i) then
if iValidValue = '1' then
divider <= (others => '0');
elsif sendingData = '1' then
if(divider_muxed = '1') then
divider <= (others => '0');
else
divider <= divider + 1;
end if;
elsif endSendingData = '1' then
divider <= (others => '0');
end if;
end if;
end process;
process(clk_i, rst_n_i)
begin
if rst_n_i = '0' then
iDacClk <= '1'; -- 0
elsif rising_edge(clk_i) then
if iValidValue = '1' then
iDacClk <= '1'; -- 0
elsif divider_muxed = '1' then
iDacClk <= not(iDacClk);
elsif endSendingData = '1' then
iDacClk <= '1'; -- 0
end if;
end if;
end process;
process(clk_i, rst_n_i)
begin
if rst_n_i = '0' then
dataSh <= (others => '0');
elsif rising_edge(clk_i) then
if iValidValue = '1' and sendingData = '0' then
if driver_sel_i = '1' then
dataSh <= std_logic_vector(to_unsigned(0, g_num_extra_bits)) & value2_i;
else
dataSh <= std_logic_vector(to_unsigned(0, g_num_extra_bits)) & value1_i;
end if;
elsif sendingData = '1' and divider_muxed = '1' and iDacClk = '0' then
dataSh(0) <= dataSh(dataSh'left);
dataSh(dataSh'left downto 1) <= dataSh(dataSh'left - 1 downto 0);
end if;
end if;
end process;
process(clk_i)
begin
if rising_edge(clk_i) then
if iValidValue = '1' and sendingData = '0' then
bitCounter(0) <= '1';
bitCounter(bitCounter'left downto 1) <= (others => '0');
elsif sendingData = '1' and to_integer(divider) = 0 and iDacClk = '1' then
bitCounter(0) <= '0';
bitCounter(bitCounter'left downto 1) <= bitCounter(bitCounter'left - 1 downto 0);
end if;
end if;
end process;
endSendingData <= bitCounter(bitCounter'left);
dac_sdata_o <= dataSh(dataSh'left);
dac_cs_n_o <= not(sendingData);
dac_sclk_o <= iDacClk;
end syn;
-------------------------------------------------------------------------------
-- Project : Helper PLL for generation of DMTD offset clock
-------------------------------------------------------------------------------
-- File : wr_helper_pll.vhd
-- Author : Javier Serrano, Tomasz Wlostowski
-- Institute : CERN
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: This is a generic PLL that assumes a DAC and VCO outside the
-- FPGA. The reset is assumed to be synchronized with the system clock outside
-- this block. The block receives a reference clock of frequency f and derives
-- from it a clock of frequency f*(num/den) where num and den are two 16-bit
-- unsigned numbers. The PI loop filter has controllable proportional and
-- integral gains which are also 16-bit unsigned. The output to the DAC is a
-- 16-bit signed number.
-------------------------------------------------------------------------------
-- Revisions:
-- Date Version Author Description
-- 4 April 2010 1.0 J.Serrano Created
-- 15 June 2010 1.1 twlostow redesigned....
-- 12 Jan 2011 1.2 twlostow added generic configuration options
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.platform_specific.all;
use work.common_components.all;
entity wr_helper_pll is
generic (
g_num_ref_inputs : integer := 1;
g_with_wishbone : integer := 1;
g_dacval_bits : integer := 16;
g_output_bias : integer := 32767;
g_div_ref : integer := 0;
g_div_fb : integer := 0;
g_kp_freq : integer := 0;
g_ki_freq : integer := 0;
g_kp_phase : integer := 0;
g_ki_phase : integer := 0;
g_ld_threshold : integer := 0;
g_ld_samples : integer := 0;
g_fd_gating : integer := 0;
g_pd_gating : integer := 0;
g_ferr_setpoint : integer := 0
);
port (
rst_n_i : in std_logic; -- Synchronous reset
cfg_enable_i : in std_logic;
cfg_force_freq_i : in std_logic;
cfg_clear_status_i : in std_logic;
cfg_refsel_i : in std_logic_vector(1 downto 0);
stat_flock_o : out std_logic;
stat_plock_o : out std_logic;
stat_lock_lost_o : out std_logic;
clk_ref_i : in std_logic_vector(g_num_ref_inputs-1 downto 0);
clk_sys_i : in std_logic; -- System clock
clk_fbck_i : in std_logic; -- Fed-back clock
dac_data_o : out std_logic_vector(g_dacval_bits-1 downto 0);
dac_load_p1_o : out std_logic;
auxout1_o : out std_logic;
auxout2_o : out std_logic;
auxout3_o : out std_logic;
wb_addr_i : in std_logic_vector(3 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic
);
end wr_helper_pll;
architecture rtl of wr_helper_pll is
component hpll_wb_slave
port (
rst_n_i : in std_logic;
wb_clk_i : in std_logic;
wb_addr_i : in std_logic_vector(3 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
hpll_pcr_enable_o : out std_logic;
hpll_pcr_force_f_o : out std_logic;
hpll_pcr_dac_clksel_o : out std_logic_vector(2 downto 0);
hpll_pcr_pd_gate_o : out std_logic_vector(2 downto 0);
hpll_pcr_swrst_o : out std_logic;
hpll_pcr_refsel_o : out std_logic_vector(1 downto 0);
hpll_divr_div_ref_o : out std_logic_vector(15 downto 0);
hpll_divr_div_fb_o : out std_logic_vector(15 downto 0);
hpll_fbgr_f_kp_o : out std_logic_vector(15 downto 0);
hpll_fbgr_f_ki_o : out std_logic_vector(15 downto 0);
hpll_pbgr_p_kp_o : out std_logic_vector(15 downto 0);
hpll_pbgr_p_ki_o : out std_logic_vector(15 downto 0);
hpll_ldcr_ld_thr_o : out std_logic_vector(7 downto 0);
hpll_ldcr_ld_samp_o : out std_logic_vector(7 downto 0);
hpll_fbcr_fd_gate_o : out std_logic_vector(2 downto 0);
hpll_fbcr_ferr_set_o : out std_logic_vector(11 downto 0);
hpll_psr_freq_lk_i : in std_logic;
hpll_psr_phase_lk_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_load_o : out std_logic;
hpll_rfifo_wr_req_i : in std_logic;
hpll_rfifo_wr_full_o : out std_logic;
hpll_rfifo_fp_mode_i : in std_logic;
hpll_rfifo_err_val_i : in std_logic_vector(11 downto 0);
hpll_rfifo_dac_val_i : in std_logic_vector(15 downto 0));
end component;
component hpll_period_detect
port (
clk_ref_i : in std_logic;
clk_fbck_i : in std_logic;
clk_sys_i : in std_logic;
rst_n_refclk_i : in std_logic;
rst_n_fbck_i : in std_logic;
rst_n_sysclk_i : in std_logic;
freq_err_o : out std_logic_vector(11 downto 0);
freq_err_stb_p_o : out std_logic;
hpll_fbcr_fd_gate_i : in std_logic_vector(2 downto 0);
hpll_fbcr_ferr_set_i : in std_logic_vector(11 downto 0));
end component;
component hpll_bangbang_pd
port (
clk_ref_i : in std_logic;
clk_fbck_i : in std_logic;
clk_sys_i : in std_logic;
rst_n_refclk_i : in std_logic;
rst_n_fbck_i : in std_logic;
rst_n_sysclk_i : in std_logic;
sync_dividers_p_i : in std_logic;
phase_err_o : out std_logic_vector(11 downto 0);
phase_err_stb_p_o : out std_logic;
hpll_pcr_pd_gate_i : in std_logic_vector(2 downto 0);
hpll_divr_div_ref_i : in std_logic_vector(15 downto 0);
hpll_divr_div_fb_i : in std_logic_vector(15 downto 0);
dbg_ref_divided_o : out std_logic;
dbg_fbck_divided_o : out std_logic;
dbg_pd_up_o : out std_logic;
dbg_pd_down_o : out std_logic);
end component;
component hpll_controller
generic (
g_error_bits : integer;
g_dacval_bits : integer;
g_output_bias : integer;
g_integrator_fracbits : integer;
g_integrator_overbits : integer;
g_coef_bits : integer);
port (
clk_sys_i : in std_logic;
rst_n_sysclk_i : in std_logic;
phase_err_i : in std_logic_vector(g_error_bits-1 downto 0);
phase_err_stb_p_i : in std_logic;
freq_err_i : in std_logic_vector(g_error_bits-1 downto 0);
freq_err_stb_p_i : in std_logic;
dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0);
dac_val_stb_p_o : out std_logic;
sync_dividers_p_o : out std_logic;
hpll_pcr_enable_i : in std_logic;
hpll_pcr_force_f_i : in std_logic;
hpll_fbgr_f_kp_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_fbgr_f_ki_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_pbgr_p_kp_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_pbgr_p_ki_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_ldcr_ld_thr_i : in std_logic_vector(7 downto 0);
hpll_ldcr_ld_samp_i : in std_logic_vector(7 downto 0);
hpll_psr_freq_lk_o : out std_logic;
hpll_psr_phase_lk_o : out std_logic;
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_load_i : in std_logic;
hpll_rfifo_wr_req_o : out std_logic;
hpll_rfifo_wr_full_i : in std_logic;
hpll_rfifo_fp_mode_o : out std_logic;
hpll_rfifo_err_val_o : out std_logic_vector(g_error_bits-1 downto 0);
hpll_rfifo_dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0));
end component;
component serial_dac
generic (
g_num_data_bits : integer;
g_num_extra_bits : integer);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
value1_i : in std_logic_vector(g_num_data_bits-1 downto 0);
value1_stb_i : in std_logic;
value2_i : in std_logic_vector(g_num_data_bits-1 downto 0);
value2_stb_i : in std_logic;
driver_sel_i : in std_logic;
sclk_divsel_i : in std_logic_vector(2 downto 0);
dac_cs_n_o : out std_logic;
dac_sclk_o : out std_logic;
dac_sdata_o : out std_logic);
end component;
-- Software reset, synced to different clocks.
signal rst_n_refclk, rst_n_fbck, rst_n_sysclk : std_logic;
-- freq & phase error
signal freq_err : std_logic_vector(11 downto 0);
signal phase_err : std_logic_vector(11 downto 0);
signal freq_err_stb_p, phase_err_stb_p : std_logic;
-- DAC drive value
signal dac_val : std_logic_vector(15 downto 0);
signal dac_val_stb_p : std_logic;
signal sync_dividers_p : std_logic;
signal dbg_ref_divided : std_logic;
signal dbg_fbck_divided : std_logic;
signal dbg_pd_up : std_logic;
signal dbg_pd_down : std_logic;
-- wishbone regs
signal hpll_pcr_enable : std_logic;
signal hpll_pcr_force_f : std_logic;
signal hpll_pcr_dac_clksel : std_logic_vector(2 downto 0);
signal hpll_pcr_pd_gate : std_logic_vector(2 downto 0);
signal hpll_pcr_swrst : std_logic;
signal hpll_pcr_refsel : std_logic_vector(1 downto 0);
signal hpll_divr_div_ref : std_logic_vector(15 downto 0);
signal hpll_divr_div_fb : std_logic_vector(15 downto 0);
signal hpll_fbgr_f_kp : std_logic_vector(15 downto 0);
signal hpll_fbgr_f_ki : std_logic_vector(15 downto 0);
signal hpll_pbgr_p_kp : std_logic_vector(15 downto 0);
signal hpll_pbgr_p_ki : std_logic_vector(15 downto 0);
signal hpll_ldcr_ld_thr : std_logic_vector(7 downto 0);
signal hpll_ldcr_ld_samp : std_logic_vector(7 downto 0);
signal hpll_fbcr_fd_gate : std_logic_vector(2 downto 0);
signal hpll_fbcr_ferr_set : std_logic_vector(11 downto 0);
signal hpll_psr_freq_lk : std_logic;
signal hpll_psr_phase_lk : std_logic;
signal hpll_psr_lock_lost_out : std_logic;
signal hpll_psr_lock_lost_in : std_logic;
signal hpll_psr_lock_lost_load : std_logic;
signal hpll_rfifo_wr_req : std_logic;
signal hpll_rfifo_wr_full : std_logic;
signal hpll_rfifo_fp_mode : std_logic;
signal hpll_rfifo_err_val : std_logic_vector(11 downto 0);
signal hpll_rfifo_dac_val : std_logic_vector(15 downto 0);
signal clk_ref_muxed : std_logic;
begin -- architecture rtl
rst_n_sysclk <= not hpll_pcr_swrst;
-- warning: this is NOT GOOD, but works :)
mux_clocks : process(hpll_pcr_refsel, clk_ref_i)
begin
clk_ref_muxed <= '0';
for i in 0 to g_num_ref_inputs-1 loop
if(to_integer(unsigned(hpll_pcr_refsel)) = i) then
clk_ref_muxed <= clk_ref_i(i);
end if;
end loop; -- i
end process;
sync_reset_refclk : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_ref_muxed,
rst_n_i => rst_n_i,
data_i => rst_n_sysclk,
synced_o => rst_n_refclk,
npulse_o => open,
ppulse_o => open);
sync_reset_fbck : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_fbck_i,
rst_n_i => rst_n_i,
data_i => rst_n_sysclk,
synced_o => rst_n_fbck,
npulse_o => open,
ppulse_o => open);
FREQ_DETECT : hpll_period_detect
port map (
clk_ref_i => clk_ref_muxed,
clk_fbck_i => clk_fbck_i,
clk_sys_i => clk_sys_i,
rst_n_refclk_i => rst_n_refclk,
rst_n_fbck_i => rst_n_fbck,
rst_n_sysclk_i => rst_n_sysclk,
freq_err_o => freq_err,
freq_err_stb_p_o => freq_err_stb_p,
hpll_fbcr_fd_gate_i => hpll_fbcr_fd_gate,
hpll_fbcr_ferr_set_i => hpll_fbcr_ferr_set);
BB_DETECT : hpll_bangbang_pd
port map (
clk_ref_i => clk_ref_muxed,
clk_fbck_i => clk_fbck_i,
clk_sys_i => clk_sys_i,
rst_n_refclk_i => rst_n_refclk,
rst_n_fbck_i => rst_n_fbck,
rst_n_sysclk_i => rst_n_sysclk,
sync_dividers_p_i => sync_dividers_p,
phase_err_o => phase_err,
phase_err_stb_p_o => phase_err_stb_p,
hpll_pcr_pd_gate_i => hpll_pcr_pd_gate,
hpll_divr_div_ref_i => hpll_divr_div_ref,
hpll_divr_div_fb_i => hpll_divr_div_fb,
dbg_ref_divided_o => dbg_ref_divided,
dbg_fbck_divided_o => dbg_fbck_divided,
dbg_pd_up_o => dbg_pd_up,
dbg_pd_down_o => dbg_pd_down);
PI_CTL : hpll_controller
generic map (
g_error_bits => 12,
g_dacval_bits => g_dacval_bits,
g_output_bias => g_output_bias,
g_integrator_fracbits => 16,
g_integrator_overbits => 6,
g_coef_bits => 16)
port map (
clk_sys_i => clk_sys_i,
rst_n_sysclk_i => rst_n_sysclk,
phase_err_i => phase_err,
phase_err_stb_p_i => phase_err_stb_p,
freq_err_i => freq_err,
freq_err_stb_p_i => freq_err_stb_p,
dac_val_o => dac_val,
dac_val_stb_p_o => dac_val_stb_p,
sync_dividers_p_o => sync_dividers_p,
hpll_pcr_enable_i => hpll_pcr_enable,
hpll_pcr_force_f_i => hpll_pcr_force_f,
hpll_fbgr_f_kp_i => hpll_fbgr_f_kp,
hpll_fbgr_f_ki_i => hpll_fbgr_f_ki,
hpll_pbgr_p_kp_i => hpll_pbgr_p_kp,
hpll_pbgr_p_ki_i => hpll_pbgr_p_ki,
hpll_ldcr_ld_thr_i => hpll_ldcr_ld_thr,
hpll_ldcr_ld_samp_i => hpll_ldcr_ld_samp,
hpll_psr_freq_lk_o => hpll_psr_freq_lk,
hpll_psr_phase_lk_o => hpll_psr_phase_lk,
hpll_psr_lock_lost_i => hpll_psr_lock_lost_out,
hpll_psr_lock_lost_o => hpll_psr_lock_lost_in,
hpll_psr_lock_lost_load_i => hpll_psr_lock_lost_load,
hpll_rfifo_wr_req_o => hpll_rfifo_wr_req,
hpll_rfifo_wr_full_i => hpll_rfifo_wr_full,
hpll_rfifo_fp_mode_o => hpll_rfifo_fp_mode,
hpll_rfifo_err_val_o => hpll_rfifo_err_val,
hpll_rfifo_dac_val_o => hpll_rfifo_dac_val
);
dac_data_o <= dac_val;
dac_load_p1_o <= dac_val_stb_p;
gen_wb_slave : if(g_with_wishbone /= 0) generate
WB_SLAVE : hpll_wb_slave
port map (
rst_n_i => rst_n_i,
wb_clk_i => clk_sys_i,
wb_addr_i => wb_addr_i,
wb_data_i => wb_data_i,
wb_data_o => wb_data_o,
wb_cyc_i => wb_cyc_i,
wb_sel_i => wb_sel_i,
wb_stb_i => wb_stb_i,
wb_we_i => wb_we_i,
wb_ack_o => wb_ack_o,
hpll_pcr_enable_o => hpll_pcr_enable,
hpll_pcr_force_f_o => hpll_pcr_force_f,
hpll_pcr_dac_clksel_o => hpll_pcr_dac_clksel,
hpll_pcr_pd_gate_o => hpll_pcr_pd_gate,
hpll_pcr_swrst_o => hpll_pcr_swrst,
hpll_pcr_refsel_o => hpll_pcr_refsel,
hpll_divr_div_ref_o => hpll_divr_div_ref,
hpll_divr_div_fb_o => hpll_divr_div_fb,
hpll_fbgr_f_kp_o => hpll_fbgr_f_kp,
hpll_fbgr_f_ki_o => hpll_fbgr_f_ki,
hpll_pbgr_p_kp_o => hpll_pbgr_p_kp,
hpll_pbgr_p_ki_o => hpll_pbgr_p_ki,
hpll_ldcr_ld_thr_o => hpll_ldcr_ld_thr,
hpll_ldcr_ld_samp_o => hpll_ldcr_ld_samp,
hpll_fbcr_fd_gate_o => hpll_fbcr_fd_gate,
hpll_fbcr_ferr_set_o => hpll_fbcr_ferr_set,
hpll_psr_freq_lk_i => hpll_psr_freq_lk,
hpll_psr_phase_lk_i => hpll_psr_phase_lk,
hpll_psr_lock_lost_o => hpll_psr_lock_lost_out,
hpll_psr_lock_lost_i => hpll_psr_lock_lost_in,
hpll_psr_lock_lost_load_o => hpll_psr_lock_lost_load,
hpll_rfifo_wr_req_i => hpll_rfifo_wr_req,
hpll_rfifo_wr_full_o => hpll_rfifo_wr_full,
hpll_rfifo_fp_mode_i => hpll_rfifo_fp_mode,
hpll_rfifo_err_val_i => hpll_rfifo_err_val,
hpll_rfifo_dac_val_i => hpll_rfifo_dac_val
);
end generate gen_wb_slave;
gen_no_wb_slave : if(g_with_wishbone = 0) generate
hpll_pcr_enable <= cfg_enable_i;
hpll_pcr_force_f <= cfg_force_freq_i;
hpll_pcr_pd_gate <= std_logic_vector(to_unsigned(g_pd_gating, hpll_pcr_pd_gate'length));
hpll_pcr_swrst <= '0';
hpll_pcr_refsel <= cfg_refsel_i;
hpll_divr_div_ref <= std_logic_vector(to_unsigned(g_div_ref, hpll_divr_div_ref'length));
hpll_divr_div_fb <= std_logic_vector(to_unsigned(g_div_fb, hpll_divr_div_fb'length));
hpll_fbgr_f_kp <= std_logic_vector(to_unsigned(g_kp_freq, hpll_fbgr_f_kp'length));
hpll_fbgr_f_ki <= std_logic_vector(to_unsigned(g_ki_freq, hpll_fbgr_f_ki'length));
hpll_pbgr_p_kp <= std_logic_vector(to_unsigned(g_kp_phase, hpll_pbgr_p_kp'length));
hpll_pbgr_p_ki <= std_logic_vector(to_unsigned(g_ki_phase, hpll_pbgr_p_ki'length));
hpll_ldcr_ld_thr <= std_logic_vector(to_unsigned(g_ld_threshold, hpll_ldcr_ld_thr'length));
hpll_ldcr_ld_samp <= std_logic_vector(to_unsigned(g_ld_samples, hpll_ldcr_ld_samp'length));
hpll_fbcr_fd_gate <= std_logic_vector(to_unsigned(g_fd_gating, hpll_fbcr_fd_gate'length));
hpll_fbcr_ferr_set <= std_logic_vector(to_unsigned(g_ferr_setpoint, hpll_fbcr_ferr_set'length));
stat_flock_o <= hpll_psr_freq_lk;
stat_plock_o <= hpll_psr_phase_lk;
stat_lock_lost_o <= hpll_psr_lock_lost_in;
hpll_psr_lock_lost_out <= '1';
hpll_psr_lock_lost_load <= cfg_clear_status_i;
hpll_rfifo_wr_full <= '0';
end generate gen_no_wb_slave;
auxout1_o <= dbg_fbck_divided;
auxout2_o <= dbg_ref_divided;
end architecture rtl;
-------------------------------------------------------------------------------
-- Project : Phase-Locked Loop
-------------------------------------------------------------------------------
-- File : pll.vhd
-- Author : Javier Serrano, Tomasz Wlostowski
-- Institute : CERN
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: This is a generic PLL that assumes a DAC and VCO outside the
-- FPGA. The reset is assumed to be synchronized with the system clock outside
-- this block. The block receives a reference clock of frequency f and derives
-- from it a clock of frequency f*(num/den) where num and den are two 16-bit
-- unsigned numbers. The PI loop filter has controllable proportional and
-- integral gains which are also 16-bit unsigned. The output to the DAC is a
-- 16-bit signed number.
-------------------------------------------------------------------------------
-- Revisions:
-- Date Version Author Description
-- 4 April 2010 1.0 J.Serrano Created
-- 15 June 2010 1.1 twlostow redesigned....
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.platform_specific.all;
use work.common_components.all;
entity wrsw_helper_pll is
port (
rst_n_i : in std_logic; -- Synchronous reset
clk_ref_local_i : in std_logic; -- Reference clock (from TCXO)
clk_ref_up0_i : in std_logic; -- Reference clock (from uplink 0)
clk_ref_up1_i : in std_logic; -- Reference clock (from uplink 1)
clk_sys_i : in std_logic; -- System clock
clk_fbck_i : in std_logic; -- Fed-back clock
dac_cs_n_o : out std_logic;
dac_sclk_o : out std_logic;
dac_sdata_o : out std_logic;
auxout1_o : out std_logic;
auxout2_o : out std_logic;
auxout3_o : out std_logic;
wb_addr_i : in std_logic_vector(3 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic
);
end wrsw_helper_pll;
architecture rtl of wrsw_helper_pll is
component hpll_wb_slave
port (
rst_n_i : in std_logic;
wb_clk_i : in std_logic;
wb_addr_i : in std_logic_vector(3 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
hpll_pcr_enable_o : out std_logic;
hpll_pcr_force_f_o : out std_logic;
hpll_pcr_dac_clksel_o : out std_logic_vector(2 downto 0);
hpll_pcr_pd_gate_o : out std_logic_vector(2 downto 0);
hpll_pcr_swrst_o : out std_logic;
hpll_pcr_refsel_o : out std_logic_vector(1 downto 0);
hpll_divr_div_ref_o : out std_logic_vector(15 downto 0);
hpll_divr_div_fb_o : out std_logic_vector(15 downto 0);
hpll_fbgr_f_kp_o : out std_logic_vector(15 downto 0);
hpll_fbgr_f_ki_o : out std_logic_vector(15 downto 0);
hpll_pbgr_p_kp_o : out std_logic_vector(15 downto 0);
hpll_pbgr_p_ki_o : out std_logic_vector(15 downto 0);
hpll_ldcr_ld_thr_o : out std_logic_vector(7 downto 0);
hpll_ldcr_ld_samp_o : out std_logic_vector(7 downto 0);
hpll_fbcr_fd_gate_o : out std_logic_vector(2 downto 0);
hpll_fbcr_ferr_set_o : out std_logic_vector(11 downto 0);
hpll_psr_freq_lk_i : in std_logic;
hpll_psr_phase_lk_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_load_o : out std_logic;
hpll_rfifo_wr_req_i : in std_logic;
hpll_rfifo_wr_full_o : out std_logic;
hpll_rfifo_fp_mode_i : in std_logic;
hpll_rfifo_err_val_i : in std_logic_vector(11 downto 0);
hpll_rfifo_dac_val_i : in std_logic_vector(15 downto 0));
end component;
component hpll_period_detect
generic(
g_freq_err_frac_bits:integer := 7
);
port (
clk_ref_i : in std_logic;
clk_fbck_i : in std_logic;
clk_sys_i : in std_logic;
rst_n_refclk_i : in std_logic;
rst_n_fbck_i : in std_logic;
rst_n_sysclk_i : in std_logic;
freq_err_o : out std_logic_vector(11 downto 0);
freq_err_stb_p_o : out std_logic;
hpll_fbcr_fd_gate_i : in std_logic_vector(2 downto 0);
hpll_fbcr_ferr_set_i : in std_logic_vector(11 downto 0));
end component;
component hpll_bangbang_pd
port (
clk_ref_i : in std_logic;
clk_fbck_i : in std_logic;
clk_sys_i : in std_logic;
rst_n_refclk_i : in std_logic;
rst_n_fbck_i : in std_logic;
rst_n_sysclk_i : in std_logic;
sync_dividers_p_i : in std_logic;
phase_err_o : out std_logic_vector(11 downto 0);
phase_err_stb_p_o : out std_logic;
hpll_pcr_pd_gate_i : in std_logic_vector(2 downto 0);
hpll_divr_div_ref_i : in std_logic_vector(15 downto 0);
hpll_divr_div_fb_i : in std_logic_vector(15 downto 0);
dbg_ref_divided_o : out std_logic;
dbg_fbck_divided_o : out std_logic;
dbg_pd_up_o : out std_logic;
dbg_pd_down_o : out std_logic);
end component;
component hpll_controller
generic (
g_error_bits : integer;
g_dacval_bits : integer;
g_output_bias : integer;
g_integrator_fracbits : integer;
g_integrator_overbits : integer;
g_coef_bits : integer);
port (
clk_sys_i : in std_logic;
rst_n_sysclk_i : in std_logic;
phase_err_i : in std_logic_vector(g_error_bits-1 downto 0);
phase_err_stb_p_i : in std_logic;
freq_err_i : in std_logic_vector(g_error_bits-1 downto 0);
freq_err_stb_p_i : in std_logic;
dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0);
dac_val_stb_p_o : out std_logic;
sync_dividers_p_o : out std_logic;
hpll_pcr_enable_i : in std_logic;
hpll_pcr_force_f_i : in std_logic;
hpll_fbgr_f_kp_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_fbgr_f_ki_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_pbgr_p_kp_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_pbgr_p_ki_i : in std_logic_vector(g_coef_bits-1 downto 0);
hpll_ldcr_ld_thr_i : in std_logic_vector(7 downto 0);
hpll_ldcr_ld_samp_i : in std_logic_vector(7 downto 0);
hpll_psr_freq_lk_o : out std_logic;
hpll_psr_phase_lk_o : out std_logic;
hpll_psr_lock_lost_i : in std_logic;
hpll_psr_lock_lost_o : out std_logic;
hpll_psr_lock_lost_load_i : in std_logic;
hpll_rfifo_wr_req_o : out std_logic;
hpll_rfifo_wr_full_i : in std_logic;
hpll_rfifo_fp_mode_o : out std_logic;
hpll_rfifo_err_val_o : out std_logic_vector(g_error_bits-1 downto 0);
hpll_rfifo_dac_val_o : out std_logic_vector(g_dacval_bits-1 downto 0));
end component;
component serial_dac
generic (
g_num_data_bits : integer;
g_num_extra_bits : integer);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
value1_i : in std_logic_vector(g_num_data_bits-1 downto 0);
value1_stb_i : in std_logic;
value2_i : in std_logic_vector(g_num_data_bits-1 downto 0);
value2_stb_i : in std_logic;
driver_sel_i : in std_logic;
sclk_divsel_i : in std_logic_vector(2 downto 0);
dac_cs_n_o : out std_logic;
dac_sclk_o : out std_logic;
dac_sdata_o : out std_logic);
end component;
-- Software reset, synced to different clocks.
signal rst_n_refclk, rst_n_fbck, rst_n_sysclk : std_logic;
-- freq & phase error
signal freq_err : std_logic_vector(11 downto 0);
signal phase_err : std_logic_vector(11 downto 0);
signal freq_err_stb_p, phase_err_stb_p : std_logic;
-- DAC drive value
signal dac_val : std_logic_vector(15 downto 0);
signal dac_val_stb_p : std_logic;
signal sync_dividers_p : std_logic;
signal dbg_ref_divided : std_logic;
signal dbg_fbck_divided : std_logic;
signal dbg_pd_up : std_logic;
signal dbg_pd_down : std_logic;
-- wishbone regs
signal hpll_pcr_enable : std_logic;
signal hpll_pcr_force_f : std_logic;
signal hpll_pcr_dac_clksel : std_logic_vector(2 downto 0);
signal hpll_pcr_pd_gate : std_logic_vector(2 downto 0);
signal hpll_pcr_swrst : std_logic;
signal hpll_pcr_refsel : std_logic_vector(1 downto 0);
signal hpll_divr_div_ref : std_logic_vector(15 downto 0);
signal hpll_divr_div_fb : std_logic_vector(15 downto 0);
signal hpll_fbgr_f_kp : std_logic_vector(15 downto 0);
signal hpll_fbgr_f_ki : std_logic_vector(15 downto 0);
signal hpll_pbgr_p_kp : std_logic_vector(15 downto 0);
signal hpll_pbgr_p_ki : std_logic_vector(15 downto 0);
signal hpll_ldcr_ld_thr : std_logic_vector(7 downto 0);
signal hpll_ldcr_ld_samp : std_logic_vector(7 downto 0);
signal hpll_fbcr_fd_gate : std_logic_vector(2 downto 0);
signal hpll_fbcr_ferr_set : std_logic_vector(11 downto 0);
signal hpll_psr_freq_lk : std_logic;
signal hpll_psr_phase_lk : std_logic;
signal hpll_psr_lock_lost_out : std_logic;
signal hpll_psr_lock_lost_in : std_logic;
signal hpll_psr_lock_lost_load : std_logic;
signal hpll_rfifo_wr_req : std_logic;
signal hpll_rfifo_wr_full : std_logic;
signal hpll_rfifo_fp_mode : std_logic;
signal hpll_rfifo_err_val : std_logic_vector(11 downto 0);
signal hpll_rfifo_dac_val : std_logic_vector(15 downto 0);
signal clk_ref_muxed : std_logic;
signal clk_ref_vec: std_logic_vector(2 downto 0);
begin -- architecture rtl
rst_n_sysclk <= not hpll_pcr_swrst;
clk_ref_vec(0) <= clk_ref_local_i;
clk_ref_vec(1) <= clk_ref_up1_i;
clk_ref_vec(2) <= clk_ref_up0_i;
-- warning: this is NOT GOOD, but works :)
mux_clocks : process(hpll_pcr_refsel, clk_ref_vec)
begin
clk_ref_muxed <= '0';
for i in 0 to 2 loop
if(to_integer(unsigned(hpll_pcr_refsel)) = i) then
clk_ref_muxed <= clk_ref_vec(i);
end if;
end loop; -- i
end process;
-- clk_ref_muxed <= clk_ref_up1_i;
sync_reset_refclk : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_ref_muxed,
rst_n_i => rst_n_i,
data_i => rst_n_sysclk,
synced_o => rst_n_refclk,
npulse_o => open,
ppulse_o => open);
sync_reset_fbck : sync_ffs
generic map (
g_sync_edge => "positive")
port map (
clk_i => clk_fbck_i,
rst_n_i => rst_n_i,
data_i => rst_n_sysclk,
synced_o => rst_n_fbck,
npulse_o => open,
ppulse_o => open);
FREQ_DETECT : hpll_period_detect
port map (
clk_ref_i => clk_ref_muxed,
clk_fbck_i => clk_fbck_i,
clk_sys_i => clk_sys_i,
rst_n_refclk_i => rst_n_refclk,
rst_n_fbck_i => rst_n_fbck,
rst_n_sysclk_i => rst_n_sysclk,
freq_err_o => freq_err,
freq_err_stb_p_o => freq_err_stb_p,
hpll_fbcr_fd_gate_i => hpll_fbcr_fd_gate,
hpll_fbcr_ferr_set_i => hpll_fbcr_ferr_set);
BB_DETECT : hpll_bangbang_pd
port map (
clk_ref_i => clk_ref_muxed,
clk_fbck_i => clk_fbck_i,
clk_sys_i => clk_sys_i,
rst_n_refclk_i => rst_n_refclk,
rst_n_fbck_i => rst_n_fbck,
rst_n_sysclk_i => rst_n_sysclk,
sync_dividers_p_i => sync_dividers_p,
phase_err_o => phase_err,
phase_err_stb_p_o => phase_err_stb_p,
hpll_pcr_pd_gate_i => hpll_pcr_pd_gate,
hpll_divr_div_ref_i => hpll_divr_div_ref,
hpll_divr_div_fb_i => hpll_divr_div_fb,
dbg_ref_divided_o => dbg_ref_divided,
dbg_fbck_divided_o => dbg_fbck_divided,
dbg_pd_up_o => dbg_pd_up,
dbg_pd_down_o => dbg_pd_down);
PI_CTL : hpll_controller
generic map (
g_error_bits => 12,
g_dacval_bits => 16,
g_output_bias => 32767,
g_integrator_fracbits => 16,
g_integrator_overbits => 6,
g_coef_bits => 16)
port map (
clk_sys_i => clk_sys_i,
rst_n_sysclk_i => rst_n_sysclk,
phase_err_i => phase_err,
phase_err_stb_p_i => phase_err_stb_p,
freq_err_i => freq_err,
freq_err_stb_p_i => freq_err_stb_p,
dac_val_o => dac_val,
dac_val_stb_p_o => dac_val_stb_p,
sync_dividers_p_o => sync_dividers_p,
hpll_pcr_enable_i => hpll_pcr_enable,
hpll_pcr_force_f_i => hpll_pcr_force_f,
hpll_fbgr_f_kp_i => hpll_fbgr_f_kp,
hpll_fbgr_f_ki_i => hpll_fbgr_f_ki,
hpll_pbgr_p_kp_i => hpll_pbgr_p_kp,
hpll_pbgr_p_ki_i => hpll_pbgr_p_ki,
hpll_ldcr_ld_thr_i => hpll_ldcr_ld_thr,
hpll_ldcr_ld_samp_i => hpll_ldcr_ld_samp,
hpll_psr_freq_lk_o => hpll_psr_freq_lk,
hpll_psr_phase_lk_o => hpll_psr_phase_lk,
hpll_psr_lock_lost_i => hpll_psr_lock_lost_out,
hpll_psr_lock_lost_o => hpll_psr_lock_lost_in,
hpll_psr_lock_lost_load_i => hpll_psr_lock_lost_load,
hpll_rfifo_wr_req_o => hpll_rfifo_wr_req,
hpll_rfifo_wr_full_i => hpll_rfifo_wr_full,
hpll_rfifo_fp_mode_o => hpll_rfifo_fp_mode,
hpll_rfifo_err_val_o => hpll_rfifo_err_val,
hpll_rfifo_dac_val_o => hpll_rfifo_dac_val
);
DAC : serial_dac
generic map (
g_num_data_bits => 16,
g_num_extra_bits => 8
)
port map (
clk_i => clk_sys_i,
rst_n_i => rst_n_i,
value1_i => dac_val,
value1_stb_i => dac_val_stb_p,
value2_i => (others => '0'),
value2_stb_i => '0',
driver_sel_i => '0',
sclk_divsel_i => hpll_pcr_dac_clksel,
dac_cs_n_o => dac_cs_n_o,
dac_sclk_o => dac_sclk_o,
dac_sdata_o => dac_sdata_o);
WB_SLAVE : hpll_wb_slave
port map (
rst_n_i => rst_n_i,
wb_clk_i => clk_sys_i,
wb_addr_i => wb_addr_i,
wb_data_i => wb_data_i,
wb_data_o => wb_data_o,
wb_cyc_i => wb_cyc_i,
wb_sel_i => wb_sel_i,
wb_stb_i => wb_stb_i,
wb_we_i => wb_we_i,
wb_ack_o => wb_ack_o,
hpll_pcr_enable_o => hpll_pcr_enable,
hpll_pcr_force_f_o => hpll_pcr_force_f,
hpll_pcr_dac_clksel_o => hpll_pcr_dac_clksel,
hpll_pcr_pd_gate_o => hpll_pcr_pd_gate,
hpll_pcr_swrst_o => hpll_pcr_swrst,
hpll_pcr_refsel_o => hpll_pcr_refsel,
hpll_divr_div_ref_o => hpll_divr_div_ref,
hpll_divr_div_fb_o => hpll_divr_div_fb,
hpll_fbgr_f_kp_o => hpll_fbgr_f_kp,
hpll_fbgr_f_ki_o => hpll_fbgr_f_ki,
hpll_pbgr_p_kp_o => hpll_pbgr_p_kp,
hpll_pbgr_p_ki_o => hpll_pbgr_p_ki,
hpll_ldcr_ld_thr_o => hpll_ldcr_ld_thr,
hpll_ldcr_ld_samp_o => hpll_ldcr_ld_samp,
hpll_fbcr_fd_gate_o => hpll_fbcr_fd_gate,
hpll_fbcr_ferr_set_o => hpll_fbcr_ferr_set,
hpll_psr_freq_lk_i => hpll_psr_freq_lk,
hpll_psr_phase_lk_i => hpll_psr_phase_lk,
hpll_psr_lock_lost_o => hpll_psr_lock_lost_out,
hpll_psr_lock_lost_i => hpll_psr_lock_lost_in,
hpll_psr_lock_lost_load_o => hpll_psr_lock_lost_load,
hpll_rfifo_wr_req_i => hpll_rfifo_wr_req,
hpll_rfifo_wr_full_o => hpll_rfifo_wr_full,
hpll_rfifo_fp_mode_i => hpll_rfifo_fp_mode,
hpll_rfifo_err_val_i => hpll_rfifo_err_val,
hpll_rfifo_dac_val_i => hpll_rfifo_dac_val
);
auxout1_o <= dbg_fbck_divided;
auxout2_o <= dbg_ref_divided;
end architecture rtl;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment