Commit b45ac230 authored by Federico Vaga's avatar Federico Vaga

Merge remote-tracking branch 'origin/develop' into develop

parents 7ab1e9a1 0ea58655
......@@ -377,7 +377,7 @@ Mezzanine 1-wire Master
~~~~~~~~~~~~~~~~~~~~~~~
.. note::
FIXME talk about the themometer core in general-cores
FIXME talk about the thermometer core in general-cores
Mezzanine I2C Master
~~~~~~~~~~~~~~~~~~~~
......@@ -470,8 +470,8 @@ register enables the sampling clock (Si570 chip), and the other
internal components. Also, in order to use the input offset DACs, the
``OFFSET_DAC_CLR_N`` field must be set to one.
The field ``MAN_BITSLIP`` allows to ’manually’ control the ADC data
alignment in the de-serialiser. The fields ``TRIG_LED`` and
The field ``SERDES_CALIB`` allows to ’manually’ restart the timing
calibration and alignment in the de-serialiser. The fields ``TRIG_LED`` and
``ACQ_LED`` allows to control the FMC front panel LEDs. Those four
fields are for test purpose only and must stay zero in normal
operation.
......@@ -1047,6 +1047,9 @@ state.
The start of an acquisition is prohibited if either the number of
shots or the number of post-trigger samples is equal to zero.
.. note::
Acquired data are always stored to be read in little endian.
Single-shot Mode
----------------
......
......@@ -41,11 +41,9 @@ memory-map:
range: 3
description: Offset DACs clear (active low)
- field:
name: man_bitslip
name: serdes_calib
range: 4
description: Manual serdes bitslip (ignore on read)
x-hdl:
type: wire
description: Initial serdes calibration
- field:
name: trig_led
range: 6
......
......@@ -15,7 +15,7 @@ package fmc_adc_100ms_csr_pkg is
ctl_fsm_cmd : std_logic_vector(1 downto 0);
ctl_fmc_clk_oe : std_logic;
ctl_offset_dac_clr_n : std_logic;
ctl_man_bitslip : std_logic;
ctl_serdes_calib : std_logic;
ctl_trig_led : std_logic;
ctl_acq_led : std_logic;
ctl_clear_trig_stat : std_logic;
......@@ -47,7 +47,6 @@ package fmc_adc_100ms_csr_pkg is
type t_fmc_adc_100ms_csr_slave_out is record
ctl_fsm_cmd : std_logic_vector(1 downto 0);
ctl_man_bitslip : std_logic;
ctl_clear_trig_stat : std_logic;
ctl_calib_apply : std_logic;
sta_fsm : std_logic_vector(2 downto 0);
......@@ -120,6 +119,7 @@ architecture syn of fmc_adc_100ms_csr is
signal wb_wip : std_logic;
signal ctl_fmc_clk_oe_reg : std_logic;
signal ctl_offset_dac_clr_n_reg : std_logic;
signal ctl_serdes_calib_reg : std_logic;
signal ctl_trig_led_reg : std_logic;
signal ctl_acq_led_reg : std_logic;
signal ctl_wreq : std_logic;
......@@ -250,7 +250,7 @@ begin
fmc_adc_100ms_csr_o.ctl_fsm_cmd <= wr_dat_d0(1 downto 0);
fmc_adc_100ms_csr_o.ctl_fmc_clk_oe <= ctl_fmc_clk_oe_reg;
fmc_adc_100ms_csr_o.ctl_offset_dac_clr_n <= ctl_offset_dac_clr_n_reg;
fmc_adc_100ms_csr_o.ctl_man_bitslip <= wr_dat_d0(4);
fmc_adc_100ms_csr_o.ctl_serdes_calib <= ctl_serdes_calib_reg;
fmc_adc_100ms_csr_o.ctl_trig_led <= ctl_trig_led_reg;
fmc_adc_100ms_csr_o.ctl_acq_led <= ctl_acq_led_reg;
fmc_adc_100ms_csr_o.ctl_clear_trig_stat <= wr_dat_d0(8);
......@@ -260,6 +260,7 @@ begin
if rst_n_i = '0' then
ctl_fmc_clk_oe_reg <= '0';
ctl_offset_dac_clr_n_reg <= '0';
ctl_serdes_calib_reg <= '0';
ctl_trig_led_reg <= '0';
ctl_acq_led_reg <= '0';
ctl_wack <= '0';
......@@ -267,6 +268,7 @@ begin
if ctl_wreq = '1' then
ctl_fmc_clk_oe_reg <= wr_dat_d0(2);
ctl_offset_dac_clr_n_reg <= wr_dat_d0(3);
ctl_serdes_calib_reg <= wr_dat_d0(4);
ctl_trig_led_reg <= wr_dat_d0(6);
ctl_acq_led_reg <= wr_dat_d0(7);
end if;
......@@ -624,7 +626,7 @@ begin
end process;
-- Process for read requests.
process (rd_adr_d0, rd_req_d0, fmc_adc_100ms_csr_i.ctl_fsm_cmd, ctl_fmc_clk_oe_reg, ctl_offset_dac_clr_n_reg, fmc_adc_100ms_csr_i.ctl_man_bitslip, ctl_trig_led_reg, ctl_acq_led_reg, fmc_adc_100ms_csr_i.ctl_clear_trig_stat, fmc_adc_100ms_csr_i.ctl_calib_apply, fmc_adc_100ms_csr_i.sta_fsm, fmc_adc_100ms_csr_i.sta_serdes_pll, fmc_adc_100ms_csr_i.sta_serdes_synced, fmc_adc_100ms_csr_i.sta_acq_cfg, fmc_adc_100ms_csr_i.sta_fmc_nr, fmc_adc_100ms_csr_i.sta_calib_busy, fmc_adc_100ms_csr_i.trig_stat_ext, fmc_adc_100ms_csr_i.trig_stat_sw, fmc_adc_100ms_csr_i.trig_stat_time, fmc_adc_100ms_csr_i.trig_stat_ch1, fmc_adc_100ms_csr_i.trig_stat_ch2, fmc_adc_100ms_csr_i.trig_stat_ch3, fmc_adc_100ms_csr_i.trig_stat_ch4, trig_en_ext_reg, fmc_adc_100ms_csr_i.trig_en_sw, trig_en_time_reg, fmc_adc_100ms_csr_i.trig_en_aux_time, trig_en_ch1_reg, trig_en_ch2_reg, trig_en_ch3_reg, trig_en_ch4_reg, trig_pol_ext_reg, trig_pol_ch1_reg, trig_pol_ch2_reg, trig_pol_ch3_reg, trig_pol_ch4_reg, ext_trig_dly_reg, shots_nbr_reg, fmc_adc_100ms_csr_i.shots_remain, fmc_adc_100ms_csr_i.multi_depth, fmc_adc_100ms_csr_i.trig_pos, fmc_adc_100ms_csr_i.fs_freq, downsample_reg, pre_samples_reg, post_samples_reg, fmc_adc_100ms_csr_i.samples_cnt, fmc_adc_ch1_i.dat, fmc_adc_ch1_rack, fmc_adc_ch2_i.dat, fmc_adc_ch2_rack, fmc_adc_ch3_i.dat, fmc_adc_ch3_rack, fmc_adc_ch4_i.dat, fmc_adc_ch4_rack) begin
process (rd_adr_d0, rd_req_d0, fmc_adc_100ms_csr_i.ctl_fsm_cmd, ctl_fmc_clk_oe_reg, ctl_offset_dac_clr_n_reg, ctl_serdes_calib_reg, ctl_trig_led_reg, ctl_acq_led_reg, fmc_adc_100ms_csr_i.ctl_clear_trig_stat, fmc_adc_100ms_csr_i.ctl_calib_apply, fmc_adc_100ms_csr_i.sta_fsm, fmc_adc_100ms_csr_i.sta_serdes_pll, fmc_adc_100ms_csr_i.sta_serdes_synced, fmc_adc_100ms_csr_i.sta_acq_cfg, fmc_adc_100ms_csr_i.sta_fmc_nr, fmc_adc_100ms_csr_i.sta_calib_busy, fmc_adc_100ms_csr_i.trig_stat_ext, fmc_adc_100ms_csr_i.trig_stat_sw, fmc_adc_100ms_csr_i.trig_stat_time, fmc_adc_100ms_csr_i.trig_stat_ch1, fmc_adc_100ms_csr_i.trig_stat_ch2, fmc_adc_100ms_csr_i.trig_stat_ch3, fmc_adc_100ms_csr_i.trig_stat_ch4, trig_en_ext_reg, fmc_adc_100ms_csr_i.trig_en_sw, trig_en_time_reg, fmc_adc_100ms_csr_i.trig_en_aux_time, trig_en_ch1_reg, trig_en_ch2_reg, trig_en_ch3_reg, trig_en_ch4_reg, trig_pol_ext_reg, trig_pol_ch1_reg, trig_pol_ch2_reg, trig_pol_ch3_reg, trig_pol_ch4_reg, ext_trig_dly_reg, shots_nbr_reg, fmc_adc_100ms_csr_i.shots_remain, fmc_adc_100ms_csr_i.multi_depth, fmc_adc_100ms_csr_i.trig_pos, fmc_adc_100ms_csr_i.fs_freq, downsample_reg, pre_samples_reg, post_samples_reg, fmc_adc_100ms_csr_i.samples_cnt, fmc_adc_ch1_i.dat, fmc_adc_ch1_rack, fmc_adc_ch2_i.dat, fmc_adc_ch2_rack, fmc_adc_ch3_i.dat, fmc_adc_ch3_rack, fmc_adc_ch4_i.dat, fmc_adc_ch4_rack) begin
-- By default ack read requests
rd_dat_d0 <= (others => 'X');
fmc_adc_ch1_re <= '0';
......@@ -640,7 +642,7 @@ begin
rd_dat_d0(1 downto 0) <= fmc_adc_100ms_csr_i.ctl_fsm_cmd;
rd_dat_d0(2) <= ctl_fmc_clk_oe_reg;
rd_dat_d0(3) <= ctl_offset_dac_clr_n_reg;
rd_dat_d0(4) <= fmc_adc_100ms_csr_i.ctl_man_bitslip;
rd_dat_d0(4) <= ctl_serdes_calib_reg;
rd_dat_d0(5) <= '0';
rd_dat_d0(6) <= ctl_trig_led_reg;
rd_dat_d0(7) <= ctl_acq_led_reg;
......
......@@ -50,8 +50,8 @@ entity ltc2174_2l16b_receiver is
adc_outb_n_i : in std_logic_vector(3 downto 0);
-- Async reset input (active high) for iserdes
serdes_arst_i : in std_logic := '0';
-- Manual bitslip command (optional)
serdes_bslip_i : in std_logic := '0';
-- Enable serdes calibration (start with an initial calibration)
serdes_calib_i : in std_logic := '0';
-- SERDES BUFPLL lock status flag
-- (used when g_USE_PLL=TRUE, otherwise it is tied to '1')
serdes_locked_o : out std_logic;
......@@ -70,26 +70,29 @@ end entity ltc2174_2l16b_receiver;
architecture arch of ltc2174_2l16b_receiver is
signal adc_dco : std_logic;
signal adc_fr : std_logic;
signal adc_outa : std_logic_vector(3 downto 0);
signal adc_outb : std_logic_vector(3 downto 0);
signal adc_out, adc_out_dly_m, adc_out_dly_s : std_logic_vector(8 downto 0);
signal serdes_incdec, serdes_valid : std_logic_vector(8 downto 0);
signal clk_serdes_p : std_logic;
signal clk_serdes_n : std_logic;
signal clk_div_buf : std_logic;
signal serdes_strobe : std_logic := '0';
signal serdes_auto_bslip : std_logic := '0';
signal serdes_bitslip : std_logic := '0';
signal serdes_synced : std_logic := '0';
signal serdes_m2s_shift : std_logic_vector(8 downto 0) := (others => '0');
signal serdes_s2m_shift : std_logic_vector(8 downto 0) := (others => '0');
signal serdes_serial_in : std_logic_vector(8 downto 0) := (others => '0');
signal serdes_out_fr : std_logic_vector(7 downto 0) := (others => '0');
signal serdes_out_fr : std_logic_vector(6 downto 0) := (others => '0');
signal bitslip_sreg : unsigned(7 downto 0) := to_unsigned(1, 8);
type serdes_array is array (0 to 8) of std_logic_vector(7 downto 0);
type serdes_array is array (0 to 8) of std_logic_vector(6 downto 0);
signal serdes_parallel_out : serdes_array := (others => (others => '0'));
signal iodelay_cal_s, iodelay_cal_m : std_logic;
signal iodelay_rst : std_logic;
signal iodelay_busy : std_logic;
signal iodelay_recal : std_logic;
signal iodelay_busy_m, iodelay_busy_s : std_logic_vector(8 downto 0);
-- used to select the data rate of the ISERDES blocks
function f_data_rate_sel (
constant SDR : boolean)
......@@ -128,10 +131,10 @@ begin -- architecture arch
port map (
I => adc_fr_p_i,
IB => adc_fr_n_i,
O => adc_fr);
O => adc_out(8));
-- ADC data
gen_adc_data_buf : for I in 0 to 3 generate
cmp_adc_outa_buf : IBUFDS
generic map (
DIFF_TERM => TRUE,
......@@ -140,7 +143,7 @@ begin -- architecture arch
port map (
I => adc_outa_p_i(i),
IB => adc_outa_n_i(i),
O => adc_outa(i));
O => adc_out(2 * i + 1));
cmp_adc_outb_buf : IBUFDS
generic map (
......@@ -150,10 +153,161 @@ begin -- architecture arch
port map (
I => adc_outb_p_i(i),
IB => adc_outb_n_i(i),
O => adc_outb(i));
O => adc_out(2 * i));
end generate gen_adc_data_buf;
-- IDELAY (master and slave) on data and frame inputs.
gen_adc_idelay: for I in adc_out'range generate
signal inc, ce : std_logic;
signal phasediff : unsigned(4 downto 0);
begin
cmp_idelay_master: IODELAY2
generic map (
DATA_RATE => f_data_rate_sel(g_USE_PLL), -- <SDR>, DDR
IDELAY_VALUE => 0, -- {0 ... 255}
IDELAY2_VALUE => 0, -- {0 ... 255}
IDELAY_MODE => "NORMAL",-- NORMAL, PCI
ODELAY_VALUE => 0, -- {0 ... 255}
IDELAY_TYPE => "DIFF_PHASE_DETECTOR",-- "DEFAULT", "DIFF_PHASE_DETECTOR", "FIXED", "VARIABLE_FROM_HALF_MAX", "VARIABLE_FROM_ZERO"
COUNTER_WRAPAROUND => "WRAPAROUND", -- <STAY_AT_LIMIT>, WRAPAROUND
DELAY_SRC => "IDATAIN", -- "IO", "IDATAIN", "ODATAIN"
SERDES_MODE => "MASTER", -- <NONE>, MASTER, SLAVE
SIM_TAPDELAY_VALUE => 49) --
port map (
IDATAIN => adc_out(i), -- data from primary IOB
TOUT => open, -- tri-state signal to IOB
DOUT => open, -- output data to IOB
T => '1', -- tri-state control from OLOGIC/OSERDES2
ODATAIN => '0', -- data from OLOGIC/OSERDES2
DATAOUT => adc_out_dly_m(i), -- Output data 1 to ILOGIC/ISERDES2
DATAOUT2 => open, -- Output data 2 to ILOGIC/ISERDES2
IOCLK0 => clk_serdes_p, -- High speed clock for calibration
IOCLK1 => clk_serdes_n, -- High speed clock for calibration
CLK => clk_div_buf, -- Fabric clock (GCLK) for control signals
CAL => iodelay_cal_m, -- Calibrate control signal
INC => inc, -- Increment counter
CE => ce, -- Clock Enable
RST => iodelay_rst, -- Reset delay line
BUSY => iodelay_busy_m(i)); -- output signal indicating sync circuit has finished / calibration has finished
cmp_idelay_slave: IODELAY2
generic map (
DATA_RATE => f_data_rate_sel(g_USE_PLL), -- <SDR>, DDR
IDELAY_VALUE => 0, -- {0 ... 255}
IDELAY2_VALUE => 0, -- {0 ... 255}
IDELAY_MODE => "NORMAL",-- NORMAL, PCI
ODELAY_VALUE => 0, -- {0 ... 255}
IDELAY_TYPE => "DIFF_PHASE_DETECTOR",-- "DEFAULT", "DIFF_PHASE_DETECTOR", "FIXED", "VARIABLE_FROM_HALF_MAX", "VARIABLE_FROM_ZERO"
COUNTER_WRAPAROUND => "WRAPAROUND", -- <STAY_AT_LIMIT>, WRAPAROUND
DELAY_SRC => "IDATAIN", -- "IO", "IDATAIN", "ODATAIN"
SERDES_MODE => "SLAVE", -- <NONE>, MASTER, SLAVE
SIM_TAPDELAY_VALUE => 49) --
port map (
IDATAIN => adc_out(i), -- data from primary IOB
TOUT => open, -- tri-state signal to IOB
DOUT => open, -- output data to IOB
T => '1', -- tri-state control from OLOGIC/OSERDES2
ODATAIN => '0', -- data from OLOGIC/OSERDES2
DATAOUT => adc_out_dly_s(i), -- Output data 1 to ILOGIC/ISERDES2
DATAOUT2 => open, -- Output data 2 to ILOGIC/ISERDES2
IOCLK0 => clk_serdes_p, -- High speed clock for calibration
IOCLK1 => clk_serdes_n, -- High speed clock for calibration
CLK => clk_div_buf, -- Fabric clock (GCLK) for control signals
CAL => iodelay_cal_s, -- Calibrate control signal
INC => inc, -- Increment counter
CE => ce, -- Clock Enable
RST => iodelay_rst, -- Reset delay line
BUSY => iodelay_busy_s(i)); -- output signal indicating sync circuit has finished / calibration has finished
-- Adjust delay
process (clk_div_buf)
begin
if rising_edge(clk_div_buf) then
ce <= '0';
inc <= '0';
if serdes_calib_i = '0' or iodelay_recal = '1' then
phasediff <= "10000";
elsif serdes_valid (i) = '1' then
if serdes_incdec (i) = '1' then
if phasediff = "11111" then
ce <= '1';
inc <= '1';
phasediff <= "10000";
else
phasediff <= phasediff + 1;
end if;
else
if phasediff = "00000" then
ce <= '1';
inc <= '0';
phasediff <= "10000";
else
phasediff <= phasediff - 1;
end if;
end if;
end if;
end if;
end process;
end generate;
iodelay_busy <= '0' when iodelay_busy_s = (iodelay_busy_s'range => '0') and iodelay_busy_m = (iodelay_busy_m'range => '0') else '1';
-- IODELAY calibration
process(clk_div_buf, serdes_arst_i)
type t_state is (S_RESET, S_RSTCAL, S_RSTBUSY, S_WAIT, S_BUSY);
variable state : t_state;
variable counter : natural;
begin
if serdes_arst_i = '1' then
iodelay_cal_m <= '0';
iodelay_cal_s <= '0';
iodelay_rst <= '0';
iodelay_recal <= '1';
state := S_RESET;
elsif rising_edge(clk_div_buf) then
iodelay_cal_m <= '0';
iodelay_cal_s <= '0';
iodelay_rst <= '0';
iodelay_recal <= '1';
case state is
when S_RESET =>
if serdes_calib_i = '1' and iodelay_busy = '0' then
state := S_RSTCAL;
end if;
when S_RSTCAL =>
-- Issue CAL on reset
iodelay_cal_m <= '1';
iodelay_cal_s <= '1';
state := S_BUSY;
when S_RSTBUSY =>
-- And then RESET
if iodelay_busy = '0' then
counter := 0;
iodelay_rst <= '1';
state := S_WAIT;
end if;
when S_WAIT =>
-- Periodically calibrate
if serdes_calib_i = '0' then
state := S_RESET;
elsif counter = 2**20 then
if iodelay_busy = '0' then
iodelay_cal_s <= '1';
state := S_BUSY;
end if;
else
counter := counter + 1;
iodelay_recal <= '0';
end if;
when S_BUSY =>
if iodelay_busy = '0' then
counter := 0;
state := S_WAIT;
end if;
end case;
end if;
end process;
------------------------------------------------------------------------------
-- Clock generation for deserializer
--
......@@ -183,7 +337,7 @@ begin -- architecture arch
I_INVERT => FALSE,
USE_DOUBLER => FALSE)
port map (
I => adc_dco,
I => adc_dco, -- 350Mhz
IOCLK => open,
DIVCLK => l_pll_clkin,
SERDESSTROBE => open);
......@@ -194,42 +348,42 @@ begin -- architecture arch
DIVIDE_BYPASS => TRUE)
port map (
O => l_pll_clkfbin,
I => clk_serdes_p);
I => clk_serdes_p); -- 100Mhz
cmp_dco_pll : PLL_BASE
generic map (
BANDWIDTH => "OPTIMIZED",
CLKFBOUT_MULT => 2,
CLKIN_PERIOD => 2.5,
CLKFBOUT_MULT => 2, -- M=2, Fvco=700Mhz
CLKIN_PERIOD => 2.86,
CLKOUT0_DIVIDE => 1,
CLKOUT1_DIVIDE => 8,
CLKOUT1_DIVIDE => 7,
CLK_FEEDBACK => "CLKOUT0",
COMPENSATION => "SOURCE_SYNCHRONOUS",
DIVCLK_DIVIDE => 1,
REF_JITTER => 0.01)
port map (
CLKOUT0 => l_pll_clkout0,
CLKOUT1 => l_pll_clkout1,
CLKOUT0 => l_pll_clkout0, -- 700Mhz (to BUFPLL)
CLKOUT1 => l_pll_clkout1, -- 100Mhz
LOCKED => l_pll_locked,
CLKFBIN => l_pll_clkfbin,
CLKIN => l_pll_clkin,
CLKIN => l_pll_clkin, -- 350Mhz
RST => '0');
cmp_clk_div_buf : BUFG
port map (
I => l_pll_clkout1,
I => l_pll_clkout1, -- 100Mhz
O => clk_div_buf);
cmp_dco_bufpll : BUFPLL
generic map (
DIVIDE => 8)
DIVIDE => 7)
port map (
IOCLK => clk_serdes_p,
IOCLK => clk_serdes_p, -- 700Mhz (to BUFIO2FB and serdes)
LOCK => serdes_locked_o,
SERDESSTROBE => serdes_strobe,
SERDESSTROBE => serdes_strobe, -- 100Mhz
GCLK => clk_div_buf,
LOCKED => l_pll_locked,
PLLIN => l_pll_clkout0);
PLLIN => l_pll_clkout0); -- 700Mhz
-- not used in this case
clk_serdes_n <= '0';
......@@ -247,25 +401,25 @@ begin -- architecture arch
cmp_dco_bufio_p : BUFIO2
generic map (
DIVIDE => 8,
DIVIDE => 7,
DIVIDE_BYPASS => FALSE,
I_INVERT => FALSE,
USE_DOUBLER => TRUE)
port map (
I => adc_dco,
IOCLK => clk_serdes_p,
DIVCLK => l_clk_div,
I => adc_dco, -- 350Mhz DDR
IOCLK => clk_serdes_p, -- 350Mhz
DIVCLK => l_clk_div, -- 100Mhz (2*350/7)
SERDESSTROBE => serdes_strobe);
cmp_dco_bufio_n : BUFIO2
generic map (
DIVIDE => 8,
DIVIDE => 7,
DIVIDE_BYPASS => FALSE,
I_INVERT => TRUE,
USE_DOUBLER => FALSE)
port map (
I => adc_dco,
IOCLK => clk_serdes_n,
IOCLK => clk_serdes_n, -- 350Mhz, 180 phase shift.
DIVCLK => open,
SERDESSTROBE => open);
......@@ -290,25 +444,23 @@ begin -- architecture arch
begin
if rising_edge(clk_div_buf) then
-- Shift register to generate bitslip enable once every 8 clock ticks
bitslip_sreg <= bitslip_sreg(0) & bitslip_sreg(bitslip_sreg'length-1 downto 1);
bitslip_sreg <= bitslip_sreg(0) & bitslip_sreg(bitslip_sreg'left downto 1);
-- Generate bitslip and synced signal
if(bitslip_sreg(bitslip_sreg'LEFT) = '1') then
-- use fr_n pattern (fr_p and fr_n are swapped on the adc mezzanine)
if(serdes_out_fr /= "00001111") then
serdes_auto_bslip <= '1';
if bitslip_sreg(bitslip_sreg'LEFT) = '1' then
if serdes_out_fr /= "0000000" and serdes_out_fr /= "1111111" then
serdes_bitslip <= '1';
serdes_synced <= '0';
else
serdes_auto_bslip <= '0';
serdes_bitslip <= '0';
serdes_synced <= '1';
end if;
else
serdes_auto_bslip <= '0';
serdes_bitslip <= '0';
end if;
end if;
end process p_auto_bitslip;
serdes_bitslip <= serdes_auto_bslip or serdes_bslip_i;
serdes_synced_o <= serdes_synced;
------------------------------------------------------------------------------
......@@ -320,19 +472,13 @@ begin -- architecture arch
------------------------------------------------------------------------------
-- serdes inputs forming
serdes_serial_in <= adc_fr
& adc_outa(3) & adc_outb(3)
& adc_outa(2) & adc_outb(2)
& adc_outa(1) & adc_outb(1)
& adc_outa(0) & adc_outb(0);
gen_adc_data_iserdes : for I in 0 to 8 generate
cmp_adc_iserdes_master : ISERDES2
generic map (
BITSLIP_ENABLE => TRUE,
DATA_RATE => f_data_rate_sel(g_USE_PLL),
DATA_WIDTH => 8,
DATA_WIDTH => 7,
INTERFACE_TYPE => "RETIMED",
SERDES_MODE => "MASTER")
port map (
......@@ -340,19 +486,19 @@ begin -- architecture arch
CFB1 => open,
DFB => open,
FABRICOUT => open,
INCDEC => open,
INCDEC => serdes_incdec(i),
Q1 => serdes_parallel_out(I)(3),
Q2 => serdes_parallel_out(I)(2),
Q3 => serdes_parallel_out(I)(1),
Q4 => serdes_parallel_out(I)(0),
SHIFTOUT => serdes_m2s_shift(I),
VALID => open,
VALID => serdes_valid(i),
BITSLIP => serdes_bitslip,
CE0 => '1',
CLK0 => clk_serdes_p,
CLK1 => clk_serdes_n,
CLKDIV => clk_div_buf,
D => serdes_serial_in(I),
D => adc_out_dly_m(i),
IOCE => serdes_strobe,
RST => serdes_arst_i,
SHIFTIN => serdes_s2m_shift(I));
......@@ -361,7 +507,7 @@ begin -- architecture arch
generic map (
BITSLIP_ENABLE => TRUE,
DATA_RATE => f_data_rate_sel(g_USE_PLL),
DATA_WIDTH => 8,
DATA_WIDTH => 7,
INTERFACE_TYPE => "RETIMED",
SERDES_MODE => "SLAVE")
port map (
......@@ -370,7 +516,7 @@ begin -- architecture arch
DFB => open,
FABRICOUT => open,
INCDEC => open,
Q1 => serdes_parallel_out(I)(7),
Q1 => open,
Q2 => serdes_parallel_out(I)(6),
Q3 => serdes_parallel_out(I)(5),
Q4 => serdes_parallel_out(I)(4),
......@@ -381,7 +527,7 @@ begin -- architecture arch
CLK0 => clk_serdes_p,
CLK1 => clk_serdes_n,
CLKDIV => clk_div_buf,
D => '0',
D => adc_out_dly_s(i),
IOCE => serdes_strobe,
RST => serdes_arst_i,
SHIFTIN => serdes_m2s_shift(I));
......@@ -393,12 +539,14 @@ begin -- architecture arch
-- Data re-ordering for serdes outputs
gen_serdes_dout_reorder : for I in 0 to 3 generate
gen_serdes_dout_reorder_bits : for J in 0 to 7 generate
gen_serdes_dout_reorder_bits : for J in 0 to 6 generate
-- OUT#B: even bits
adc_data_o(I*16 + 2*J) <= serdes_parallel_out(2*I)(J);
adc_data_o(I*16 + 2*J + 2) <= serdes_parallel_out(2*I)(J);
-- OUT#A: odd bits
adc_data_o(I*16 + 2*J + 1) <= serdes_parallel_out(2*I + 1)(J);
adc_data_o(I*16 + 2*J + 3) <= serdes_parallel_out(2*I + 1)(J);
end generate gen_serdes_dout_reorder_bits;
adc_data_o(I*16 + 0) <= '0';
adc_data_o(I*16 + 1) <= '0';
end generate gen_serdes_dout_reorder;
end architecture arch;
......@@ -153,8 +153,7 @@ architecture rtl of fmc_adc_100Ms_core is
-- SerDes
signal serdes_out_data : std_logic_vector(63 downto 0);
signal serdes_out_data_synced : std_logic_vector(63 downto 0);
signal serdes_man_bitslip : std_logic;
signal serdes_man_bitslip_sync : std_logic;
signal serdes_calib_sync : std_logic;
signal serdes_locked : std_logic;
signal serdes_locked_sync : std_logic;
signal serdes_synced : std_logic;
......@@ -430,8 +429,8 @@ begin
port map (
clk_i => fs_clk,
rst_n_a_i => '1',
d_i => serdes_man_bitslip,
q_o => serdes_man_bitslip_sync);
d_i => csr_regout.ctl_serdes_calib,
q_o => serdes_calib_sync);
cmp_adc_serdes : entity work.ltc2174_2l16b_receiver
generic map (
......@@ -446,7 +445,7 @@ begin
adc_outb_p_i => adc_outb_p_i,
adc_outb_n_i => adc_outb_n_i,
serdes_arst_i => serdes_arst,
serdes_bslip_i => serdes_man_bitslip_sync,
serdes_calib_i => serdes_calib_sync,
serdes_locked_o => serdes_locked,
serdes_synced_o => serdes_synced,
adc_data_o => serdes_out_data,
......@@ -487,7 +486,6 @@ begin
fmc_adc_ch4_o => wb_channel_in(4));
csr_regin.ctl_fsm_cmd <= fsm_cmd;
csr_regin.ctl_man_bitslip <= serdes_man_bitslip;
csr_regin.ctl_clear_trig_stat <= trig_storage_clear;
csr_regin.ctl_calib_apply <= sync_calib_apply;
......@@ -533,12 +531,10 @@ begin
if rising_edge(sys_clk_i) then
if ctl_reg_wr = '1' then
fsm_cmd <= csr_regout.ctl_fsm_cmd;
serdes_man_bitslip <= csr_regout.ctl_man_bitslip;
trig_storage_clear <= csr_regout.ctl_clear_trig_stat;
sync_calib_apply <= csr_regout.ctl_calib_apply;
else
fsm_cmd <= (others => '0');
serdes_man_bitslip <= '0';
trig_storage_clear <= '0';
sync_calib_apply <= '0';
end if;
......
......@@ -69,11 +69,11 @@ entity fmc_adc_mezzanine is
acq_cfg_ok_o : out std_logic;
-- Auxiliary trigger input wishbone interface
wb_trigin_slave_i : in t_wishbone_slave_in;
wb_trigin_slave_i : in t_wishbone_slave_in := c_DUMMY_WB_SLAVE_IN;
wb_trigin_slave_o : out t_wishbone_slave_out;
-- Trigout wishbone interface
wb_trigout_slave_i : in t_wishbone_slave_in;
wb_trigout_slave_i : in t_wishbone_slave_in := c_DUMMY_WB_SLAVE_IN;
wb_trigout_slave_o : out t_wishbone_slave_out;
-- FMC interface
......
......@@ -10,8 +10,8 @@
`define FMC_ADC_100MS_CSR_CTL_FMC_CLK_OE 'h4
`define FMC_ADC_100MS_CSR_CTL_OFFSET_DAC_CLR_N_OFFSET 3
`define FMC_ADC_100MS_CSR_CTL_OFFSET_DAC_CLR_N 'h8
`define FMC_ADC_100MS_CSR_CTL_MAN_BITSLIP_OFFSET 4
`define FMC_ADC_100MS_CSR_CTL_MAN_BITSLIP 'h10
`define FMC_ADC_100MS_CSR_CTL_SERDES_CALIB_OFFSET 4
`define FMC_ADC_100MS_CSR_CTL_SERDES_CALIB 'h10
`define FMC_ADC_100MS_CSR_CTL_TRIG_LED_OFFSET 6
`define FMC_ADC_100MS_CSR_CTL_TRIG_LED 'h40
`define FMC_ADC_100MS_CSR_CTL_ACQ_LED_OFFSET 7
......
......@@ -531,10 +531,11 @@ begin -- architecture arch
d_i => fmc_irq(I),
q_o => irq_vector(I));
cmp_fmc_adc_mezzanine : fmc_adc_mezzanine
cmp_fmc_adc_mezzanine : entity work.fmc_adc_mezzanine
generic map (
g_MULTISHOT_RAM_SIZE => g_MULTISHOT_RAM_SIZE,
g_SPARTAN6_USE_PLL => TRUE,
g_BYTE_SWAP => TRUE,
g_FMC_ADC_NR => I,
g_WB_MODE => PIPELINED,
g_WB_GRANULARITY => BYTE)
......
......@@ -76,17 +76,20 @@ int fa_adc_output_randomizer_set(struct fa_dev *fa, bool enable)
uint32_t tx, rx;
int err;
/* Read register A1 */
tx = 0x8000;
tx |= (1 << 8);
err = fa_spi_xfer(fa, FA_SPI_SS_ADC, 16, tx, &rx);
if (err)
return err;
/* Set or clear RAND bit */
if (enable)
rx |= BIT(6);
else
rx &= ~BIT(6);
/* Write back A1 */
tx = 0x0000;
tx |= (1 << 8);
tx |= (rx & 0xFF);
......@@ -106,6 +109,7 @@ bool fa_adc_is_output_randomizer(struct fa_dev *fa)
uint32_t tx, rx;
int err;
/* Read register A1 */
tx = 0x8000;
tx |= (1 << 8);
err = fa_spi_xfer(fa, FA_SPI_SS_ADC, 16, tx, &rx);
......
......@@ -82,6 +82,9 @@ int fa_spi_init(struct fa_dev *fa)
/* Force 2's complement data output (register 1, bit 5) */
fa_spi_xfer(fa, FA_SPI_SS_ADC, 16, BIT(8) | BIT(5), &rx);
/* 2 lanes, 14-bit serializaion (register 2) */
fa_spi_xfer(fa, FA_SPI_SS_ADC, 16, (2 << 8) | 0x1, &rx);
return 0;
}
......
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