Commit d69bd493 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski Committed by Tristan Gingold

wb_fine_pulse_gen: use double clock rate on Kintex7 Ultrascale, allowing for 1ns resolution

parent 9bd003e5
...@@ -16,9 +16,9 @@ entity fine_pulse_gen_kintexultrascale is ...@@ -16,9 +16,9 @@ entity fine_pulse_gen_kintexultrascale is
); );
port port
( (
clk_ref_i : in std_logic;
clk_par_i : in std_logic; clk_par_i : in std_logic;
clk_serdes_i : in std_logic; clk_serdes_i : in std_logic;
rst_serdes_i : in std_logic; rst_serdes_i : in std_logic;
rst_sys_n_i : in std_logic; rst_sys_n_i : in std_logic;
...@@ -62,9 +62,9 @@ architecture rtl of fine_pulse_gen_kintexultrascale is ...@@ -62,9 +62,9 @@ architecture rtl of fine_pulse_gen_kintexultrascale is
T : in std_ulogic); T : in std_ulogic);
end component OSERDESE3; end component OSERDESE3;
signal par_data : std_logic_vector(7 downto 0); signal par_data : std_logic_vector(15 downto 0);
signal par_data_125 : std_logic_vector(7 downto 0);
signal par_data_rev : std_logic_vector(7 downto 0); signal par_data_rev : std_logic_vector(15 downto 0);
signal dout_predelay, dout_prebuf, dout_nodelay : std_logic; signal dout_predelay, dout_prebuf, dout_nodelay : std_logic;
signal odelay_load : std_logic; signal odelay_load : std_logic;
...@@ -72,6 +72,7 @@ architecture rtl of fine_pulse_gen_kintexultrascale is ...@@ -72,6 +72,7 @@ architecture rtl of fine_pulse_gen_kintexultrascale is
signal odelay_ntaps : std_logic_vector(4 downto 0); signal odelay_ntaps : std_logic_vector(4 downto 0);
signal trig_d : std_logic; signal trig_d : std_logic;
-- function f_gen_bitmask (coarse : std_logic_vector; pol : std_logic; cont : std_logic) return std_logic_vector is -- function f_gen_bitmask (coarse : std_logic_vector; pol : std_logic; cont : std_logic) return std_logic_vector is
...@@ -80,19 +81,25 @@ architecture rtl of fine_pulse_gen_kintexultrascale is ...@@ -80,19 +81,25 @@ architecture rtl of fine_pulse_gen_kintexultrascale is
-- end f_gen_bitmask; -- end f_gen_bitmask;
signal mask : std_logic_vector(15 downto 0); signal mask : std_logic_vector(31 downto 0);
signal flip : std_logic; signal flip : std_logic;
signal dly_load_d : std_logic; signal dly_load_d : std_logic;
signal clk_ref_div2 : std_logic := '0';
signal clk_ref_div2_d0, clk_ref_div2_d1, gb_sync_p : std_logic;
begin begin
rst <= not rst_sys_n_i; rst <= not rst_sys_n_i;
process(clk_par_i) process(clk_ref_i)
variable rv : std_logic_vector(15 downto 0); variable rv : std_logic_vector(31 downto 0);
begin begin
if rising_edge(clk_par_i) then if rising_edge(clk_ref_i) then
dly_load_d <= dly_load_i; dly_load_d <= dly_load_i;
if dly_load_i = '1' then if dly_load_i = '1' then
...@@ -102,21 +109,37 @@ begin ...@@ -102,21 +109,37 @@ begin
case coarse_i is case coarse_i is
when x"00" => when x"00" =>
rv := "1111000011110000"; rv := "11111111000000001111111100000000";
when x"01" => when x"01" =>
rv := "0111100001111000"; rv := "01111111100000000111111110000000";
when x"02" => when x"02" =>
rv := "0011110000111100"; rv := "00111111110000000011111111000000";
when x"03" => when x"03" =>
rv := "0001111000011110"; rv := "00011111111000000001111111100000";
when x"04" => when x"04" =>
rv := "0000111100001111"; rv := "00001111111100000000111111110000";
when x"05" => when x"05" =>
rv := "1000011110000111"; rv := "00000111111110000000011111111000";
when x"06" => when x"06" =>
rv := "1100001111000011"; rv := "00000011111111000000001111111100";
when x"07" => when x"07" =>
rv := "1110000111100001"; rv := "00000001111111100000000111111110";
when x"08" =>
rv := "00000000111111110000000011111111";
when x"09" =>
rv := "00000000011111111000000001111111";
when x"0a" =>
rv := "00000000001111111100000000111111";
when x"0b" =>
rv := "00000000000111111110000000011111";
when x"0c" =>
rv := "00000000000011111111000000001111";
when x"0d" =>
rv := "00000000000001111111100000000111";
when x"0e" =>
rv := "00000000000000111111110000000011";
when x"0f" =>
rv := "00000000000000011111111000000001";
when others => when others =>
rv := (others => '0'); rv := (others => '0');
end case; end case;
...@@ -125,21 +148,37 @@ begin ...@@ -125,21 +148,37 @@ begin
else else
case coarse_i is case coarse_i is
when x"00" => when x"00" =>
rv := "1111000000000000"; rv := "11111111000000000000000000000000";
when x"01" => when x"01" =>
rv := "0111100000000000"; rv := "01111111100000000000000000000000";
when x"02" => when x"02" =>
rv := "0011110000000000"; rv := "00111111110000000000000000000000";
when x"03" => when x"03" =>
rv := "0001111000000000"; rv := "00011111111000000000000000000000";
when x"04" => when x"04" =>
rv := "0000111100000000"; rv := "00001111111100000000000000000000";
when x"05" => when x"05" =>
rv := "0000011110000000"; rv := "00000111111110000000000000000000";
when x"06" => when x"06" =>
rv := "0000001111000000"; rv := "00000011111111000000000000000000";
when x"07" => when x"07" =>
rv := "0000000111100000"; rv := "00000001111111100000000000000000";
when x"08" =>
rv := "00000000111111110000000000000000";
when x"09" =>
rv := "00000000011111111000000000000000";
when x"0a" =>
rv := "00000000001111111100000000000000";
when x"0b" =>
rv := "00000000000111111110000000000000";
when x"0c" =>
rv := "00000000000011111111000000000000";
when x"0d" =>
rv := "00000000000001111111100000000000";
when x"0e" =>
rv := "00000000000000111111110000000000";
when x"0f" =>
rv := "00000000000000011111111000000000";
when others => when others =>
rv := (others => '0'); rv := (others => '0');
end case; end case;
...@@ -159,17 +198,17 @@ begin ...@@ -159,17 +198,17 @@ begin
trig_d <= trig_p_i; trig_d <= trig_p_i;
if trig_p_i = '1' then if trig_p_i = '1' then
par_data <= mask(15 downto 8); par_data <= mask(31 downto 16);
flip <= '0'; flip <= '0';
elsif trig_d = '1' then elsif trig_d = '1' then
par_data <= mask(7 downto 0); par_data <= mask(15 downto 0);
else else
if cont_i = '1' then if cont_i = '1' then
if flip = '1' then if flip = '1' then
par_data <= mask(7 downto 0); par_data <= mask(15 downto 0);
else else
par_data <= mask(15 downto 8); par_data <= mask(31 downto 16);
end if; end if;
else else
if pol_i = '1' then if pol_i = '1' then
...@@ -183,6 +222,34 @@ begin ...@@ -183,6 +222,34 @@ begin
end process; end process;
p_div_clk : process(clk_ref_i, rst_serdes_i )
begin
if rst_serdes_i = '1' then
clk_ref_div2 <= '0';
elsif rising_edge(clk_ref_i) then
clk_ref_div2 <= not clk_ref_div2;
end if;
end process;
p_gearbox : process(clk_par_i)
begin
if rising_edge(clk_par_i) then
clk_ref_div2_d0 <= clk_ref_div2;
clk_ref_div2_d1 <= clk_ref_div2_d0;
gb_sync_p <= clk_ref_div2_d0 xor clk_ref_div2_d1;
if gb_sync_p = '1' then
par_data_125 <= par_data(15 downto 8);
else
par_data_125 <= par_data(7 downto 0);
end if;
end if;
end process;
U_Serdes : OSERDESE3 U_Serdes : OSERDESE3
generic map ( generic map (
DATA_WIDTH => 8, DATA_WIDTH => 8,
...@@ -198,14 +265,14 @@ begin ...@@ -198,14 +265,14 @@ begin
OQ => pulse_o, OQ => pulse_o,
CLK => clk_serdes_i, CLK => clk_serdes_i,
CLKDIV => clk_par_i, CLKDIV => clk_par_i,
D(0) => par_data(7), D(0) => par_data_125(7),
D(1) => par_data(6), D(1) => par_data_125(6),
D(2) => par_data(5), D(2) => par_data_125(5),
D(3) => par_data(4), D(3) => par_data_125(4),
D(4) => par_data(3), D(4) => par_data_125(3),
D(5) => par_data(2), D(5) => par_data_125(2),
D(6) => par_data(1), D(6) => par_data_125(1),
D(7) => par_data(0), D(7) => par_data_125(0),
RST => rst_serdes_i, RST => rst_serdes_i,
T => '0' T => '0'
); );
......
...@@ -136,6 +136,7 @@ architecture rtl of fine_pulse_gen_kintexultrascale_shared is ...@@ -136,6 +136,7 @@ architecture rtl of fine_pulse_gen_kintexultrascale_shared is
end component BUFG; end component BUFG;
signal clk_ser_prebuf, mmcm_clk_fb_prebuf, mmcm_clk_fb : std_logic; signal clk_ser_prebuf, mmcm_clk_fb_prebuf, mmcm_clk_fb : std_logic;
signal clk_par_prebuf : std_logic;
begin begin
...@@ -165,10 +166,14 @@ begin ...@@ -165,10 +166,14 @@ begin
CLKFBOUT_PHASE => 0.0, -- Phase offset in degrees of CLKFB (-360.000-360.000) CLKFBOUT_PHASE => 0.0, -- Phase offset in degrees of CLKFB (-360.000-360.000)
CLKFBOUT_USE_FINE_PS => "FALSE", CLKFBOUT_USE_FINE_PS => "FALSE",
CLKOUT0_DIVIDE_F => 4.0, -- clk_ser: 250 MHz CLKOUT0_DIVIDE_F => 2.0, -- clk_ser: 500 MHz
CLKOUT0_DUTY_CYCLE => 0.5, CLKOUT0_DUTY_CYCLE => 0.5,
CLKOUT0_PHASE => 0.0, CLKOUT0_PHASE => 0.0,
CLKOUT0_USE_FINE_PS => "FALSE" CLKOUT1_DIVIDE => 8, -- clk_par: 125 MHz
CLKOUT1_DUTY_CYCLE => 0.5,
CLKOUT1_PHASE => 0.0,
CLKOUT0_USE_FINE_PS => "FALSE",
CLKOUT1_USE_FINE_PS => "FALSE"
) )
port map ( port map (
-- Clock Inputs inputs: Clock inputs -- Clock Inputs inputs: Clock inputs
...@@ -176,6 +181,7 @@ begin ...@@ -176,6 +181,7 @@ begin
CLKIN2 => '0', CLKIN2 => '0',
-- Clock Outputs outputs: User configurable clock outputs -- Clock Outputs outputs: User configurable clock outputs
CLKOUT0 => clk_ser_prebuf, CLKOUT0 => clk_ser_prebuf,
CLKOUT1 => clk_par_prebuf,
-- Feedback -- Feedback
CLKFBOUT => mmcm_clk_fb_prebuf, CLKFBOUT => mmcm_clk_fb_prebuf,
CLKFBIN => mmcm_clk_fb, CLKFBIN => mmcm_clk_fb,
...@@ -208,7 +214,10 @@ begin ...@@ -208,7 +214,10 @@ begin
I => clk_ser_prebuf, I => clk_ser_prebuf,
O => clk_ser_o); O => clk_ser_o);
clk_par_o <= clk_ref_i; u_buf_mmcm_par : BUFG
port map (
I => clk_par_prebuf,
O => clk_par_o);
end generate gen_use_int_serdes_clock; end generate gen_use_int_serdes_clock;
......
...@@ -427,6 +427,7 @@ begin ...@@ -427,6 +427,7 @@ begin
g_use_odelay => f_to_bool(g_use_odelay(i)) ) g_use_odelay => f_to_bool(g_use_odelay(i)) )
port map ( port map (
clk_par_i => clk_par, clk_par_i => clk_par,
clk_ref_i => clk_ref_i,
clk_serdes_i => clk_ser, clk_serdes_i => clk_ser,
rst_serdes_i => regs_out.csr_serdes_rst_o, rst_serdes_i => regs_out.csr_serdes_rst_o,
rst_sys_n_i => rst_sys_n_i, rst_sys_n_i => rst_sys_n_i,
......
...@@ -43,8 +43,8 @@ class DDSSyncUnitDriver; ...@@ -43,8 +43,8 @@ class DDSSyncUnitDriver;
int coarse_par = int'($floor (delta / 16.0)); int coarse_par = int'($floor (delta / 16.0));
int coarse_ser = int'($floor (delta / 2.0) - coarse_par * 8); int coarse_ser = int'($floor (delta / 1.0) - coarse_par * 16);
int fine = int'((delta / 2.0 - $floor(delta / 2.0)) * 2.0 / tap_size); int fine = int'((delta / 1.0 - $floor(delta / 1.0)) * 1.0 / tap_size);
int mask = coarse_ser; int mask = coarse_ser;
//(1 << (7-coarse_ser+1)) - 1; //(1 << (7-coarse_ser+1)) - 1;
uint32_t ocr; uint32_t ocr;
...@@ -149,7 +149,7 @@ module main; ...@@ -149,7 +149,7 @@ module main;
first_delay = dly; first_delay = dly;
$display("t_pps %t t_pulse %t delta %d", t_pps, t_pulse, (t_pulse - t_pps) / 1ns ); $display("t_pps %t t_pulse %t delta %.2f", t_pps, t_pulse, real'(t_pulse - t_pps) / real'(1ns) );
/* delta = dly-first_delay; /* delta = dly-first_delay;
...@@ -173,14 +173,14 @@ module main; ...@@ -173,14 +173,14 @@ module main;
xwb_fine_pulse_gen xwb_fine_pulse_gen
#( #(
.g_target_platform("KintexUltrascale"), .g_target_platform("KintexUltrascale"),
.g_use_external_serdes_clock(1), .g_use_external_serdes_clock(0),
.g_num_channels(1) .g_num_channels(1)
) )
DUT DUT
( (
.rst_sys_n_i(rst_n), .rst_sys_n_i(rst_n),
.clk_ser_ext_i(clk_250m), // .clk_ser_ext_i(clk_250m),
.clk_sys_i (clk_62m5), .clk_sys_i (clk_62m5),
.clk_ref_i (clk_62m5), .clk_ref_i (clk_62m5),
...@@ -222,12 +222,12 @@ module main; ...@@ -222,12 +222,12 @@ module main;
-----/\----- EXCLUDED -----/\----- */ -----/\----- EXCLUDED -----/\----- */
for (t = 1.0; t <= 200.9; t+=1.0) for (t = 1.0; t <= 200.9; t+=0.1)
begin begin
// $display("Pulse @ %f", t ); // $display("Pulse @ %f", t );
dlys.push_back(t); dlys.push_back(t);
drv.pulse(0, 0, 0, t); drv.pulse(0, 1, 0, t);
end end
......
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