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;
CLKOUT0B : out std_ulogic;
CLKOUT1 : out std_ulogic;
CLKOUT1B : out std_ulogic;
CLKOUT2 : out std_ulogic;
CLKOUT2B : out std_ulogic;
CLKOUT3 : out std_ulogic;
CLKOUT3B : out std_ulogic;
CLKOUT4 : out std_ulogic;
CLKOUT5 : out std_ulogic;
CLKOUT6 : out std_ulogic;
DO : out std_logic_vector(15 downto 0);
DRDY : out std_ulogic;
LOCKED : out std_ulogic;
PSDONE : out std_ulogic;
CDDCREQ : in std_ulogic;
CLKFBIN : in std_ulogic;
CLKIN1 : in std_ulogic;
CLKIN2 : in std_ulogic;
CLKINSEL : in std_ulogic;
DADDR : in std_logic_vector(6 downto 0);
DCLK : in std_ulogic;
DEN : in std_ulogic;
DI : in std_logic_vector(15 downto 0);
DWE : in std_ulogic;
PSCLK : in std_ulogic;
PSEN : in std_ulogic;
PSINCDEC : in std_ulogic;
PWRDWN : in std_ulogic;
RST : in std_ulogic
);
end component;
component BUFG is
port (
O : out std_ulogic;
I : in std_ulogic
);
end component BUFG;
signal clk_ser_prebuf, mmcm_clk_fb_prebuf, mmcm_clk_fb : std_logic;
begin
gen_use_Ext_serdes_clock : if not g_use_external_serdes_clock generate
-- stub for the moment
clk_ser_o <= clk_ser_ext_i;
clk_par_o <= clk_ref_i;
pll_locked_o <= '1';
end generate gen_use_Ext_serdes_clock;
gen_use_int_serdes_clock : if g_use_external_serdes_clock generate
U_MMCM : MMCME3_ADV
generic map (
BANDWIDTH => "OPTIMIZED", -- Jitter programming (HIGH, LOW, OPTIMIZED)
COMPENSATION => "AUTO", -- AUTO, BUF_IN, EXTERNAL, INTERNAL, ZHOLD
STARTUP_WAIT => "FALSE", -- Delays DONE until MMCM is locked (FALSE, TRUE)
CLKOUT4_CASCADE => "FALSE",
-- CLKIN_PERIOD: Input clock period in ns units, ps resolution (i.e. 33.333 is 30 MHz).
CLKIN1_PERIOD => 16.0,
CLKFBOUT_MULT_F => 16.0, -- Multiply value for all CLKOUT (2.000-64.000)
DIVCLK_DIVIDE => 1, -- Master division value (1-106)
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_DUTY_CYCLE => 0.5,
CLKOUT0_PHASE => 0.0,
CLKOUT0_USE_FINE_PS => "FALSE"
)
port map (
-- Clock Inputs inputs: Clock inputs
CLKIN1 => clk_ref_i,
CLKIN2 => '0',
-- Clock Outputs outputs: User configurable clock outputs
CLKOUT0 => clk_ser_prebuf,
-- Feedback
CLKFBOUT => mmcm_clk_fb_prebuf,
CLKFBIN => mmcm_clk_fb,
-- Status Ports outputs: MMCM status ports
LOCKED => pll_locked_o,
CDDCREQ => '0',
-- Control Ports inputs: MMCM control ports
CLKINSEL => '1',
PWRDWN => '0',
RST => pll_rst_i,
-- DRP Ports inputs: Dynamic reconfiguration ports
DADDR => (others => '0'),
DCLK => '0',
DEN => '0',
DI => (others => '0'),
DWE => '0',
-- Dynamic Phase Shift Ports inputs: Ports used for dynamic phase shifting of the outputs
PSCLK => '0',
PSEN => '0',
PSINCDEC => '0'
);
u_buf_mmcm_fb : BUFG
port map (
I => mmcm_clk_fb_prebuf,
O => mmcm_clk_fb);
u_buf_mmcm_ser : BUFG
port map (
I => clk_ser_prebuf,
O => clk_ser_o);
clk_par_o <= clk_ref_i;
end generate gen_use_int_serdes_clock;
end rtl;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
`define ADDR_FPG_CSR 6'h0
`define FPG_CSR_TRIG0_OFFSET 0
`define FPG_CSR_TRIG0 32'h00000001
`define FPG_CSR_TRIG1_OFFSET 1
`define FPG_CSR_TRIG1 32'h00000002
`define FPG_CSR_TRIG2_OFFSET 2
`define FPG_CSR_TRIG2 32'h00000004
`define FPG_CSR_TRIG3_OFFSET 3
`define FPG_CSR_TRIG3 32'h00000008
`define FPG_CSR_TRIG4_OFFSET 4
`define FPG_CSR_TRIG4 32'h00000010
`define FPG_CSR_TRIG5_OFFSET 5
`define FPG_CSR_TRIG5 32'h00000020
`define FPG_CSR_TRIG6_OFFSET 6
`define FPG_CSR_TRIG6 32'h00000040
`define FPG_CSR_TRIG7_OFFSET 7
`define FPG_CSR_TRIG7 32'h00000080
`define FPG_CSR_FORCE0_OFFSET 8
`define FPG_CSR_FORCE0 32'h00000100
`define FPG_CSR_FORCE1_OFFSET 9
`define FPG_CSR_FORCE1 32'h00000200
`define FPG_CSR_FORCE2_OFFSET 10
`define FPG_CSR_FORCE2 32'h00000400
`define FPG_CSR_FORCE3_OFFSET 11
`define FPG_CSR_FORCE3 32'h00000800
`define FPG_CSR_FORCE4_OFFSET 12
`define FPG_CSR_FORCE4 32'h00001000
`define FPG_CSR_FORCE5_OFFSET 13
`define FPG_CSR_FORCE5 32'h00002000
`define FPG_CSR_READY_OFFSET 14
`define FPG_CSR_READY 32'h000fc000
`define FPG_CSR_PLL_RST_OFFSET 20
`define FPG_CSR_PLL_RST 32'h00100000
`define ADDR_FPG_OCR0 6'h4
`define FPG_OCR0_PPS_OFFS_OFFSET 0
`define FPG_OCR0_PPS_OFFS 32'h0000000f
`define FPG_OCR0_FINE_OFFSET 4
`define FPG_OCR0_FINE 32'h000001f0
`define FPG_OCR0_POL_OFFSET 9
`define FPG_OCR0_POL 32'h00000200
`define FPG_OCR0_MASK_OFFSET 10
`define FPG_OCR0_MASK 32'h0003fc00
`define FPG_OCR0_CONT_OFFSET 18
`define FPG_OCR0_CONT 32'h00040000
`define FPG_OCR0_TRIG_SEL_OFFSET 19
`define FPG_OCR0_TRIG_SEL 32'h00080000
`define ADDR_FPG_OCR1 6'h8
`define FPG_OCR1_PPS_OFFS_OFFSET 0
`define FPG_OCR1_PPS_OFFS 32'h0000000f
`define FPG_OCR1_FINE_OFFSET 4
`define FPG_OCR1_FINE 32'h000001f0
`define FPG_OCR1_POL_OFFSET 9
`define FPG_OCR1_POL 32'h00000200
`define FPG_OCR1_MASK_OFFSET 10
`define FPG_OCR1_MASK 32'h0003fc00
`define FPG_OCR1_CONT_OFFSET 18
`define FPG_OCR1_CONT 32'h00040000
`define FPG_OCR1_TRIG_SEL_OFFSET 19
`define FPG_OCR1_TRIG_SEL 32'h00080000
`define ADDR_FPG_OCR2 6'hc
`define FPG_OCR2_PPS_OFFS_OFFSET 0
`define FPG_OCR2_PPS_OFFS 32'h0000000f
`define FPG_OCR2_FINE_OFFSET 4
`define FPG_OCR2_FINE 32'h000001f0
`define FPG_OCR2_POL_OFFSET 9
`define FPG_OCR2_POL 32'h00000200
`define FPG_OCR2_MASK_OFFSET 10
`define FPG_OCR2_MASK 32'h0003fc00
`define FPG_OCR2_CONT_OFFSET 18
`define FPG_OCR2_CONT 32'h00040000
`define FPG_OCR2_TRIG_SEL_OFFSET 19
`define FPG_OCR2_TRIG_SEL 32'h00080000
`define ADDR_FPG_OCR3 6'h10
`define FPG_OCR3_PPS_OFFS_OFFSET 0
`define FPG_OCR3_PPS_OFFS 32'h0000000f
`define FPG_OCR3_FINE_OFFSET 4
`define FPG_OCR3_FINE 32'h000001f0
`define FPG_OCR3_POL_OFFSET 9
`define FPG_OCR3_POL 32'h00000200
`define FPG_OCR3_MASK_OFFSET 10
`define FPG_OCR3_MASK 32'h0003fc00
`define FPG_OCR3_CONT_OFFSET 18
`define FPG_OCR3_CONT 32'h00040000
`define FPG_OCR3_TRIG_SEL_OFFSET 19
`define FPG_OCR3_TRIG_SEL 32'h00080000
`define ADDR_FPG_OCR4 6'h14
`define FPG_OCR4_PPS_OFFS_OFFSET 0
`define FPG_OCR4_PPS_OFFS 32'h0000000f
`define FPG_OCR4_FINE_OFFSET 4
`define FPG_OCR4_FINE 32'h000001f0
`define FPG_OCR4_POL_OFFSET 9
`define FPG_OCR4_POL 32'h00000200
`define FPG_OCR4_MASK_OFFSET 10
`define FPG_OCR4_MASK 32'h0003fc00
`define FPG_OCR4_CONT_OFFSET 18
`define FPG_OCR4_CONT 32'h00040000
`define FPG_OCR4_TRIG_SEL_OFFSET 19
`define FPG_OCR4_TRIG_SEL 32'h00080000
`define ADDR_FPG_OCR5 6'h18
`define FPG_OCR5_PPS_OFFS_OFFSET 0
`define FPG_OCR5_PPS_OFFS 32'h0000000f
`define FPG_OCR5_FINE_OFFSET 4
`define FPG_OCR5_FINE 32'h000001f0
`define FPG_OCR5_POL_OFFSET 9
`define FPG_OCR5_POL 32'h00000200
`define FPG_OCR5_MASK_OFFSET 10
`define FPG_OCR5_MASK 32'h0003fc00
`define FPG_OCR5_CONT_OFFSET 18
`define FPG_OCR5_CONT 32'h00040000
`define FPG_OCR5_TRIG_SEL_OFFSET 19
`define FPG_OCR5_TRIG_SEL 32'h00080000
`define ADDR_FPG_OCR6 6'h1c
`define FPG_OCR6_PPS_OFFS_OFFSET 0
`define FPG_OCR6_PPS_OFFS 32'h0000000f
`define FPG_OCR6_FINE_OFFSET 4
`define FPG_OCR6_FINE 32'h000001f0
`define FPG_OCR6_POL_OFFSET 9
`define FPG_OCR6_POL 32'h00000200
`define FPG_OCR6_MASK_OFFSET 10
`define FPG_OCR6_MASK 32'h0003fc00
`define FPG_OCR6_CONT_OFFSET 18
`define FPG_OCR6_CONT 32'h00040000
`define FPG_OCR6_TRIG_SEL_OFFSET 19
`define FPG_OCR6_TRIG_SEL 32'h00080000
`define ADDR_FPG_OCR7 6'h20
`define FPG_OCR7_PPS_OFFS_OFFSET 0
`define FPG_OCR7_PPS_OFFS 32'h0000000f
`define FPG_OCR7_FINE_OFFSET 4
`define FPG_OCR7_FINE 32'h000001f0
`define FPG_OCR7_POL_OFFSET 9
`define FPG_OCR7_POL 32'h00000200
`define FPG_OCR7_MASK_OFFSET 10
`define FPG_OCR7_MASK 32'h0003fc00
`define FPG_OCR7_CONT_OFFSET 18
`define FPG_OCR7_CONT 32'h00040000
`define FPG_OCR7_TRIG_SEL_OFFSET 19
`define FPG_OCR7_TRIG_SEL 32'h00080000
`define ADDR_FPG_ODELAY_CALIB 6'h24
`define FPG_ODELAY_CALIB_RST_IDELAYCTRL_OFFSET 0
`define FPG_ODELAY_CALIB_RST_IDELAYCTRL 32'h00000001
`define FPG_ODELAY_CALIB_RST_ODELAY_OFFSET 1
`define FPG_ODELAY_CALIB_RST_ODELAY 32'h00000002
`define FPG_ODELAY_CALIB_RST_OSERDES_OFFSET 2
`define FPG_ODELAY_CALIB_RST_OSERDES 32'h00000004
`define FPG_ODELAY_CALIB_RDY_OFFSET 3
`define FPG_ODELAY_CALIB_RDY 32'h00000008
`define FPG_ODELAY_CALIB_VALUE_OFFSET 4
`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
sim_tool = "modelsim"
top_module="main"
action = "simulation"
target = "xilinx"
fetchto = "../../ip_cores"
vcom_opt="-mixedsvvh l -2008"
sim_top="main"
syn_device="xc7k70t"
include_dirs=["../../../sim", "../include" ]
files = [ "main.sv" ]
modules = { "local" : [ "../../../" ] }
//------------------------------------------------------------------------------
// Copyright CERN 2018
//------------------------------------------------------------------------------
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-2.0.
// Unless required by applicable law or agreed to in writing, software,
// hardware and materials distributed under this License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions
// and limitations under the License.
//------------------------------------------------------------------------------
`timescale 1ps/1ps
`include "vhd_wishbone_master.svh"
`include "wb_fine_pulse_gen_regs.vh"
module dupa;
xwb_fine_pulse_gen dut();
endmodule // dupa
class DDSSyncUnitDriver;
protected CBusAccessor m_acc;
protected int m_base;
function new(CBusAccessor acc, int base);
m_acc =acc;
m_base =base;
endfunction // new
task automatic pulse( int out, int polarity, int cont, real delta, int tr_force = 0 );
const real refclk_period = 5.0;
const real n_fine_taps = 31;
const real tap_size = 0.078; /* ns */
// refclk_period/n_fine_taps;
uint64_t rv;
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 mask = coarse_ser;
//(1 << (7-coarse_ser+1)) - 1;
uint32_t ocr;
// coarse_par = 0;
// coarse_ser = 0;
// $display("tapSize %f \n", tap_size);
// $display("pgm %d %d %d", coarse_par, coarse_ser, fine);
ocr = (coarse_par << `FPG_OCR0_PPS_OFFS_OFFSET)
| (mask << `FPG_OCR0_MASK_OFFSET)
| (fine << `FPG_OCR0_FINE_OFFSET)
| (cont ? `FPG_OCR0_CONT : 0)
| (polarity ? `FPG_OCR0_POL : 0 );
m_acc.write( m_base + `ADDR_FPG_OCR0 + 4 * out, ocr );
if(tr_force)
m_acc.write( m_base + `ADDR_FPG_CSR, 1<< (6 + out) );
else
m_acc.write( m_base + `ADDR_FPG_CSR, 1<< (out) );
// $display("triggered");
forever begin
m_acc.read(m_base + `ADDR_FPG_CSR, rv);
if( rv & ( 1 << (`FPG_CSR_READY_OFFSET + out ) ) )
break;
end
endtask
endclass // DDSSyncUnitDriver
module main;
reg rst_n = 0;
reg clk_125m = 0;
reg clk_250m = 0;
reg clk_62m5 = 0;
reg clk_dmtd = 0;
always #2ns clk_250m <= ~clk_250m;
always @(posedge clk_250m) clk_125m <= ~clk_125m;
always #(7.9ns) clk_dmtd <= ~clk_dmtd;
always @(posedge clk_125m) clk_62m5 <= ~clk_62m5;
initial begin
repeat(20) @(posedge clk_125m);
rst_n = 1;
end
wire loop_p, loop_n;
reg pps_p = 0;
initial forever begin
repeat(100) @(posedge clk_62m5);
pps_p <= 1;
@(posedge clk_62m5);
pps_p <= 0;
end
time t_pps, t_pulse;
real dlys[$];
time first_delay = 0;
time delta_prev = 0,delta;
int t_pps_valid = 0;
always@(posedge pps_p)
begin
t_pps = $time;
t_pps_valid = 1;
end
always@(posedge DUT.pulse_o[0])
begin
t_pulse = $time;
if( dlys.size() && t_pps_valid )
begin
automatic real t_req = dlys.pop_front();
automatic time dly = t_pulse - t_pps;
t_pps_valid = 0;
if(!first_delay)
first_delay = dly;
$display("t_pps %t t_pulse %t delta %d", t_pps, t_pulse, (t_pulse - t_pps) / 1ns );
/* delta = dly-first_delay;
$display("delta: %-20d ps, ddelta : %-20d ps", delta, delta-delta_prev );
delta_prev = delta;*/
end
end
// the Device Under Test
xwb_fine_pulse_gen
#(
.g_target_platform("KintexUltrascale"),
.g_use_external_serdes_clock(1),
.g_num_channels(1)
)
DUT
(
.rst_sys_n_i(rst_n),
.clk_ser_ext_i(clk_250m),
.clk_sys_i (clk_62m5),
.clk_ref_i (clk_62m5),
.pps_p_i(pps_p),
.slave_i (Host.out),
.slave_o (Host.in)
);
IVHDWishboneMaster Host
(
.clk_i (clk_62m5),
.rst_n_i (rst_n));
initial begin
real t;
CBusAccessor acc = Host.get_accessor();
DDSSyncUnitDriver drv = new( acc, 0 );
@(posedge rst_n);
@(posedge clk_62m5);
@(posedge pps_p);
#1us;
/* -----\/----- EXCLUDED -----\/-----
drv.pulse(1, 0, 1, 100);
drv.pulse(4, 0, 0, 100, 1);
-----/\----- EXCLUDED -----/\----- */
for (t = 1.0; t <= 200.9; t+=1.0)
begin
// $display("Pulse @ %f", t );
dlys.push_back(t);
drv.pulse(0, 0, 0, t);
end
#1us;
end // initial begin
endmodule // main
#vlog -sv main.sv +incdir+. +incdir+../../include/wb +incdir+../include/vme64x_bfm +incdir+../../include +incdir+../include +incdir+../../sim
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
vsim -L unisim -L XilinxCoreLib work.main -voptargs=+acc -t 10fs
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
do wave.do
radix -hexadecimal
run 1350us
\ No newline at end of file
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