Commit 101aff2a authored by Tomasz Wlostowski's avatar Tomasz Wlostowski Committed by Tristan Gingold

wb_fine_pulse_gen: simplify clock crossings

Conflicts:
	modules/wishbone/wb_fine_pulse_gen/xwb_fine_pulse_gen.vhd
parent f3f8dd3d
......@@ -11,15 +11,14 @@ use unisim.VCOMPONENTS.all;
entity fine_pulse_gen_kintexultrascale is
generic (
g_sim_delay_tap_ps : integer := 30;
g_ref_clk_freq : real := 125.0;
g_use_odelay : boolean := false;
g_CLK_ODELAY_FREQ : real := 200.0
g_idelayctrl_ref_clk_freq : real := 250.0;
g_use_odelay : boolean := false
);
port
(
clk_sys_i : in std_logic; -- system clock
clk_ref_i : in std_logic; -- 62.5 MHz (WR)
clk_par_i : in std_logic; -- 125 MHz
clk_odelay_i : in std_logic; -- 200 MHz
clk_serdes_i : in std_logic; -- 500 MHz (DDR)
rst_serdes_i : in std_logic;
......@@ -50,6 +49,8 @@ end fine_pulse_gen_kintexultrascale;
architecture rtl of fine_pulse_gen_kintexultrascale is
constant c_DELAY_VALUE : integer := 1000; -- in ps
component OSERDESE3 is
......@@ -132,7 +133,14 @@ architecture rtl of fine_pulse_gen_kintexultrascale is
signal odelay_value_out, odelay_value_in, odelay_value_in_pulse : std_logic_vector(8 downto 0);
signal odelay_load_clk_ref, odelay_load_pulse : std_logic;
signal odelay_load_clk_odelay : std_logic;
signal odelay_load_clk_par : std_logic;
attribute mark_debug : string;
attribute mark_debug of odelay_en_vtc_i : signal is "true";
attribute mark_debug of odelay_cal_latch_i : signal is "true";
attribute mark_debug of odelay_value_out : signal is "true";
begin
......@@ -274,6 +282,7 @@ begin
elsif rising_edge(clk_ref_i) then
clk_ref_div2 <= not clk_ref_div2;
odelay_load_clk_ref <= odelay_load_pulse or odelay_load_i;
if odelay_load_pulse = '1' then
......@@ -293,7 +302,7 @@ begin
rst_n_i => rst_sys_n_i,
d_ready_o => open,
d_p_i => odelay_load_clk_ref,
q_p_o => odelay_load_clk_odelay);
q_p_o => odelay_load_clk_par);
p_gearbox : process(clk_par_i)
begin
......@@ -311,7 +320,7 @@ begin
end process;
U_Serdes : OSERDESE3
generic map (
......@@ -345,8 +354,28 @@ begin
b_odelay : block
attribute IODELAY_GROUP: string;
attribute IODELAY_GROUP of U_ODELAYE3_Fine_Pulse_Gen : label is "IODELAY_FPGen";
signal odelay_rst_clk_par : std_logic;
signal odelay_en_vtc_clk_par : std_logic;
begin
U_Sync_Reset : gc_sync_ffs
port map (
clk_i => clk_par_i,
rst_n_i => '1',
data_i => odelay_rst_i,
synced_o => odelay_rst_clk_par
);
U_Sync_VTC : gc_sync_ffs
port map (
clk_i => clk_par_i,
rst_n_i => '1',
data_i => odelay_en_vtc_i,
synced_o => odelay_en_vtc_clk_par
);
-- If a OSERDESE3 block (or its simplified version ODDRE) is instantiated,
-- the ODELAYE3 CLK and OSERDESE3 CLK_DIV (or ODDRE C) port must share the same clock
U_ODELAYE3_Fine_Pulse_Gen : ODELAYE3
......@@ -357,7 +386,7 @@ begin
DELAY_VALUE => c_DELAY_VALUE, -- Output delay tap setting
IS_CLK_INVERTED => '0', -- Optional inversion for CLK
IS_RST_INVERTED => '0', -- Optional inversion for RST
REFCLK_FREQUENCY => g_CLK_ODELAY_FREQ, -- IDELAYCTRL clock input frequency in MHz (200.0-2667.0).
REFCLK_FREQUENCY => g_idelayctrl_ref_clk_freq, -- IDELAYCTRL clock input frequency in MHz (200.0-2667.0).
SIM_DEVICE => "ULTRASCALE", -- Set the device version (ULTRASCALE, ULTRASCALE_PLUS, ULTRASCALE_PLUS_ES1, ULTRASCALE_PLUS_ES2)
UPDATE_MODE => "ASYNC" -- Determines when updates to the delay will take effect (ASYNC, MANUAL, SYNC)
)
......@@ -370,18 +399,19 @@ begin
CE => '0', -- 1-bit input: Active high enable increment/decrement input
CLK => clk_par_i, -- 1-bit input: Clock input
CNTVALUEIN => odelay_value_in, -- 9-bit input: Counter value input
EN_VTC => odelay_en_vtc_i, -- 1-bit input: Keep delay constant over VT
EN_VTC => odelay_en_vtc_clk_par, -- 1-bit input: Keep delay constant over VT
INC => '0', -- 1-bit input: Increment/Decrement tap delay input
LOAD => odelay_load_clk_odelay, -- 1-bit input: Load DELAY_VALUE input
LOAD => odelay_load_clk_par, -- 1-bit input: Load DELAY_VALUE input
ODATAIN => pulse_predelay, -- 1-bit input: Data input
RST => odelay_rst_i -- 1-bit input: Asynchronous Reset to the DELAY_VALUE
RST => odelay_rst_clk_par -- 1-bit input: Asynchronous Reset to the DELAY_VALUE
);
end block;
-- same delay applied to all pins
p_latch_delay : process(clk_odelay_i)
p_latch_delay : process(clk_sys_i)
begin
if rising_edge(clk_odelay_i) then
if rising_edge(clk_sys_i) then
if odelay_cal_latch_i = '1' then
odelay_value_out_o <= odelay_value_out;
end if;
......
library ieee;
use ieee.std_logic_1164.all;
use work.gencores_pkg.all;
library unisim;
......@@ -146,8 +147,17 @@ begin
b_idelayctrl: block
attribute IODELAY_GROUP: string;
attribute IODELAY_GROUP of U_IDELAYCTRL_Fine_Pulse_Gen : label is "IODELAY_FPGen";
signal rst_synced : std_logic;
begin
U_Sync_Reset : gc_sync_ffs
port map (
clk_i => clk_odelay,
rst_n_i => '1',
data_i => odelayctrl_rst_i,
synced_o => rst_synced
);
U_IDELAYCTRL_Fine_Pulse_Gen : IDELAYCTRL
generic map (
SIM_DEVICE => "ULTRASCALE" -- Must be set to "ULTRASCALE"
......@@ -198,7 +208,7 @@ begin
CLKOUT2_DIVIDE => 4, -- clk_odelay: 250 MHz
CLKOUT2_DUTY_CYCLE => 0.5,
CLKOUT2_PHASE => 0.0,
CLKOUT0_USE_FINE_PS => "FALSE",
CLKOUT1_USE_FINE_PS => "FALSE"
)
......
......@@ -103,7 +103,6 @@ peripheral {
size = 6;
type = SLV;
prefix = "READY";
clock = "clk_ref_i";
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
......@@ -606,21 +605,18 @@ peripheral {
name = "Reset Output IDELAYCTRL";
type = BIT;
prefix = "rst_idelayctrl";
clock = "clk_odelay_i";
};
field {
name = "Reset Output ODELAY";
type = BIT;
prefix = "rst_odelay";
clock = "clk_odelay_i";
};
field {
name = "Reset Output OSERDES";
type = BIT;
prefix = "rst_oserdes";
clock = "clk_oserdes_i";
};
field {
......@@ -629,7 +625,6 @@ peripheral {
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
prefix = "rdy";
clock = "clk_odelay_i";
};
field {
......@@ -640,27 +635,14 @@ peripheral {
access_bus = READ_WRITE;
access_dev = READ_ONLY;
prefix = "value";
clock = "clk_ref_i";
};
field {
name = "Delay value update";
prefix = "value_update";
type = MONOSTABLE;
clock = "clk_ref_i";
};
field {
name = "Serdes Bitslip";
description = "Bit slip of the DAC output serdes. Together with the value field, it allows output delay adjustment range of a full DAC clock cycle. Expressed in nanoseconds (0 to 4).";
type = SLV;
size = 2;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
prefix = "bitslip";
clock = "clk_odelay_i";
};
field {
name = "Enable VT compensation";
description = "Enable VT compensation";
......@@ -668,14 +650,12 @@ peripheral {
access_bus = READ_WRITE;
access_dev = READ_ONLY;
prefix = "en_vtc";
clock = "clk_odelay_i";
};
field {
name = "Latch calibration taps";
type = MONOSTABLE;
prefix = "cal_latch";
clock = "clk_odelay_i";
};
field {
......@@ -686,7 +666,6 @@ peripheral {
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
prefix = "taps";
clock = "clk_odelay_i";
};
};
};
......@@ -3,7 +3,7 @@
---------------------------------------------------------------------------------------
-- File : fine_pulse_gen_wbgen2_pkg.vhd
-- Author : auto-generated by wbgen2 from fine_pulse_gen_wb.wb
-- Created : Wed Jun 24 13:47:27 2020
-- Created : Tue Jul 7 14:29:21 2020
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE fine_pulse_gen_wb.wb
......@@ -106,7 +106,6 @@ package fpg_wbgen2_pkg is
odelay_calib_rst_oserdes_o : std_logic;
odelay_calib_value_o : std_logic_vector(8 downto 0);
odelay_calib_value_update_o : std_logic;
odelay_calib_bitslip_o : std_logic_vector(1 downto 0);
odelay_calib_en_vtc_o : std_logic;
odelay_calib_cal_latch_o : std_logic;
end record;
......@@ -181,7 +180,6 @@ package fpg_wbgen2_pkg is
odelay_calib_rst_oserdes_o => '0',
odelay_calib_value_o => (others => '0'),
odelay_calib_value_update_o => '0',
odelay_calib_bitslip_o => (others => '0'),
odelay_calib_en_vtc_o => '0',
odelay_calib_cal_latch_o => '0'
);
......@@ -194,9 +192,6 @@ component fine_pulse_gen_wb is
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
clk_ref_i : in std_logic;
clk_odelay_i : in std_logic;
clk_oserdes_i : in std_logic;
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out;
int_o : out std_logic;
......
......@@ -24,7 +24,7 @@ entity xwb_fine_pulse_gen is
clk_ser_ext_i : in std_logic := '0'; -- external SERDES clock, used when
-- g_use_external_serdes_clock == true
ext_trigger_p_i : in std_logic := '0'; -- External trigger (i.e. RF receiver)
pps_p_i : in std_logic; -- WR PPS
......@@ -49,7 +49,7 @@ architecture rtl of xwb_fine_pulse_gen is
return false;
end if;
end function;
component fine_pulse_gen_kintex7_shared is
......@@ -100,7 +100,7 @@ architecture rtl of xwb_fine_pulse_gen is
cont : std_logic;
force_tr : std_logic;
odelay_load : std_logic;
odelay_value_out : std_logic_vector(8 downto 0);
......@@ -109,19 +109,19 @@ architecture rtl of xwb_fine_pulse_gen is
type t_channel_array is array(integer range <>) of t_channel;
constant c_MAX_NUM_CHANNELS : integer := 6;
signal ch : t_channel_array(0 to c_MAX_NUM_CHANNELS-1);
signal clk_par : std_logic;
signal clk_ser : std_logic;
signal clk_odelay : std_logic;
signal regs_out : t_fpg_out_registers;
signal regs_in : t_fpg_in_registers;
signal rst_n_wr : std_logic;
signal pps_p_d : std_logic;
function f_to_bool(x : bit) return boolean is
begin
if x= '1' then
......@@ -130,28 +130,33 @@ architecture rtl of xwb_fine_pulse_gen is
return false;
end if;
end f_to_bool;
constant c_pps_divider : integer := 6250;
signal pps_ext : std_logic;
signal pps_cnt : unsigned(15 downto 0);
signal pll_locked : std_logic;
signal rst_serdes : std_logic;
signal rst_serdes_in, rst_serdes : std_logic;
signal odelay_calib_rdy : std_logic;
signal pps_p1 : std_logic;
begin
p_extend_pps : process(clk_ref_i)
begin
if rising_edge(clk_ref_i) then
if rst_n_wr = '0' then
pps_ext <= '0';
pps_cnt <= (others => '0');
pps_p1 <= '0';
else
pps_p_d <= pps_p_i;
pps_p1 <= not pps_p_d and pps_p_i;
if pps_p_i = '1' and pps_p_d = '0' then
pps_cnt <= to_unsigned(1, pps_cnt'length);
pps_ext <= '0';
......@@ -165,16 +170,13 @@ begin
end if;
end if;
end process;
U_Regs : entity work.fine_pulse_gen_wb
port map (
rst_n_i => rst_sys_n_i,
clk_sys_i => clk_sys_i,
clk_ref_i => clk_ref_i,
slave_i => slave_i,
slave_o => slave_o,
clk_odelay_i => clk_odelay,
clk_oserdes_i => clk_par,
regs_i => regs_in,
regs_o => regs_out);
......@@ -274,13 +276,27 @@ begin
q_p_o => ch(5).force_tr);
regs_in.csr_ready_i(0) <= ch(0).ready;
regs_in.csr_ready_i(1) <= ch(1).ready;
regs_in.csr_ready_i(2) <= ch(2).ready;
regs_in.csr_ready_i(3) <= ch(3).ready;
regs_in.csr_ready_i(4) <= ch(4).ready;
regs_in.csr_ready_i(5) <= ch(5).ready;
gen_ready_flags : for i in 0 to g_num_channels-1 generate
U_Sync : gc_sync_ffs
port map (
clk_i => clk_sys_i,
rst_n_i => rst_sys_n_i,
data_i => ch(i).ready,
synced_o => regs_in.csr_ready_i(i)
);
end generate gen_ready_flags;
rst_serdes_in <= regs_out.odelay_calib_rst_oserdes_o or regs_out.csr_serdes_rst_o;
U_Sync_Serdes_Reset : gc_sync_ffs
port map (
clk_i => clk_ref_i,
rst_n_i => '1',
data_i => rst_serdes_in,
synced_o => rst_serdes
);
ch(0).pol <= regs_out.ocr0_pol_o;
ch(1).pol <= regs_out.ocr1_pol_o;
......@@ -323,13 +339,13 @@ begin
ch(3).pps_offs <= unsigned(regs_out.ocr3_pps_offs_o);
ch(4).pps_offs <= unsigned(regs_out.ocr4_pps_offs_o);
ch(5).pps_offs <= unsigned(regs_out.ocr5_pps_offs_o);
gen_channels : for i in 0 to g_NUM_CHANNELS-1 generate
p_fsm : process(clk_ref_i)
begin
if rising_edge(clk_ref_i) then
......@@ -337,20 +353,17 @@ begin
ch(i).state <= IDLE;
ch(i).trig_p <= '0';
ch(i).delay_load <= '0';
ch(i).trig_p <= '0';
ch(i).odelay_load <= '0';
else
if ch(i).trig_sel = '1' then
ch(i).trig_in <= ext_trigger_p_i;
else
ch(i).trig_in <= pps_p_i;
ch(i).trig_in <= pps_p1;
end if;
ch(i).trig_in_d <= ch(i).trig_in;
case ch(i).state is
when IDLE =>
ch(i).trig_p <= '0';
......@@ -379,8 +392,8 @@ begin
if pps_ext = '1' then
ch(i).state <= WAIT_TRIGGER;
end if;
when WAIT_PPS =>
ch(i).trig_p <= '0';
ch(i).delay_load <= '0';
......@@ -414,6 +427,7 @@ begin
port map (
clk_par_i => clk_par,
clk_serdes_i => clk_ser,
rst_serdes_i => rst_serdes,
rst_sys_n_i => rst_sys_n_i,
trig_p_i => ch(I).trig_p,
cont_i => ch(i).cont,
......@@ -430,14 +444,14 @@ begin
U_Pulse_Gen : entity work.fine_pulse_gen_kintexultrascale
generic map (
g_sim_delay_tap_ps => 50,
g_ref_clk_freq => 200.0,
g_idelayctrl_ref_clk_freq => 250.0,
g_use_odelay => f_to_bool(g_use_odelay(i)) )
port map (
clk_sys_i => clk_sys_i,
clk_par_i => clk_par,
clk_ref_i => clk_ref_i,
clk_serdes_i => clk_ser,
clk_odelay_i => clk_odelay,
rst_serdes_i => regs_out.csr_serdes_rst_o,
rst_serdes_i => rst_serdes,
rst_sys_n_i => rst_sys_n_i,
trig_p_i => ch(I).trig_p,
cont_i => ch(i).cont,
......@@ -457,7 +471,7 @@ begin
);
end generate gen_is_kintex_us_pg;
end generate;
......@@ -476,7 +490,7 @@ begin
clk_par_o => clk_par,
clk_ser_o => clk_ser,
clk_ser_ext_i => clk_ser_ext_i,
clk_odelay_o => clk_odelay,
-- clk_odelay_o => clk_odelay,
pll_locked_o => pll_locked);
end generate gen_is_kintex7;
......@@ -494,23 +508,24 @@ begin
clk_par_o => clk_par,
clk_ser_o => clk_ser,
clk_ser_ext_i => clk_ser_ext_i,
clk_odelay_o => clk_odelay,
-- clk_odelay_o => clk_odelay,
pll_locked_o => pll_locked,
odelayctrl_rdy_o => regs_in.odelay_calib_rdy_i,
odelayctrl_rdy_o => odelay_calib_rdy,
odelayctrl_rst_i => regs_out.odelay_calib_rst_idelayctrl_o
);
U_Sync_Reset : gc_sync_ffs
port map (
clk_i => clk_sys_i,
rst_n_i => rst_sys_n_i,
data_i => odelay_calib_rdy,
synced_o => regs_in.odelay_calib_rdy_i
);
end generate gen_is_kintex_ultrascale;
clk_par_o <= clk_par;
regs_in.csr_pll_locked_i <= pll_locked;
end rtl;
end rtl;
......@@ -152,11 +152,9 @@
`define FPG_ODELAY_CALIB_VALUE 32'h00001ff0
`define FPG_ODELAY_CALIB_VALUE_UPDATE_OFFSET 13
`define FPG_ODELAY_CALIB_VALUE_UPDATE 32'h00002000
`define FPG_ODELAY_CALIB_BITSLIP_OFFSET 14
`define FPG_ODELAY_CALIB_BITSLIP 32'h0000c000
`define FPG_ODELAY_CALIB_EN_VTC_OFFSET 16
`define FPG_ODELAY_CALIB_EN_VTC 32'h00010000
`define FPG_ODELAY_CALIB_CAL_LATCH_OFFSET 17
`define FPG_ODELAY_CALIB_CAL_LATCH 32'h00020000
`define FPG_ODELAY_CALIB_TAPS_OFFSET 18
`define FPG_ODELAY_CALIB_TAPS 32'h07fc0000
`define FPG_ODELAY_CALIB_EN_VTC_OFFSET 14
`define FPG_ODELAY_CALIB_EN_VTC 32'h00004000
`define FPG_ODELAY_CALIB_CAL_LATCH_OFFSET 15
`define FPG_ODELAY_CALIB_CAL_LATCH 32'h00008000
`define FPG_ODELAY_CALIB_TAPS_OFFSET 16
`define FPG_ODELAY_CALIB_TAPS 32'h01ff0000
......@@ -97,7 +97,7 @@ class FinePulseGenDriver extends IBusDevice;
calib_time = real'(1.0);
calib_taps = (rv & `FPG_ODELAY_CALIB_TAPS) >> `FPG_ODELAY_CALIB_TAPS_OFFSET;
$display("FPG ODELAY calibration done, val %.1f/%d\n", calib_time, calib_taps );
$display("FPG ODELAY calibration done, %.1f ns = %d taps\n", calib_time, calib_taps );
m_delay_tap_size = calib_time / real'(calib_taps);
......
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