Commit 35e1f715 authored by Dimitris Lampridis's avatar Dimitris Lampridis

hdl: implement mechanism to atomically load calibration values.

Addresses HT-608, needed by HT-607.
Signed-off-by: Dimitris Lampridis's avatarDimitris Lampridis <dimitris.lampridis@cern.ch>
parent 429c9afb
......@@ -68,6 +68,16 @@ memory-map:
Write 1 to clear the last trigger status register. Auto-resets to zero.
x-hdl:
type: wire
- field:
name: calib_apply
range: 15
description: Apply the new calibration values
comment: |
Write 1 to apply the new calibration values (Gain and Offset) already
loaded in the chX_calib registers, in an atomic way (all channels at
once). Auto-resets to zero.
x-hdl:
type: wire
- reg:
name: sta
address: 0x00000004
......@@ -113,6 +123,13 @@ memory-map:
1: Valid acquisition configuration
- Shot number > 0
- Post-trigger sample > 0
- field:
name: calib_busy
range: 15
description: Calibration busy flag
comment: |
0: ready to accept new values
1: busy applying previous values (should never be detected by software, error condition)
- reg:
name: trig_stat
address: 0x00000008
......
......@@ -16,6 +16,7 @@ package fmc_adc_100ms_csr_pkg is
ctl_trig_led : std_logic;
ctl_acq_led : std_logic;
ctl_clear_trig_stat : std_logic;
ctl_calib_apply : std_logic;
ctl_wr : std_logic;
trig_en_ext : std_logic;
trig_en_sw : std_logic;
......@@ -73,10 +74,12 @@ package fmc_adc_100ms_csr_pkg is
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);
sta_serdes_pll : std_logic;
sta_serdes_synced : std_logic;
sta_acq_cfg : std_logic;
sta_calib_busy : std_logic;
trig_stat_ext : std_logic;
trig_stat_sw : std_logic;
trig_stat_time : std_logic;
......@@ -335,6 +338,7 @@ begin
ctl_trig_led_reg <= wb_i.dat(6);
ctl_acq_led_reg <= wb_i.dat(7);
fmc_adc_100ms_csr_o.ctl_clear_trig_stat <= wb_i.dat(8);
fmc_adc_100ms_csr_o.ctl_calib_apply <= wb_i.dat(15);
end if;
wr_ack_int <= wr_int;
when "0000001" =>
......@@ -571,6 +575,7 @@ begin
reg_rdat_int(6) <= ctl_trig_led_reg;
reg_rdat_int(7) <= ctl_acq_led_reg;
reg_rdat_int(8) <= fmc_adc_100ms_csr_i.ctl_clear_trig_stat;
reg_rdat_int(15) <= fmc_adc_100ms_csr_i.ctl_calib_apply;
rd_ack1_int <= rd_int;
when "0000001" =>
-- sta
......@@ -578,6 +583,7 @@ begin
reg_rdat_int(3) <= fmc_adc_100ms_csr_i.sta_serdes_pll;
reg_rdat_int(4) <= fmc_adc_100ms_csr_i.sta_serdes_synced;
reg_rdat_int(5) <= fmc_adc_100ms_csr_i.sta_acq_cfg;
reg_rdat_int(15) <= fmc_adc_100ms_csr_i.sta_calib_busy;
rd_ack1_int <= rd_int;
when "0000010" =>
-- trig_stat
......
......@@ -10,7 +10,7 @@
-------------------------------------------------------------------------------
-- Description: FMC ADC 100Ms/s core.
-------------------------------------------------------------------------------
-- Copyright (c) 2011-2018 CERN (BE-CO-HT)
-- Copyright (c) 2011-2020 CERN (BE-CO-HT)
-------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
-------------------------------------------------------------------------------
......@@ -222,10 +222,12 @@ architecture rtl of fmc_adc_100Ms_core is
signal sync_fifo_valid : std_logic;
-- Gain/offset calibration and saturation value
signal sync_calib_apply : std_logic;
signal sync_calib_busy : std_logic;
signal gain_calibr : std_logic_vector(63 downto 0);
signal offset_calibr : std_logic_vector(63 downto 0);
signal gain_calibr_in : std_logic_vector(63 downto 0);
signal offset_calibr_in : std_logic_vector(63 downto 0);
signal sync_calib_in : std_logic_vector(127 downto 0);
signal sync_calib_out : std_logic_vector(127 downto 0);
signal data_calibr_in : std_logic_vector(63 downto 0);
signal data_calibr_out : std_logic_vector(63 downto 0);
signal data_calibr_out_d1 : std_logic_vector(63 downto 0);
......@@ -471,6 +473,7 @@ begin
csr_regin.sta_serdes_pll <= serdes_locked_sync;
csr_regin.sta_serdes_synced <= serdes_synced_sync;
csr_regin.sta_acq_cfg <= acq_config_ok;
csr_regin.sta_calib_busy <= sync_calib_busy;
csr_regin.trig_stat_ext <= trig_storage(0);
csr_regin.trig_stat_sw <= trig_storage(1);
csr_regin.trig_stat_time <= trig_storage(4);
......@@ -497,6 +500,7 @@ begin
trig_led_man <= csr_regout.ctl_trig_led;
acq_led_man <= csr_regout.ctl_acq_led;
trig_storage_clear <= csr_regout.ctl_clear_trig_stat and ctl_reg_wr;
sync_calib_apply <= csr_regout.ctl_calib_apply and ctl_reg_wr;
int_trig_delay_in(1) <= csr_regout.ch1_trig_dly;
int_trig_delay_in(2) <= csr_regout.ch2_trig_dly;
int_trig_delay_in(3) <= csr_regout.ch3_trig_dly;
......@@ -521,11 +525,10 @@ begin
pre_trig_value <= csr_regout.pre_samples;
post_trig_value <= csr_regout.post_samples;
gain_calibr_in <= csr_regout.ch4_calib_gain & csr_regout.ch3_calib_gain &
csr_regout.ch2_calib_gain & csr_regout.ch1_calib_gain;
offset_calibr_in <= csr_regout.ch4_calib_offset & csr_regout.ch3_calib_offset &
csr_regout.ch2_calib_offset & csr_regout.ch1_calib_offset;
sync_calib_in <= csr_regout.ch4_calib_offset & csr_regout.ch3_calib_offset &
csr_regout.ch2_calib_offset & csr_regout.ch1_calib_offset &
csr_regout.ch4_calib_gain & csr_regout.ch3_calib_gain &
csr_regout.ch2_calib_gain & csr_regout.ch1_calib_gain;
sat_val_in <= csr_regout.ch4_sat_val & csr_regout.ch3_sat_val &
csr_regout.ch2_sat_val & csr_regout.ch1_sat_val;
......@@ -642,30 +645,6 @@ begin
data_i => sat_val_in(15*I-1 downto 15*(I-1)),
data_o => sat_val(15*I-1 downto 15*(I-1)));
cmp_ch_gain_sync : gc_sync_word_wr
generic map (
g_AUTO_WR => TRUE,
g_WIDTH => 16)
port map (
clk_in_i => sys_clk_i,
rst_in_n_i => '1',
clk_out_i => fs_clk,
rst_out_n_i => '1',
data_i => gain_calibr_in(16*I-1 downto 16*(I-1)),
data_o => gain_calibr(16*I-1 downto 16*(I-1)));
cmp_ch_offset_sync : gc_sync_word_wr
generic map (
g_AUTO_WR => TRUE,
g_WIDTH => 16)
port map (
clk_in_i => sys_clk_i,
rst_in_n_i => '1',
clk_out_i => fs_clk,
rst_out_n_i => '1',
data_i => offset_calibr_in(16*I-1 downto 16*(I-1)),
data_o => offset_calibr(16*I-1 downto 16*(I-1)));
cmp_ch_trig_delay_sync : gc_sync_word_wr
generic map (
g_AUTO_WR => TRUE,
......@@ -679,6 +658,23 @@ begin
data_o => int_trig_delay(I));
end generate gen_ch_reg_sync;
cmp_ch_calib_sync : gc_sync_word_wr
generic map (
g_AUTO_WR => FALSE,
g_WIDTH => 128)
port map (
clk_in_i => sys_clk_i,
rst_in_n_i => '1',
clk_out_i => fs_clk,
rst_out_n_i => '1',
data_i => sync_calib_in,
wr_i => sync_calib_apply,
busy_o => sync_calib_busy,
data_o => sync_calib_out);
offset_calibr <= sync_calib_out(127 downto 64);
gain_calibr <= sync_calib_out(63 downto 0);
cmp_sw_trig_sync : gc_pulse_synchronizer2
port map (
clk_in_i => sys_clk_i,
......
......@@ -16,6 +16,8 @@
`define FMC_ADC_100MS_CSR_CTL_ACQ_LED 'h80
`define FMC_ADC_100MS_CSR_CTL_CLEAR_TRIG_STAT_OFFSET 8
`define FMC_ADC_100MS_CSR_CTL_CLEAR_TRIG_STAT 'h100
`define FMC_ADC_100MS_CSR_CTL_CALIB_APPLY_OFFSET 15
`define FMC_ADC_100MS_CSR_CTL_CALIB_APPLY 'h8000
`define ADDR_FMC_ADC_100MS_CSR_STA 'h4
`define FMC_ADC_100MS_CSR_STA_FSM_OFFSET 0
`define FMC_ADC_100MS_CSR_STA_FSM 'h7
......@@ -25,6 +27,8 @@
`define FMC_ADC_100MS_CSR_STA_SERDES_SYNCED 'h10
`define FMC_ADC_100MS_CSR_STA_ACQ_CFG_OFFSET 5
`define FMC_ADC_100MS_CSR_STA_ACQ_CFG 'h20
`define FMC_ADC_100MS_CSR_STA_CALIB_BUSY_OFFSET 15
`define FMC_ADC_100MS_CSR_STA_CALIB_BUSY 'h8000
`define ADDR_FMC_ADC_100MS_CSR_TRIG_STAT 'h8
`define FMC_ADC_100MS_CSR_TRIG_STAT_EXT_OFFSET 0
`define FMC_ADC_100MS_CSR_TRIG_STAT_EXT 'h1
......
......@@ -246,6 +246,7 @@ module main;
acc.write(`CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH2_CALIB, 'h00008000);
acc.write(`CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH3_CALIB, 'h00008000);
acc.write(`CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH4_CALIB, 'h00008000);
acc.write(`CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CTL, 'h00008000); // apply calibration
acc.write(`CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH1_SAT, 'h00007fff);
acc.write(`CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH2_SAT, 'h00007fff);
acc.write(`CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH3_SAT, 'h00007fff);
......
......@@ -13,6 +13,7 @@
#define FMC_ADC_100MS_CSR_CTL_TRIG_LED 0x40UL
#define FMC_ADC_100MS_CSR_CTL_ACQ_LED 0x80UL
#define FMC_ADC_100MS_CSR_CTL_CLEAR_TRIG_STAT 0x100UL
#define FMC_ADC_100MS_CSR_CTL_CALIB_APPLY 0x8000UL
/* Status register */
#define FMC_ADC_100MS_CSR_STA 0x4UL
......@@ -21,6 +22,7 @@
#define FMC_ADC_100MS_CSR_STA_SERDES_PLL 0x8UL
#define FMC_ADC_100MS_CSR_STA_SERDES_SYNCED 0x10UL
#define FMC_ADC_100MS_CSR_STA_ACQ_CFG 0x20UL
#define FMC_ADC_100MS_CSR_STA_CALIB_BUSY 0x8000UL
/* Trigger status */
#define FMC_ADC_100MS_CSR_TRIG_STAT 0x8UL
......
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