Commit 2ae8ad3d authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

wb_fine_pulse_gen: work in progress on switching between pulse/continuous clock mode

parent d79a36fb
......@@ -4,19 +4,23 @@ use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
use work.genram_pkg.all;
library unisim;
use unisim.VCOMPONENTS.all;
entity fine_pulse_gen_kintex7 is
generic (
g_ID : integer;
g_sim_delay_tap_ps : integer := 30;
g_ref_clk_freq : real := 125.0;
g_use_odelay : boolean := false
g_use_odelay : boolean := false;
g_ENABLE_PATTERN_MODE : boolean := false
);
port
(
clk_par_i : in std_logic;
clk_sys_i : in std_logic;
clk_serdes_i : in std_logic;
rst_serdes_i : in std_logic;
......@@ -31,6 +35,13 @@ entity fine_pulse_gen_kintex7 is
pulse_o : out std_logic;
ready_o : out std_logic;
pat_addr_i : in std_logic_vector(6 downto 0);
pat_data_i : in std_logic_vector(15 downto 0);
pat_wr_i : in std_logic;
pat_out_sel_i : in std_logic_vector(2 downto 0);
pat_mode_en_i : in std_logic;
dly_load_i : in std_logic;
dly_fine_i : in std_logic_vector(4 downto 0)
);
......@@ -46,14 +57,8 @@ architecture rtl of fine_pulse_gen_kintex7 is
signal odelay_load : 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_start : std_logic_vector(15 downto 0);
signal mask_end : std_logic_vector(15 downto 0);
......@@ -69,12 +74,42 @@ architecture rtl of fine_pulse_gen_kintex7 is
attribute mark_debug of dly_fine_i : signal is "TRUE";
attribute mark_debug of odelay_ntaps : signal is "TRUE";
type t_state is (IDLE, CONT_H, CONT_L, START_PULSE_H, START_PULSE_L, MID_PULSE_H, MID_PULSE_L, END_PULSE_H, END_PULSE_L);
type t_state is (IDLE, CONT_H, CONT_L, START_PULSE_H, START_PULSE_L, MID_PULSE_H, MID_PULSE_L, END_PULSE_H, END_PULSE_L, PLAY_PATTERN);
signal state : t_state;
signal pat_cnt, pat_len : unsigned(6 downto 0);
signal pat_rd_data : std_logic_vector(7 downto 0);
signal pat_wr : std_logic;
begin
gen_with_pattern_mode : if g_ENABLE_PATTERN_MODE generate
pat_wr <= pat_wr_i when (g_ID = unsigned(pat_out_sel_i)) else '0';
-- length_i is in 16s of clock cycles in the "standard" mode
pat_len <= unsigned(length_i(10 downto 4));
inst_pattern_ram : generic_dpram
generic map (
g_data_width => 8,
g_size => 128,
g_with_byte_enable => false)
port map (
rst_n_i => rst_par_n_i,
clka_i => clk_sys_i,
wea_i => pat_wr,
aa_i => pat_addr_i,
da_i => pat_data_i(7 downto 0),
clkb_i => clk_par_i,
web_i => '0',
ab_i => std_logic_vector(pat_cnt),
qb_o => pat_rd_data);
end generate gen_with_pattern_mode;
process(clk_par_i, rst_par_n_i)
variable rv, rv2 : std_logic_vector(15 downto 0);
begin
......@@ -224,7 +259,10 @@ begin
ready_o <= '1';
if trig_p_i = '1' then
if cont_i = '1' then
if pat_mode_en_i = '1' and g_ENABLE_PATTERN_MODE then
state <= PLAY_PATTERN;
pat_cnt <= pat_cnt + 1;
elsif cont_i = '1' then
state <= CONT_H;
ready_o <= '1';
elsif length_d = 0 then
......@@ -234,8 +272,24 @@ begin
state <= START_PULSE_H;
ready_o <= '0';
end if;
else
pat_cnt <= (others => '0');
end if;
when PLAY_PATTERN =>
if g_ENABLE_PATTERN_MODE then
if pat_cnt = unsigned(pat_len) then
ready_o <= '1';
pat_cnt <= (others => '0');
if cont_i = '0' then
state <= IDLE;
end if;
else
pat_cnt <= pat_cnt + 1;
end if;
par_data <= pat_rd_data(7 downto 0);
end if;
when CONT_H =>
if cont_i = '0' then
state <= IDLE;
......
......@@ -12,7 +12,8 @@ entity fine_pulse_gen_kintexultrascale is
generic (
g_sim_delay_tap_ps : integer := 30;
g_idelayctrl_ref_clk_freq : real := 250.0;
g_use_odelay : boolean := false
g_use_odelay : boolean := false;
g_ENABLE_PATTERN_MODE : boolean := false
);
port
(
......@@ -146,10 +147,10 @@ architecture rtl of fine_pulse_gen_kintexultrascale is
begin
assert not g_ENABLE_PATTERN_MODE report "g_ENABLE_PATTERN_MODE is not supported on Ultrascale platform yet." severity failure;
rst <= not rst_sys_n_i;
process(clk_ref_i)
variable rv : std_logic_vector(31 downto 0);
begin
......
......@@ -155,6 +155,10 @@ memory-map:
description: Trigger select
comment: '1: external trigger; 0: PPS'
range: 19
- field:
name: PAT_EN
description: Pattern mode enable
range: 20
- reg:
name: OCR0B
description: Output 0 Control Register B
......@@ -170,10 +174,6 @@ memory-map:
name: LENGTH
description: Pulse Length (target platform specific, 0 = minimum possible pulse width)
range: 31-16
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_ONLY
type: SLV
- reg:
name: OCR1A
description: Output 0 Control Register A
......@@ -202,6 +202,10 @@ memory-map:
description: Trigger select
comment: '1: external trigger; 0: PPS'
range: 19
- field:
name: PAT_EN
description: Pattern mode enable
range: 20
- reg:
name: OCR1B
description: Output 1 Control Register B
......@@ -217,10 +221,6 @@ memory-map:
name: LENGTH
description: Pulse Length (target platform specific, 0 = minimum possible pulse width)
range: 31-16
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_ONLY
type: SLV
- reg:
name: OCR2A
description: Output 2 Control Register A
......@@ -249,6 +249,10 @@ memory-map:
description: Trigger select
comment: '1: external trigger; 0: PPS'
range: 19
- field:
name: PAT_EN
description: Pattern mode enable
range: 20
- reg:
name: OCR2B
description: Output 2 Control Register B
......@@ -264,10 +268,6 @@ memory-map:
name: LENGTH
description: Pulse Length (target platform specific, 0 = minimum possible pulse width)
range: 31-16
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_ONLY
type: SLV
- reg:
name: OCR3A
description: Output 3 Control Register A
......@@ -296,6 +296,10 @@ memory-map:
description: Trigger select
comment: '1: external trigger; 0: PPS'
range: 19
- field:
name: PAT_EN
description: Pattern mode enable
range: 20
- reg:
name: OCR3B
description: Output 3 Control Register B
......@@ -311,10 +315,6 @@ memory-map:
name: LENGTH
description: Pulse Length (target platform specific, 0 = minimum possible pulse width)
range: 31-16
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_ONLY
type: SLV
- reg:
name: OCR4A
description: Output 4 Control Register A
......@@ -343,6 +343,10 @@ memory-map:
description: Trigger select
comment: '1: external trigger; 0: PPS'
range: 19
- field:
name: PAT_EN
description: Pattern mode enable
range: 20
- reg:
name: OCR4B
description: Output 4 Control Register B
......@@ -358,10 +362,6 @@ memory-map:
name: LENGTH
description: Pulse Length (target platform specific, 0 = minimum possible pulse width)
range: 31-16
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_ONLY
type: SLV
- reg:
name: OCR5A
description: Output 5 Control Register A
......@@ -390,6 +390,10 @@ memory-map:
description: Trigger select
comment: '1: external trigger; 0: PPS'
range: 19
- field:
name: PAT_EN
description: Pattern mode enable
range: 20
- reg:
name: OCR5B
description: Output 5 Control Register B
......@@ -405,10 +409,6 @@ memory-map:
name: LENGTH
description: Pulse Length (target platform specific, 0 = minimum possible pulse width)
range: 31-16
x-wbgen:
access_bus: READ_WRITE
access_dev: READ_ONLY
type: SLV
- reg:
name: odelay_calib
......@@ -466,3 +466,25 @@ memory-map:
range: 24-16
x-hdl:
type: wire
- reg:
name: PGEN_CR
description: Pattern generator control register
width: 32
access: rw
address: next
x-hdl:
type: wire
write-strobe: True
children:
- field:
name: ADDR
description: Pattern memory address
range: 6-0
- field:
name: OUT_SEL
description: Output select for pattern memory access
range: 9-7
- field:
name: DATA
description: Pattern data (device-specific)
range: 31-16
\ No newline at end of file
......@@ -12,10 +12,16 @@ use work.wb_fpgen_regs_pkg.all;
entity xwb_fine_pulse_gen is
generic (
g_num_channels: integer := 6;
g_use_external_serdes_clock : boolean := false;
g_target_platform : string := "Kintex7";
g_use_odelay : bit_vector(5 downto 0) := "110000"
-- number of output channels. From 1 to 6.
g_NUM_CHANNELS : integer := 6;
-- when true, the fast serdes clock is provided from an external source
-- through clk_ser_ext_i, otherwise an internal PLL is instantiated.
g_USE_EXTERNAL_SERDES_CLOCK : boolean := false;
-- target FPGA. Kintex7 and KintexUltrascale are so far supported
g_TARGET_PLATFORM : string := "Kintex7";
-- enables ODELAY primitives for fine delay adjustment on selected outputs.
g_USE_ODELAY : bit_vector(5 downto 0) := "110000";
g_ENABLE_PATTERN_MODE : bit_vector(5 downto 0) := "110000"
);
port (
clk_sys_i : in std_logic;
......@@ -23,13 +29,13 @@ entity xwb_fine_pulse_gen is
rst_sys_n_i : in std_logic;
clk_ser_ext_i : in std_logic := '0'; -- external SERDES clock, used when
-- g_use_external_serdes_clock == true
-- 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
pulse_o : out std_logic_vector(g_num_channels-1 downto 0);
pulse_o : out std_logic_vector(g_NUM_CHANNELS -1 downto 0);
clk_par_o : out std_logic;
......@@ -43,7 +49,7 @@ architecture rtl of xwb_fine_pulse_gen is
impure function f_global_use_odelay return boolean is
begin
if g_use_odelay /= "000000" then
if g_USE_ODELAY /= "000000" then
return true;
else
return false;
......@@ -76,6 +82,7 @@ architecture rtl of xwb_fine_pulse_gen is
trig_ready : std_logic;
odelay_load : std_logic;
odelay_value_out : std_logic_vector(8 downto 0);
pat_mode_en : std_logic;
end record;
type t_channel_array is array(integer range <>) of t_channel;
......@@ -261,7 +268,7 @@ begin
gen_ready_flags : for i in 0 to g_num_channels-1 generate
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,
......@@ -329,6 +336,13 @@ begin
ch(3).trig_sel <= regs_out.ocr3a_trig_sel;
ch(4).trig_sel <= regs_out.ocr4a_trig_sel;
ch(5).trig_sel <= regs_out.ocr5a_trig_sel;
ch(0).pat_mode_en <= regs_out.ocr0a_pat_en;
ch(1).pat_mode_en <= regs_out.ocr1a_pat_en;
ch(2).pat_mode_en <= regs_out.ocr2a_pat_en;
ch(3).pat_mode_en <= regs_out.ocr3a_pat_en;
ch(4).pat_mode_en <= regs_out.ocr4a_pat_en;
ch(5).pat_mode_en <= regs_out.ocr5a_pat_en;
ch(0).pps_offs <= unsigned(regs_out.ocr0b_pps_offs);
ch(1).pps_offs <= unsigned(regs_out.ocr1b_pps_offs);
......@@ -337,7 +351,7 @@ begin
ch(4).pps_offs <= unsigned(regs_out.ocr4b_pps_offs);
ch(5).pps_offs <= unsigned(regs_out.ocr5b_pps_offs);
gen_channels : for i in 0 to g_NUM_CHANNELS-1 generate
gen_channels : for i in 0 to g_NUM_CHANNELS -1 generate
ch(i).ready <= ch(i).trig_ready and ch(i).phy_ready;
......@@ -411,15 +425,18 @@ begin
gen_is_kintex7_pg: if g_target_platform = "Kintex7" generate
gen_is_kintex7_pg: if g_TARGET_PLATFORM = "Kintex7" generate
U_Pulse_Gen : entity work.fine_pulse_gen_kintex7
generic map (
g_ID => i,
g_sim_delay_tap_ps => 50,
g_ref_clk_freq => 200.0,
g_use_odelay => f_to_bool(g_use_odelay(i)) )
g_USE_ODELAY => f_to_bool(g_USE_ODELAY(i)),
g_ENABLE_PATTERN_MODE => f_to_bool(g_ENABLE_PATTERN_MODE(i)))
port map (
clk_par_i => clk_par,
clk_sys_i => clk_sys_i,
clk_serdes_i => clk_ser,
rst_serdes_i => rst_serdes,
rst_par_n_i => rst_n_wr,
......@@ -431,17 +448,26 @@ begin
pulse_o => pulse_o(i),
ready_o => ch(I).phy_ready,
dly_load_i => ch(i).delay_load,
dly_fine_i => ch(i).delay_fine(4 downto 0));
dly_fine_i => ch(i).delay_fine(4 downto 0),
pat_addr_i => regs_out.PGEN_CR_ADDR,
pat_data_i => regs_out.PGEN_CR_DATA,
pat_out_sel_i => regs_out.PGEN_CR_OUT_SEL,
pat_wr_i => regs_out.PGEN_CR_wr,
pat_mode_en_i => ch(i).pat_mode_en
);
end generate gen_is_kintex7_pg;
gen_is_kintex_us_pg: if g_target_platform = "KintexUltrascale" generate
gen_is_kintex_us_pg: if g_TARGET_PLATFORM = "KintexUltrascale" generate
U_Pulse_Gen : entity work.fine_pulse_gen_kintexultrascale
generic map (
g_sim_delay_tap_ps => 50,
g_idelayctrl_ref_clk_freq => 250.0,
g_use_odelay => f_to_bool(g_use_odelay(i)) )
g_USE_ODELAY => f_to_bool(g_USE_ODELAY(i)),
g_ENABLE_PATTERN_MODE => f_to_bool(g_ENABLE_PATTERN_MODE(i))
)
port map (
clk_sys_i => clk_sys_i,
clk_par_i => clk_par,
......@@ -476,12 +502,12 @@ begin
regs_in.odelay_calib_taps <= ch(0).odelay_value_out;
gen_is_kintex7: if g_target_platform = "Kintex7" generate
gen_is_kintex7: if g_TARGET_PLATFORM = "Kintex7" generate
U_K7_Shared: entity work.fine_pulse_gen_kintex7_shared
generic map (
g_global_use_odelay => f_global_use_odelay,
g_use_external_serdes_clock => g_use_external_serdes_clock)
g_USE_EXTERNAL_SERDES_CLOCK => g_USE_EXTERNAL_SERDES_CLOCK)
port map (
pll_rst_i => regs_out.csr_pll_rst,
clk_ref_i => clk_ref_i,
......@@ -504,12 +530,12 @@ begin
end generate gen_is_kintex7;
gen_is_kintex_ultrascale: if g_target_platform = "KintexUltrascale" generate
gen_is_kintex_ultrascale: if g_TARGET_PLATFORM = "KintexUltrascale" generate
U_K7U_Shared: entity work.fine_pulse_gen_kintexultrascale_shared
generic map (
g_global_use_odelay => f_global_use_odelay,
g_use_external_serdes_clock => g_use_external_serdes_clock
g_USE_EXTERNAL_SERDES_CLOCK => g_USE_EXTERNAL_SERDES_CLOCK
)
port map (
pll_rst_i => regs_out.csr_pll_rst,
......
package wb_fpgen_regs_Consts;
localparam WB_FPGEN_SIZE = 56;
localparam WB_FPGEN_SIZE = 60;
localparam WB_FPGEN_MEMMAP_VERSION = 'h1;
localparam ADDR_WB_FPGEN_CSR = 'h0;
localparam WB_FPGEN_CSR_TRIG0_OFFSET = 0;
localparam WB_FPGEN_CSR_TRIG0 = 32'h1;
......@@ -50,6 +49,8 @@ package wb_fpgen_regs_Consts;
localparam WB_FPGEN_OCR0A_CONT = 32'h40000;
localparam WB_FPGEN_OCR0A_TRIG_SEL_OFFSET = 19;
localparam WB_FPGEN_OCR0A_TRIG_SEL = 32'h80000;
localparam WB_FPGEN_OCR0A_PAT_EN_OFFSET = 20;
localparam WB_FPGEN_OCR0A_PAT_EN = 32'h100000;
localparam ADDR_WB_FPGEN_OCR0B = 'h8;
localparam WB_FPGEN_OCR0B_PPS_OFFS_OFFSET = 0;
localparam WB_FPGEN_OCR0B_PPS_OFFS = 32'hffff;
......@@ -66,6 +67,8 @@ package wb_fpgen_regs_Consts;
localparam WB_FPGEN_OCR1A_CONT = 32'h40000;
localparam WB_FPGEN_OCR1A_TRIG_SEL_OFFSET = 19;
localparam WB_FPGEN_OCR1A_TRIG_SEL = 32'h80000;
localparam WB_FPGEN_OCR1A_PAT_EN_OFFSET = 20;
localparam WB_FPGEN_OCR1A_PAT_EN = 32'h100000;
localparam ADDR_WB_FPGEN_OCR1B = 'h10;
localparam WB_FPGEN_OCR1B_PPS_OFFS_OFFSET = 0;
localparam WB_FPGEN_OCR1B_PPS_OFFS = 32'hffff;
......@@ -82,6 +85,8 @@ package wb_fpgen_regs_Consts;
localparam WB_FPGEN_OCR2A_CONT = 32'h40000;
localparam WB_FPGEN_OCR2A_TRIG_SEL_OFFSET = 19;
localparam WB_FPGEN_OCR2A_TRIG_SEL = 32'h80000;
localparam WB_FPGEN_OCR2A_PAT_EN_OFFSET = 20;
localparam WB_FPGEN_OCR2A_PAT_EN = 32'h100000;
localparam ADDR_WB_FPGEN_OCR2B = 'h18;
localparam WB_FPGEN_OCR2B_PPS_OFFS_OFFSET = 0;
localparam WB_FPGEN_OCR2B_PPS_OFFS = 32'hffff;
......@@ -98,6 +103,8 @@ package wb_fpgen_regs_Consts;
localparam WB_FPGEN_OCR3A_CONT = 32'h40000;
localparam WB_FPGEN_OCR3A_TRIG_SEL_OFFSET = 19;
localparam WB_FPGEN_OCR3A_TRIG_SEL = 32'h80000;
localparam WB_FPGEN_OCR3A_PAT_EN_OFFSET = 20;
localparam WB_FPGEN_OCR3A_PAT_EN = 32'h100000;
localparam ADDR_WB_FPGEN_OCR3B = 'h20;
localparam WB_FPGEN_OCR3B_PPS_OFFS_OFFSET = 0;
localparam WB_FPGEN_OCR3B_PPS_OFFS = 32'hffff;
......@@ -114,6 +121,8 @@ package wb_fpgen_regs_Consts;
localparam WB_FPGEN_OCR4A_CONT = 32'h40000;
localparam WB_FPGEN_OCR4A_TRIG_SEL_OFFSET = 19;
localparam WB_FPGEN_OCR4A_TRIG_SEL = 32'h80000;
localparam WB_FPGEN_OCR4A_PAT_EN_OFFSET = 20;
localparam WB_FPGEN_OCR4A_PAT_EN = 32'h100000;
localparam ADDR_WB_FPGEN_OCR4B = 'h28;
localparam WB_FPGEN_OCR4B_PPS_OFFS_OFFSET = 0;
localparam WB_FPGEN_OCR4B_PPS_OFFS = 32'hffff;
......@@ -130,6 +139,8 @@ package wb_fpgen_regs_Consts;
localparam WB_FPGEN_OCR5A_CONT = 32'h40000;
localparam WB_FPGEN_OCR5A_TRIG_SEL_OFFSET = 19;
localparam WB_FPGEN_OCR5A_TRIG_SEL = 32'h80000;
localparam WB_FPGEN_OCR5A_PAT_EN_OFFSET = 20;
localparam WB_FPGEN_OCR5A_PAT_EN = 32'h100000;
localparam ADDR_WB_FPGEN_OCR5B = 'h30;
localparam WB_FPGEN_OCR5B_PPS_OFFS_OFFSET = 0;
localparam WB_FPGEN_OCR5B_PPS_OFFS = 32'hffff;
......@@ -154,4 +165,11 @@ package wb_fpgen_regs_Consts;
localparam WB_FPGEN_ODELAY_CALIB_CAL_LATCH = 32'h8000;
localparam WB_FPGEN_ODELAY_CALIB_TAPS_OFFSET = 16;
localparam WB_FPGEN_ODELAY_CALIB_TAPS = 32'h1ff0000;
localparam ADDR_WB_FPGEN_PGEN_CR = 'h38;
localparam WB_FPGEN_PGEN_CR_ADDR_OFFSET = 0;
localparam WB_FPGEN_PGEN_CR_ADDR = 32'h7f;
localparam WB_FPGEN_PGEN_CR_OUT_SEL_OFFSET = 7;
localparam WB_FPGEN_PGEN_CR_OUT_SEL = 32'h380;
localparam WB_FPGEN_PGEN_CR_DATA_OFFSET = 16;
localparam WB_FPGEN_PGEN_CR_DATA = 32'hffff0000;
endpackage
`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 FPG_CSR_SERDES_RST_OFFSET 21
`define FPG_CSR_SERDES_RST 32'h00200000
`define FPG_CSR_PLL_LOCKED_OFFSET 22
`define FPG_CSR_PLL_LOCKED 32'h00400000
`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_COARSE_OFFSET 10
`define FPG_OCR0_COARSE 32'h00003c00
`define FPG_OCR0_CONT_OFFSET 14
`define FPG_OCR0_CONT 32'h00004000
`define FPG_OCR0_TRIG_SEL_OFFSET 15
`define FPG_OCR0_TRIG_SEL 32'h00008000
`define FPG_OCR0_LENGTH_OFFSET 16
`define FPG_OCR0_LENGTH 32'hffff0000
`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_COARSE_OFFSET 10
`define FPG_OCR1_COARSE 32'h00003c00
`define FPG_OCR1_CONT_OFFSET 14
`define FPG_OCR1_CONT 32'h00004000
`define FPG_OCR1_TRIG_SEL_OFFSET 15
`define FPG_OCR1_TRIG_SEL 32'h00008000
`define FPG_OCR1_LENGTH_OFFSET 16
`define FPG_OCR1_LENGTH 32'hffff0000
`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_COARSE_OFFSET 10
`define FPG_OCR2_COARSE 32'h00003c00
`define FPG_OCR2_CONT_OFFSET 14
`define FPG_OCR2_CONT 32'h00004000
`define FPG_OCR2_TRIG_SEL_OFFSET 15
`define FPG_OCR2_TRIG_SEL 32'h00008000
`define FPG_OCR2_LENGTH_OFFSET 16
`define FPG_OCR2_LENGTH 32'hffff0000
`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_COARSE_OFFSET 10
`define FPG_OCR3_COARSE 32'h00003c00
`define FPG_OCR3_CONT_OFFSET 14
`define FPG_OCR3_CONT 32'h00004000
`define FPG_OCR3_TRIG_SEL_OFFSET 15
`define FPG_OCR3_TRIG_SEL 32'h00008000
`define FPG_OCR3_LENGTH_OFFSET 16
`define FPG_OCR3_LENGTH 32'hffff0000
`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_COARSE_OFFSET 10
`define FPG_OCR4_COARSE 32'h00003c00
`define FPG_OCR4_CONT_OFFSET 14
`define FPG_OCR4_CONT 32'h00004000
`define FPG_OCR4_TRIG_SEL_OFFSET 15
`define FPG_OCR4_TRIG_SEL 32'h00008000
`define FPG_OCR4_LENGTH_OFFSET 16
`define FPG_OCR4_LENGTH 32'hffff0000
`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_COARSE_OFFSET 10
`define FPG_OCR5_COARSE 32'h00003c00
`define FPG_OCR5_CONT_OFFSET 14
`define FPG_OCR5_CONT 32'h00004000
`define FPG_OCR5_TRIG_SEL_OFFSET 15
`define FPG_OCR5_TRIG_SEL 32'h00008000
`define FPG_OCR5_LENGTH_OFFSET 16
`define FPG_OCR5_LENGTH 32'hffff0000
`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_COARSE_OFFSET 10
`define FPG_OCR6_COARSE 32'h00003c00
`define FPG_OCR6_CONT_OFFSET 14
`define FPG_OCR6_CONT 32'h00004000
`define FPG_OCR6_TRIG_SEL_OFFSET 15
`define FPG_OCR6_TRIG_SEL 32'h00008000
`define FPG_OCR6_LENGTH_OFFSET 16
`define FPG_OCR6_LENGTH 32'hffff0000
`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_COARSE_OFFSET 10
`define FPG_OCR7_COARSE 32'h00003c00
`define FPG_OCR7_CONT_OFFSET 14
`define FPG_OCR7_CONT 32'h00004000
`define FPG_OCR7_TRIG_SEL_OFFSET 15
`define FPG_OCR7_TRIG_SEL 32'h00008000
`define FPG_OCR7_LENGTH_OFFSET 16
`define FPG_OCR7_LENGTH 32'hffff0000
`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_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
......@@ -117,6 +117,7 @@ class FinePulseGenDriver extends CBusDevice;
real calib_time;
int calib_taps;
m_serdes_ratio = 8;
m_serdes_bit_length_ns = 2.0;
......@@ -145,6 +146,50 @@ class FinePulseGenDriver extends CBusDevice;
endtask
task automatic pulse_pattern( input int out, bit pattern[$], int fine, int cont );
int i,paddr,plen,mask=0,fail,rv;
uint32_t ocr_a, ocr_b;
for(i=0;i<pattern.size();i++)
begin
mask |= pattern[i] ? 1<<(7-(i % 8)) : 0;
if( i % 8 == 7 )
begin
$display("i %d mask %x paddr %x", i, mask, paddr );
writel(ADDR_WB_FPGEN_PGEN_CR,
( mask << WB_FPGEN_PGEN_CR_DATA_OFFSET )
| ( paddr << WB_FPGEN_PGEN_CR_ADDR_OFFSET )
| ( out << WB_FPGEN_PGEN_CR_OUT_SEL_OFFSET ) );
mask = 0;
paddr++;
end
end
ocr_a =
(fine << WB_FPGEN_OCR0A_FINE_OFFSET)
| (cont ? WB_FPGEN_OCR0A_CONT : 0)
| WB_FPGEN_OCR0A_PAT_EN;
ocr_b = (1 << WB_FPGEN_OCR0B_PPS_OFFS_OFFSET)
| ( (paddr-1) << WB_FPGEN_OCR0B_LENGTH_OFFSET);
writel(ADDR_WB_FPGEN_OCR0A + 8 * out, ocr_a);
writel(ADDR_WB_FPGEN_OCR0B + 8 * out, ocr_b);
writel(ADDR_WB_FPGEN_CSR, 1 << (WB_FPGEN_CSR_TRIG0_OFFSET + out));
#100ns;
poll_bits_with_timeout(ADDR_WB_FPGEN_CSR, (1 << (WB_FPGEN_CSR_READY_OFFSET + out)),
(1 << (WB_FPGEN_CSR_READY_OFFSET + out)), 20us, rv, fail);
if (fail) begin
m_log.fail("Timeout exceeded waiting for channel trigger ready bit.");
end
endtask
task automatic pulse(int out, int polarity, int cont, real delta, real length = 0,
int tr_force = 0);
......@@ -164,16 +209,17 @@ class FinePulseGenDriver extends CBusDevice;
if (!m_with_odelay) fine = 0;
m_log.msg(1, $sformatf(
"Pulse: tap_size %.5f coarse_par %d coarse_ser %d fine_taps %d length %.0f len_tics %d",
"Pulse: tap_size %.5f coarse_par %d coarse_ser %d fine_taps %d length %.0f len_tics %d cont %d",
m_delay_tap_size,
coarse_par,
coarse_ser,
fine,
length,
len_tics
len_tics,
cont
));
ocr_a = (coarse_ser << WB_FPGEN_OCR0A_COARSE_OFFSET)
ocr_a = (coarse_ser << WB_FPGEN_OCR0A_COARSE_OFFSET)
| (fine << WB_FPGEN_OCR0A_FINE_OFFSET)
| (cont ? WB_FPGEN_OCR0A_CONT : 0)
| (polarity ? WB_FPGEN_OCR0A_POL : 0 );
......@@ -185,7 +231,6 @@ class FinePulseGenDriver extends CBusDevice;
writel(ADDR_WB_FPGEN_OCR0A + 8 * out, ocr_a);
writel(ADDR_WB_FPGEN_OCR0B + 8 * out, ocr_b);
if (tr_force)
writel(ADDR_WB_FPGEN_CSR, 1 << (WB_FPGEN_CSR_FORCE0_OFFSET + out));
else
......@@ -250,7 +295,8 @@ module fpgen_test_wrapper;
.g_target_platform(g_TARGET_PLATFORM),
.g_use_external_serdes_clock(0),
.g_num_channels(1),
.g_use_odelay(6'b111111)
.g_use_odelay(6'b111111),
.g_enable_pattern_mode(6'b111111)
) DUT (
.rst_sys_n_i(rst_n),
......@@ -348,12 +394,14 @@ module fpgen_test_wrapper;
endtask
task run_tests();
task automatic run_tests();
real t;
real pwidths[$];
Logger logger = Logger::get();
CWishboneAccessor acc;
FinePulseGenDriver drv;
bit pattern[$];
int i;
@(posedge rst_n);
@(posedge clk_62m5);
......@@ -371,20 +419,30 @@ module fpgen_test_wrapper;
logger.pass();
logger.startTest(
$sformatf("Produce a 10MHz pattern") );
for(i=0;i<200;i++)
pattern.push_back(i/25%2?1:0);
drv.pulse_pattern(0, pattern, 0, 1);
logger.pass();
$stop;
logger.startTest(
$sformatf("Produce some fixed-width pulses at fine PPS offsets [%s]", g_TARGET_PLATFORM));
clear_timestamps();
for (t = 1.0; t <= 1.0; t += 5) begin
for (t = 1.0; t <= 100.0; t += 5.0) begin
t_pps_valid = 0;
while (!t_pps_valid) @(posedge clk_62m5);
$warning("dupa!");
//logger.msg(1, $sformatf("PPS absolute time = %t", t_pps));
logger.msg(1, $sformatf("PPS absolute time = %t", t_pps));
logger.msg(1, $sformatf("Ts Expected = %.03f", t));
timestamps_expected.push_back(t + 108.7);
widths_expected.push_back(1088.0);
drv.pulse(0, 0, 1, t, 1088.0);
drv.pulse(0, 0, 0, t, 1088.0);
end
if (!compare_timestamps()) logger.pass();
......
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