Commit a975b77b authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

hdl: improved softpll-ng

parent 760bd932
files = ["spll_period_detect.vhd",
"spll_wbgen2_pkg.vhd",
# "wr_softpll_ng.vhd",
# "xwr_softpll_ng.vhd",
"spll_wb_slave.vhd"]
\ No newline at end of file
"spll_wbgen2_pkg.vhd",
"wr_softpll_ng.vhd",
"xwr_softpll_ng.vhd",
"spll_wb_slave.vhd"]
......@@ -6,7 +6,7 @@
-- Author : Tomasz Wlostowski
-- Company : CERN BE-Co-HT
-- Created : 2010-06-14
-- Last update: 2012-01-17
-- Last update: 2012-01-23
-- Platform : FPGA-generic
-- Standard : VHDL'87
-------------------------------------------------------------------------------
......@@ -70,55 +70,84 @@ end spll_period_detect;
architecture rtl of spll_period_detect is
constant c_COUNTER_BITS : integer := 19;
constant c_GATING_PERIOD : integer := 1024;
constant c_GATING_PERIOD_LOG2 : integer := 17;
-- frequency counters: feedback clock & gating counter
signal in_muxed : std_logic;
signal in_sel_onehot : std_logic_vector(g_num_ref_inputs-1 downto 0);
subtype t_counter is unsigned(c_GATING_PERIOD_LOG2+1 downto 0);
type t_counter_array is array(integer range <>) of t_counter;
signal freq : std_logic_vector(19 downto 0);
signal freq_valid_dmtdclk, freq_valid_sysclk : std_logic;
signal freq_valid_dmtdclk_d0, freq_valid_dmtdclk_pulse : std_logic;
signal freq_valid_sysclk : std_logic;
signal gate_counter : t_counter;
signal gate_pulse_dmtdclk : std_logic;
signal gate_pulse_synced : std_logic_vector(g_num_ref_inputs-1 downto 0);
signal fb_counters, fb_freq : t_counter_array(g_num_ref_inputs-1 downto 0);
signal fb_muxpipe : t_counter_array(2 downto 0);
begin -- rtl
p_gate_counter : process(clk_dmtd_i)
begin
if rising_edge(clk_dmtd_i) then
if rst_n_dmtdclk_i = '0' then
gate_counter <= to_unsigned(1, gate_counter'length);
else
if(gate_counter(c_GATING_PERIOD_LOG2) = '1') then
gate_counter <= to_unsigned(1, gate_counter'length);
else
gate_counter <= gate_counter + 1;
end if;
end if;
end if;
end process;
gen_in_sel_mask : for i in 0 to g_num_ref_inputs-1 generate
in_sel_onehot(i) <= '1' when i = to_integer(unsigned(in_sel_i)) else '0';
end generate gen_in_sel_mask; -- i
gate_pulse_dmtdclk <= gate_counter(c_GATING_PERIOD_LOG2);
in_muxed <= '1' when unsigned(in_sel_onehot and clk_ref_i) /= 0 else '0';
gen_feedback_counters : for i in 0 to g_num_ref_inputs-1 generate
U_Gate_Sync : gc_pulse_synchronizer
port map (
clk_in_i => clk_dmtd_i,
clk_out_i => clk_ref_i(i),
rst_n_i => rst_n_sysclk_i,
d_p_i => gate_pulse_dmtdclk,
q_p_o => gate_pulse_synced(i));
p_feedback_counter : process(clk_ref_i(i))
begin
if rst_n_sysclk_i = '0' then
fb_counters(i) <= to_unsigned(1, c_GATING_PERIOD_LOG2+2);
elsif rising_edge(clk_ref_i(i)) then
if(gate_pulse_synced(i) = '1') then
fb_freq(i) <= fb_counters(i);
fb_counters(i) <= to_unsigned(0, c_GATING_PERIOD_LOG2+2);
else
fb_counters(i) <= fb_counters(i) + 1;
end if;
end if;
end process;
end generate gen_feedback_counters;
U_Freq_Meter : gc_frequency_meter
U_Sync_Gate : gc_sync_ffs
generic map (
g_with_internal_timebase => true,
g_clk_sys_freq => c_GATING_PERIOD,
g_counter_bits => 20)
g_sync_edge => "positive")
port map (
clk_sys_i => clk_dmtd_i,
clk_in_i => in_muxed,
rst_n_i => rst_n_dmtdclk_i,
pps_p1_i => '0',
freq_o => freq,
freq_valid_o => freq_valid_dmtdclk);
U_Pulse_Sync : gc_pulse_synchronizer
port map (
clk_in_i => clk_dmtd_i,
clk_out_i => clk_sys_i,
rst_n_i => rst_n_sysclk_i,
d_p_i => freq_valid_dmtdclk_pulse,
q_p_o => freq_valid_sysclk);
clk_i => clk_sys_i,
rst_n_i => rst_n_sysclk_i,
data_i => std_logic(gate_counter(c_GATING_PERIOD_LOG2-1)),
ppulse_o => freq_valid_sysclk);
p_mux_counters : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
fb_muxpipe(0) <= fb_freq(to_integer(unsigned(in_sel_i)));
for i in 1 to fb_muxpipe'length-1 loop
fb_muxpipe(i) <= fb_muxpipe(i-1);
end loop; -- i
end if;
end process;
p_edge_detect: process(clk_dmtd_i)
begin
if rising_edge(clk_dmtd_i) then
freq_valid_dmtdclk_d0 <= freq_valid_dmtdclk;
end if;
end process;
freq_valid_dmtdclk_pulse <= freq_valid_dmtdclk and not freq_valid_dmtdclk_d0;
p_output : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
......@@ -126,12 +155,12 @@ begin -- rtl
freq_err_o <= (others => '0');
freq_err_stb_p_o <= '0';
elsif(freq_valid_sysclk = '1') then
freq_err_o <= std_logic_vector(resize(unsigned(freq) - c_GATING_PERIOD, freq_err_o'length));
freq_err_o <= std_logic_vector(resize(fb_muxpipe(fb_muxpipe'length-1) - (2 ** c_GATING_PERIOD_LOG2), freq_err_o'length));
freq_err_stb_p_o <= '1';
else
freq_err_stb_p_o <= '0';
end if;
end if;
end process;
end rtl;
This diff is collapsed.
......@@ -3,12 +3,13 @@
peripheral {
name = "WR Softcore PLL";
hdl_entity = "spll_wb_slave";
prefix = "SPLL";
prefix = "spll";
reg {
name = "SPLL Control/Status Register";
prefix = "CSR";
field {
align = 8;
name = "Period detector reference select";
......@@ -38,8 +39,45 @@ peripheral {
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "Enable Period Measurement";
prefix = "PER_EN";
type = BIT;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "DMTD Clock Control Register";
prefix = "DCCR";
field {
name = "DMTD Clock Gate Divider";
prefix = "GATE_DIV";
size = 6;
type = SLV;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Reference Channel Gating Enable Register";
prefix = "RCGER";
field {
name = "Reference Channel Gating Enable";
prefix = "GATE_SEL";
size = 32;
type = PASS_THROUGH;
};
};
reg {
name = "Output Channel Control Register";
prefix = "OCCR";
......@@ -165,13 +203,56 @@ peripheral {
};
};
reg {
name = "Debug FIFO Register - SPLL side";
prefix = "DFR_SPLL";
field {
name = "Debug Value";
prefix = "VALUE";
size = 31;
type = PASS_THROUGH;
};
field {
name = "End-of-Sample";
prefix = "EOS";
size = 1;
type = PASS_THROUGH;
};
};
fifo_reg {
name = "Debug FIFO Register - Host side";
prefix = "DFR_HOST";
direction = CORE_TO_BUS;
size = 8192;
flags_dev = {FIFO_FULL, FIFO_EMPTY, FIFO_COUNT};
flags_bus = {FIFO_FULL, FIFO_EMPTY, FIFO_COUNT};
field {
name = "Value";
prefix = "VALUE";
type = SLV;
size = 32;
};
field {
name = "Seq ID";
prefix = "SEQ_ID";
type = SLV;
size = 16;
};
};
fifo_reg {
name = "Tag Readout Register";
prefix = "TRR";
direction = CORE_TO_BUS;
size = 32;
flags_dev = {FIFO_FULL};
flags_dev = {FIFO_FULL, FIFO_EMPTY};
flags_bus = {FIFO_EMPTY};
field {
......@@ -196,6 +277,8 @@ peripheral {
};
};
irq {
name = "Got a tag";
prefix = "TAG";
......
This diff is collapsed.
This diff is collapsed.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
use work.wishbone_pkg.all;
entity xwr_softpll_ng is
generic(
g_tag_bits : integer;
g_interface_mode : t_wishbone_interface_mode := CLASSIC;
g_address_granularity : t_wishbone_address_granularity := WORD;
g_num_ref_inputs : integer;
g_num_outputs : integer;
g_period_detector_ref_mask : std_logic_vector(31 downto 0) := x"ffffffff"
);
port(
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
-- Reference inputs (i.e. the RX clocks recovered by the PHYs)
clk_ref_i : in std_logic_vector(g_num_ref_inputs-1 downto 0);
-- Feedback clocks (i.e. the outputs of the main or aux oscillator)
clk_fb_i : in std_logic_vector(g_num_outputs-1 downto 0);
-- DMTD Offset clock
clk_dmtd_i : in std_logic;
-- DMTD oscillator drive
dac_dmtd_data_o : out std_logic_vector(15 downto 0);
dac_dmtd_load_o : out std_logic;
-- Output channel DAC value
dac_out_data_o : out std_logic_vector(15 downto 0);
-- Output channel select (0 = channel 0, etc. )
dac_out_sel_o : out std_logic_vector(3 downto 0);
dac_out_load_o : out std_logic;
out_enable_i : in std_logic_vector(g_num_outputs-1 downto 0);
out_locked_o : out std_logic_vector(g_num_outputs-1 downto 0);
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out;
debug_o : out std_logic_vector(3 downto 0)
);
end xwr_softpll_ng;
architecture wrapper of xwr_softpll_ng is
component wr_softpll_ng
generic (
g_tag_bits : integer;
g_interface_mode : t_wishbone_interface_mode;
g_address_granularity : t_wishbone_address_granularity;
g_num_ref_inputs : integer;
g_num_outputs : integer;
g_period_detector_ref_mask : std_logic_vector(31 downto 0) := x"ffffffff"
);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
clk_ref_i : in std_logic_vector(g_num_ref_inputs-1 downto 0);
clk_fb_i : in std_logic_vector(g_num_outputs-1 downto 0);
clk_dmtd_i : in std_logic;
dac_dmtd_data_o : out std_logic_vector(15 downto 0);
dac_dmtd_load_o : out std_logic;
dac_out_data_o : out std_logic_vector(15 downto 0);
dac_out_sel_o : out std_logic_vector(3 downto 0);
dac_out_load_o : out std_logic;
out_enable_i : in std_logic_vector(g_num_outputs-1 downto 0);
out_locked_o : out std_logic_vector(g_num_outputs-1 downto 0);
wb_adr_i : in std_logic_vector(6 downto 0);
wb_dat_i : in std_logic_vector(31 downto 0);
wb_dat_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;
wb_stall_o : out std_logic;
wb_irq_o : out std_logic;
debug_o : out std_logic_vector(3 downto 0));
end component;
begin -- behavioral
U_Wrapped_Softpll : wr_softpll_ng
generic map (
g_tag_bits => g_tag_bits,
g_interface_mode => g_interface_mode,
g_address_granularity => g_address_granularity,
g_num_ref_inputs => g_num_ref_inputs,
g_num_outputs => g_num_outputs,
g_period_detector_ref_mask => g_period_detector_ref_mask)
port map (
clk_sys_i => clk_sys_i,
rst_n_i => rst_n_i,
clk_ref_i => clk_ref_i,
clk_fb_i => clk_fb_i,
clk_dmtd_i => clk_dmtd_i,
dac_dmtd_data_o => dac_dmtd_data_o,
dac_dmtd_load_o => dac_dmtd_load_o,
dac_out_data_o => dac_out_data_o,
dac_out_sel_o => dac_out_sel_o,
dac_out_load_o => dac_out_load_o,
out_enable_i => out_enable_i,
out_locked_o => out_locked_o,
wb_adr_i => slave_i.adr(6 downto 0),
wb_dat_i => slave_i.dat,
wb_dat_o => slave_o.dat,
wb_cyc_i => slave_i.cyc,
wb_sel_i => slave_i.sel,
wb_stb_i => slave_i.stb,
wb_we_i => slave_i.we,
wb_ack_o => slave_o.ack,
wb_stall_o => slave_o.stall,
wb_irq_o => slave_o.int,
debug_o => debug_o);
end wrapper;
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