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

wishbone: added Fine Pulse Generator module

parent b694c67c
......@@ -27,6 +27,7 @@ modules = { "local" : [
"wb_split",
"wb16_to_wb32",
"wb_indirect",
"wb_fine_pulse_gen",
"wbgen2",
"wbgenplus",
"wb_xc7_fw_update",
......
files = [
"fine_pulse_gen_kintex7_shared.vhd",
"fine_pulse_gen_kintexultrascale_shared.vhd",
"fine_pulse_gen_kintex7.vhd",
"fine_pulse_gen_kintexultrascale.vhd",
"fine_pulse_gen_wbgen2_pkg.vhd",
"fine_pulse_gen_wb.vhd",
"xwb_fine_pulse_gen.vhd"]
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
library unisim;
use unisim.VCOMPONENTS.all;
entity fine_pulse_gen_kintex7 is
generic (
g_sim_delay_tap_ps : integer := 30;
g_ref_clk_freq : real := 125.0;
g_use_odelay : boolean := false
);
port
(
clk_par_i : in std_logic;
clk_serdes_i : in std_logic;
rst_sys_n_i : in std_logic;
cont_i : in std_logic;
pol_i : in std_logic;
coarse_i : in std_logic_vector(7 downto 0);
trig_p_i : in std_logic;
pulse_o : out std_logic;
dly_load_i : in std_logic;
dly_fine_i : in std_logic_vector(4 downto 0)
);
end fine_pulse_gen_kintex7;
architecture rtl of fine_pulse_gen_kintex7 is
signal par_data : std_logic_vector(7 downto 0);
signal dout_predelay, dout_prebuf, dout_nodelay : std_logic;
signal odelay_load : std_logic;
signal rst : std_logic;
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
-- variable rv : std_logic_vector(15 downto 0);
-- begin
-- end f_gen_bitmask;
signal mask : std_logic_vector(15 downto 0);
signal flip : std_logic;
signal dly_load_d : std_logic;
begin
rst <= not rst_sys_n_i;
process(clk_par_i)
variable rv : std_logic_vector(15 downto 0);
begin
if rising_edge(clk_par_i) then
dly_load_d <= dly_load_i;
if dly_load_i = '1' then
odelay_ntaps <= dly_fine_i;
if cont_i = '1' then
case coarse_i is
when x"00" =>
rv := "1111000011110000";
when x"01" =>
rv := "0111100001111000";
when x"02" =>
rv := "0011110000111100";
when x"03" =>
rv := "0001111000011110";
when x"04" =>
rv := "0000111100001111";
when x"05" =>
rv := "1000011110000111";
when x"06" =>
rv := "1100001111000011";
when x"07" =>
rv := "1110000111100001";
when others =>
rv := (others => '0');
end case;
else
case coarse_i is
when x"00" =>
rv := "1111000000000000";
when x"01" =>
rv := "0111100000000000";
when x"02" =>
rv := "0011110000000000";
when x"03" =>
rv := "0001111000000000";
when x"04" =>
rv := "0000111100000000";
when x"05" =>
rv := "0000011110000000";
when x"06" =>
rv := "0000001111000000";
when x"07" =>
rv := "0000000111100000";
when others =>
rv := (others => '0');
end case;
end if;
if pol_i = '0' then
mask <= rv;
else
mask <= not rv;
end if;
end if;
odelay_load <= dly_load_i or dly_load_d;
trig_d <= trig_p_i;
if trig_p_i = '1' then
par_data <= mask(15 downto 8);
flip <= '0';
elsif trig_d = '1' then
par_data <= mask(7 downto 0);
else
if cont_i = '1' then
if flip = '1' then
par_data <= mask(7 downto 0);
else
par_data <= mask(15 downto 8);
end if;
else
if pol_i = '1' then
par_data <= (others => '1');
else
par_data <= (others => '0');
end if;
end if;
end if;
end if;
end process;
U_Serdes : OSERDESE2
generic map (
DATA_RATE_OQ => "SDR",
DATA_RATE_TQ => "SDR",
DATA_WIDTH => 8,
TRISTATE_WIDTH => 1,
SERDES_MODE => "MASTER")
port map (
D1 => par_data(7),
D2 => par_data(6),
D3 => par_data(5),
D4 => par_data(4),
D5 => par_data(3),
D6 => par_data(2),
D7 => par_data(1),
D8 => par_data(0),
T1 => '0',
T2 => '0',
T3 => '0',
T4 => '0',
SHIFTIN1 => '0',
SHIFTIN2 => '0',
OCE => '1',
CLK => clk_serdes_i,
CLKDIV => clk_par_i,
OFB => dout_predelay,
OQ => dout_nodelay,
TBYTEIN => '0',
TCE => '0',
RST => rst);
gen_with_odelay : if g_use_odelay generate
U_Delay : ODELAYE2
generic map (
CINVCTRL_SEL => "FALSE",
DELAY_SRC => "ODATAIN",
HIGH_PERFORMANCE_MODE => "TRUE",
ODELAY_TYPE => "VAR_LOAD",
ODELAY_VALUE => 0,
REFCLK_FREQUENCY => g_ref_clk_freq,
PIPE_SEL => "FALSE",
SIGNAL_PATTERN => "DATA"
)
port map (
DATAOUT => dout_prebuf,
CLKIN => '0',
C => clk_par_i,
CE => '0',
INC => '0',
ODATAIN => dout_predelay,
LD => odelay_load,
REGRST => rst,
LDPIPEEN => '0',
CNTVALUEIN => odelay_ntaps,
CINVCTRL => '0'
);
end generate gen_with_odelay;
gen_without_odelay : if not g_use_odelay generate
dout_prebuf <= dout_nodelay;
end generate gen_without_odelay;
pulse_o <= dout_prebuf;
-- gen_output_diff : if g_use_diff_output generate
-- U_OBuf : OBUFDS
-- generic map(
-- IOSTANDARD => "LVDS_25",
-- SLEW => "FAST")
-- port map(
-- O => pulse_p_o,
-- OB => pulse_n_o,
-- I => dout_prebuf);
-- end generate gen_output_diff;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
library unisim;
use unisim.VCOMPONENTS.all;
entity fine_pulse_gen_kintex7_shared is
generic (
g_global_use_odelay : boolean;
g_use_external_serdes_clock : boolean
);
port (
-- PLL async reset
pll_rst_i : in std_logic;
clk_ser_ext_i : in std_logic;
-- 62.5 MHz reference
clk_ref_i : in std_logic;
-- serdes parallel clock
clk_par_o : out std_logic;
-- serdes serial clock
clk_ser_o : out std_logic;
clk_odelay_o : out std_logic;
pll_locked_o : out std_logic
);
end fine_pulse_gen_kintex7_shared;
architecture rtl of fine_pulse_gen_kintex7_shared is
signal pll_locked : std_logic;
signal clk_fb_pll, clk_fb_pll_bufg, clk_iodelay, clk_iodelay_bufg : std_logic;
begin
pll_iodelay_map : PLLE2_ADV
generic map(
BANDWIDTH => ("HIGH"),
COMPENSATION => ("ZHOLD"),
STARTUP_WAIT => ("FALSE"),
DIVCLK_DIVIDE => (1),
CLKFBOUT_MULT => (16),
CLKFBOUT_PHASE => (0.000),
CLKOUT0_DIVIDE => (5), -- 200 MHz
CLKOUT0_PHASE => (0.000),
CLKOUT0_DUTY_CYCLE => (0.500),
CLKOUT1_DIVIDE => (2), -- 500 MHz
CLKOUT1_PHASE => (0.000),
CLKOUT1_DUTY_CYCLE => (0.500),
CLKIN1_PERIOD => (16.000))
port map(
CLKFBOUT => clk_fb_pll,
CLKOUT0 => clk_iodelay,
CLKOUT1 => clk_ser_o,
-- Input clock control
CLKFBIN => clk_fb_pll_bufg,
CLKIN1 => clk_ref_i,
CLKIN2 => '0',
CLKINSEL => '1',
DADDR => (others => '0'),
DCLK => '0',
DEN => '0',
DI => (others => '0'),
DWE => '0',
PWRDWN => '0',
RST => pll_rst_i,
LOCKED => pll_locked_o
);
clk_par_o <= clk_ref_i;
int_bufg : BUFG
port map (
O => clk_fb_pll_bufg,
I => clk_fb_pll
);
gen_with_iodelay : if g_global_use_odelay generate
int_bufg_clkiodelay : BUFG
port map (
O => clk_iodelay_bufg,
I => clk_iodelay
);
IDELAYCTRL_inst : IDELAYCTRL
port map (
RDY => open, -- 1-bit output: Ready output
REFCLK => clk_iodelay_bufg, -- 1-bit input: Reference clock input
RST => '0' -- 1-bit input: Active high reset input
);
clk_odelay_o <= clk_iodelay_bufg;
end generate gen_with_iodelay;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
library unisim;
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
);
port
(
clk_par_i : in std_logic;
clk_serdes_i : in std_logic;
rst_sys_n_i : in std_logic;
cont_i : in std_logic;
pol_i : in std_logic;
coarse_i : in std_logic_vector(7 downto 0);
trig_p_i : in std_logic;
pulse_o : out std_logic;
dly_load_i : in std_logic;
dly_fine_i : in std_logic_vector(4 downto 0)
);
end fine_pulse_gen_kintexultrascale;
architecture rtl of fine_pulse_gen_kintexultrascale is
component OSERDESE3 is
generic (
DATA_WIDTH : integer := 8;
INIT : bit := '0';
IS_CLKDIV_INVERTED : bit := '0';
IS_CLK_INVERTED : bit := '0';
IS_RST_INVERTED : bit := '0';
ODDR_MODE : string := "FALSE";
OSERDES_D_BYPASS : string := "FALSE";
OSERDES_T_BYPASS : string := "FALSE";
SIM_DEVICE : string := "ULTRASCALE";
SIM_VERSION : real := 2.0);
port (
OQ : out std_ulogic;
T_OUT : out std_ulogic;
CLK : in std_ulogic;
CLKDIV : in std_ulogic;
D : in std_logic_vector(7 downto 0);
RST : in std_ulogic;
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 dout_predelay, dout_prebuf, dout_nodelay : std_logic;
signal odelay_load : std_logic;
signal rst : std_logic;
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
-- variable rv : std_logic_vector(15 downto 0);
-- begin
-- end f_gen_bitmask;
signal mask : std_logic_vector(15 downto 0);
signal flip : std_logic;
signal dly_load_d : std_logic;
begin
rst <= not rst_sys_n_i;
process(clk_par_i)
variable rv : std_logic_vector(15 downto 0);
begin
if rising_edge(clk_par_i) then
dly_load_d <= dly_load_i;
if dly_load_i = '1' then
odelay_ntaps <= dly_fine_i;
if cont_i = '1' then
case coarse_i is
when x"00" =>
rv := "1111000011110000";
when x"01" =>
rv := "0111100001111000";
when x"02" =>
rv := "0011110000111100";
when x"03" =>
rv := "0001111000011110";
when x"04" =>
rv := "0000111100001111";
when x"05" =>
rv := "1000011110000111";
when x"06" =>
rv := "1100001111000011";
when x"07" =>
rv := "1110000111100001";
when others =>
rv := (others => '0');
end case;
else
case coarse_i is
when x"00" =>
rv := "1111000000000000";
when x"01" =>
rv := "0111100000000000";
when x"02" =>
rv := "0011110000000000";
when x"03" =>
rv := "0001111000000000";
when x"04" =>
rv := "0000111100000000";
when x"05" =>
rv := "0000011110000000";
when x"06" =>
rv := "0000001111000000";
when x"07" =>
rv := "0000000111100000";
when others =>
rv := (others => '0');
end case;
end if;
if pol_i = '0' then
mask <= rv;
else
mask <= not rv;
end if;
end if;
odelay_load <= dly_load_i or dly_load_d;
trig_d <= trig_p_i;
if trig_p_i = '1' then
par_data <= mask(15 downto 8);
flip <= '0';
elsif trig_d = '1' then
par_data <= mask(7 downto 0);
else
if cont_i = '1' then
if flip = '1' then
par_data <= mask(7 downto 0);
else
par_data <= mask(15 downto 8);
end if;
else
if pol_i = '1' then
par_data <= (others => '1');
else
par_data <= (others => '0');
end if;
end if;
end if;
end if;
end process;
U_Serdes : OSERDESE3
generic map (
DATA_WIDTH => 8,
INIT => '0',
IS_CLKDIV_INVERTED => '0',
IS_CLK_INVERTED => '0',
IS_RST_INVERTED => '0',
ODDR_MODE => "FALSE",
OSERDES_D_BYPASS => "FALSE",
OSERDES_T_BYPASS => "FALSE",
SIM_DEVICE => "ULTRASCALE")
port map (
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),
RST => RST,
T => '0'
);
end rtl;
library ieee;
use ieee.std_logic_1164.all;
library unisim;
use unisim.VCOMPONENTS.all;
entity fine_pulse_gen_kintexultrascale_shared is
generic (
g_global_use_odelay : boolean;
g_use_external_serdes_clock : boolean
);
port (
-- PLL async reset
pll_rst_i : in std_logic;
clk_ser_ext_i : in std_logic;
-- 62.5 MHz reference
clk_ref_i : in std_logic;
-- serdes parallel clock
clk_par_o : out std_logic;
-- serdes serial clock
clk_ser_o : out std_logic;
clk_odelay_o : out std_logic;
pll_locked_o : out std_logic
);
end fine_pulse_gen_kintexultrascale_shared;
architecture rtl of fine_pulse_gen_kintexultrascale_shared is
component MMCME3_ADV
generic (
BANDWIDTH : string := "OPTIMIZED";
CLKFBOUT_MULT_F : real := 5.000;
CLKFBOUT_PHASE : real := 0.000;
CLKFBOUT_USE_FINE_PS : string := "FALSE";
CLKIN1_PERIOD : real := 0.000;
CLKIN2_PERIOD : real := 0.000;
CLKOUT0_DIVIDE_F : real := 1.000;
CLKOUT0_DUTY_CYCLE : real := 0.500;
CLKOUT0_PHASE : real := 0.000;
CLKOUT0_USE_FINE_PS : string := "FALSE";
CLKOUT1_DIVIDE : integer := 1;
CLKOUT1_DUTY_CYCLE : real := 0.500;
CLKOUT1_PHASE : real := 0.000;
CLKOUT1_USE_FINE_PS : string := "FALSE";
CLKOUT2_DIVIDE : integer := 1;
CLKOUT2_DUTY_CYCLE : real := 0.500;
CLKOUT2_PHASE : real := 0.000;
CLKOUT2_USE_FINE_PS : string := "FALSE";
CLKOUT3_DIVIDE : integer := 1;
CLKOUT3_DUTY_CYCLE : real := 0.500;
CLKOUT3_PHASE : real := 0.000;
CLKOUT3_USE_FINE_PS : string := "FALSE";
CLKOUT4_CASCADE : string := "FALSE";
CLKOUT4_DIVIDE : integer := 1;
CLKOUT4_DUTY_CYCLE : real := 0.500;
CLKOUT4_PHASE : real := 0.000;
CLKOUT4_USE_FINE_PS : string := "FALSE";
CLKOUT5_DIVIDE : integer := 1;
CLKOUT5_DUTY_CYCLE : real := 0.500;
CLKOUT5_PHASE : real := 0.000;
CLKOUT5_USE_FINE_PS : string := "FALSE";
CLKOUT6_DIVIDE : integer := 1;
CLKOUT6_DUTY_CYCLE : real := 0.500;
CLKOUT6_PHASE : real := 0.000;
CLKOUT6_USE_FINE_PS : string := "FALSE";
COMPENSATION : string := "AUTO";
DIVCLK_DIVIDE : integer := 1;
IS_CLKFBIN_INVERTED : bit := '0';
IS_CLKIN1_INVERTED : bit := '0';
IS_CLKIN2_INVERTED : bit := '0';
IS_CLKINSEL_INVERTED : bit := '0';
IS_PSEN_INVERTED : bit := '0';
IS_PSINCDEC_INVERTED : bit := '0';
IS_PWRDWN_INVERTED : bit := '0';
IS_RST_INVERTED : bit := '0';
REF_JITTER1 : real := 0.010;
REF_JITTER2 : real := 0.010;
SS_EN : string := "FALSE";
SS_MODE : string := "CENTER_HIGH";
SS_MOD_PERIOD : integer := 10000;
STARTUP_WAIT : string := "FALSE"
);
port (
CDDCDONE : out std_ulogic;
CLKFBOUT : out std_ulogic;
CLKFBOUTB : out std_ulogic;
CLKFBSTOPPED : out std_ulogic;
CLKINSTOPPED : out std_ulogic;
CLKOUT0 : out std_ulogic;