From d69bd49323ab47764d2bc85f6cce40b5101850c3 Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> Date: Thu, 16 Apr 2020 17:28:19 +0200 Subject: [PATCH] wb_fine_pulse_gen: use double clock rate on Kintex7 Ultrascale, allowing for 1ns resolution --- .../fine_pulse_gen_kintexultrascale.vhd | 139 +++++++++++++----- ...fine_pulse_gen_kintexultrascale_shared.vhd | 15 +- .../wb_fine_pulse_gen/xwb_fine_pulse_gen.vhd | 1 + testbench/wishbone/wb_fine_pulse_gen/main.sv | 14 +- 4 files changed, 123 insertions(+), 46 deletions(-) diff --git a/modules/wishbone/wb_fine_pulse_gen/fine_pulse_gen_kintexultrascale.vhd b/modules/wishbone/wb_fine_pulse_gen/fine_pulse_gen_kintexultrascale.vhd index d7a6e6c3..b9e3ade0 100644 --- a/modules/wishbone/wb_fine_pulse_gen/fine_pulse_gen_kintexultrascale.vhd +++ b/modules/wishbone/wb_fine_pulse_gen/fine_pulse_gen_kintexultrascale.vhd @@ -16,9 +16,9 @@ entity fine_pulse_gen_kintexultrascale is ); port ( + clk_ref_i : in std_logic; clk_par_i : in std_logic; clk_serdes_i : in std_logic; - rst_serdes_i : in std_logic; rst_sys_n_i : in std_logic; @@ -62,9 +62,9 @@ architecture rtl of fine_pulse_gen_kintexultrascale is T : in std_ulogic); end component OSERDESE3; - signal par_data : std_logic_vector(7 downto 0); - - signal par_data_rev : 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(15 downto 0); signal dout_predelay, dout_prebuf, dout_nodelay : std_logic; signal odelay_load : std_logic; @@ -72,6 +72,7 @@ architecture rtl of fine_pulse_gen_kintexultrascale is signal odelay_ntaps : std_logic_vector(4 downto 0); + signal trig_d : std_logic; -- 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 -- 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 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 rst <= not rst_sys_n_i; - process(clk_par_i) - variable rv : std_logic_vector(15 downto 0); + process(clk_ref_i) + variable rv : std_logic_vector(31 downto 0); begin - if rising_edge(clk_par_i) then + if rising_edge(clk_ref_i) then dly_load_d <= dly_load_i; if dly_load_i = '1' then @@ -102,21 +109,37 @@ begin case coarse_i is when x"00" => - rv := "1111000011110000"; + rv := "11111111000000001111111100000000"; when x"01" => - rv := "0111100001111000"; + rv := "01111111100000000111111110000000"; when x"02" => - rv := "0011110000111100"; + rv := "00111111110000000011111111000000"; when x"03" => - rv := "0001111000011110"; + rv := "00011111111000000001111111100000"; when x"04" => - rv := "0000111100001111"; + rv := "00001111111100000000111111110000"; when x"05" => - rv := "1000011110000111"; + rv := "00000111111110000000011111111000"; when x"06" => - rv := "1100001111000011"; + rv := "00000011111111000000001111111100"; 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 => rv := (others => '0'); end case; @@ -125,21 +148,37 @@ begin else case coarse_i is when x"00" => - rv := "1111000000000000"; + rv := "11111111000000000000000000000000"; when x"01" => - rv := "0111100000000000"; + rv := "01111111100000000000000000000000"; when x"02" => - rv := "0011110000000000"; + rv := "00111111110000000000000000000000"; when x"03" => - rv := "0001111000000000"; + rv := "00011111111000000000000000000000"; when x"04" => - rv := "0000111100000000"; + rv := "00001111111100000000000000000000"; when x"05" => - rv := "0000011110000000"; + rv := "00000111111110000000000000000000"; when x"06" => - rv := "0000001111000000"; + rv := "00000011111111000000000000000000"; 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 => rv := (others => '0'); end case; @@ -159,17 +198,17 @@ begin trig_d <= trig_p_i; if trig_p_i = '1' then - par_data <= mask(15 downto 8); + par_data <= mask(31 downto 16); flip <= '0'; elsif trig_d = '1' then - par_data <= mask(7 downto 0); + par_data <= mask(15 downto 0); else if cont_i = '1' then if flip = '1' then - par_data <= mask(7 downto 0); + par_data <= mask(15 downto 0); else - par_data <= mask(15 downto 8); + par_data <= mask(31 downto 16); end if; else if pol_i = '1' then @@ -183,6 +222,34 @@ begin 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 generic map ( DATA_WIDTH => 8, @@ -198,14 +265,14 @@ begin OQ => pulse_o, CLK => clk_serdes_i, CLKDIV => clk_par_i, - D(0) => par_data(7), - D(1) => par_data(6), - D(2) => par_data(5), - D(3) => par_data(4), - D(4) => par_data(3), - D(5) => par_data(2), - D(6) => par_data(1), - D(7) => par_data(0), + D(0) => par_data_125(7), + D(1) => par_data_125(6), + D(2) => par_data_125(5), + D(3) => par_data_125(4), + D(4) => par_data_125(3), + D(5) => par_data_125(2), + D(6) => par_data_125(1), + D(7) => par_data_125(0), RST => rst_serdes_i, T => '0' ); diff --git a/modules/wishbone/wb_fine_pulse_gen/fine_pulse_gen_kintexultrascale_shared.vhd b/modules/wishbone/wb_fine_pulse_gen/fine_pulse_gen_kintexultrascale_shared.vhd index 5f1fa366..64da9c25 100644 --- a/modules/wishbone/wb_fine_pulse_gen/fine_pulse_gen_kintexultrascale_shared.vhd +++ b/modules/wishbone/wb_fine_pulse_gen/fine_pulse_gen_kintexultrascale_shared.vhd @@ -136,6 +136,7 @@ architecture rtl of fine_pulse_gen_kintexultrascale_shared is end component BUFG; signal clk_ser_prebuf, mmcm_clk_fb_prebuf, mmcm_clk_fb : std_logic; + signal clk_par_prebuf : std_logic; begin @@ -165,10 +166,14 @@ begin CLKFBOUT_PHASE => 0.0, -- Phase offset in degrees of CLKFB (-360.000-360.000) 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_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 ( -- Clock Inputs inputs: Clock inputs @@ -176,6 +181,7 @@ begin CLKIN2 => '0', -- Clock Outputs outputs: User configurable clock outputs CLKOUT0 => clk_ser_prebuf, + CLKOUT1 => clk_par_prebuf, -- Feedback CLKFBOUT => mmcm_clk_fb_prebuf, CLKFBIN => mmcm_clk_fb, @@ -208,7 +214,10 @@ begin I => clk_ser_prebuf, 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; diff --git a/modules/wishbone/wb_fine_pulse_gen/xwb_fine_pulse_gen.vhd b/modules/wishbone/wb_fine_pulse_gen/xwb_fine_pulse_gen.vhd index db8cf11a..c7b0c27a 100644 --- a/modules/wishbone/wb_fine_pulse_gen/xwb_fine_pulse_gen.vhd +++ b/modules/wishbone/wb_fine_pulse_gen/xwb_fine_pulse_gen.vhd @@ -427,6 +427,7 @@ begin g_use_odelay => f_to_bool(g_use_odelay(i)) ) port map ( clk_par_i => clk_par, + clk_ref_i => clk_ref_i, clk_serdes_i => clk_ser, rst_serdes_i => regs_out.csr_serdes_rst_o, rst_sys_n_i => rst_sys_n_i, diff --git a/testbench/wishbone/wb_fine_pulse_gen/main.sv b/testbench/wishbone/wb_fine_pulse_gen/main.sv index 7a061ffb..a1ef59d0 100644 --- a/testbench/wishbone/wb_fine_pulse_gen/main.sv +++ b/testbench/wishbone/wb_fine_pulse_gen/main.sv @@ -43,8 +43,8 @@ class DDSSyncUnitDriver; int coarse_par = int'($floor (delta / 16.0)); - int coarse_ser = int'($floor (delta / 2.0) - coarse_par * 8); - int fine = int'((delta / 2.0 - $floor(delta / 2.0)) * 2.0 / tap_size); + int coarse_ser = int'($floor (delta / 1.0) - coarse_par * 16); + int fine = int'((delta / 1.0 - $floor(delta / 1.0)) * 1.0 / tap_size); int mask = coarse_ser; //(1 << (7-coarse_ser+1)) - 1; uint32_t ocr; @@ -149,7 +149,7 @@ module main; 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; @@ -173,14 +173,14 @@ module main; xwb_fine_pulse_gen #( .g_target_platform("KintexUltrascale"), - .g_use_external_serdes_clock(1), + .g_use_external_serdes_clock(0), .g_num_channels(1) ) DUT ( .rst_sys_n_i(rst_n), - .clk_ser_ext_i(clk_250m), +// .clk_ser_ext_i(clk_250m), .clk_sys_i (clk_62m5), .clk_ref_i (clk_62m5), @@ -222,12 +222,12 @@ module main; -----/\----- EXCLUDED -----/\----- */ - for (t = 1.0; t <= 200.9; t+=1.0) + for (t = 1.0; t <= 200.9; t+=0.1) begin // $display("Pulse @ %f", t ); dlys.push_back(t); - drv.pulse(0, 0, 0, t); + drv.pulse(0, 1, 0, t); end -- GitLab