Commit 06ab5cf4 authored by Matthieu Cattin's avatar Matthieu Cattin

hdl: Fix bug in saturation block, add registers to improve timing.

- fixed and variable saturation blocks merged into one.
- registers added before the crossbar in the fmc-adc mezzanine component.
- acq_config_ok signal is now registered.
parent 8f87d9ba
......@@ -240,21 +240,12 @@ architecture rtl of fmc_adc_100Ms_core is
clk_i : in std_logic; --! Clock
offset_i : in std_logic_vector(15 downto 0); --! Signed offset input (two's complement)
gain_i : in std_logic_vector(15 downto 0); --! Unsigned gain input
sat_i : in std_logic_vector(14 downto 0); --! Unsigned saturation value input
data_i : in std_logic_vector(15 downto 0); --! Signed data input (two's complement)
data_o : out std_logic_vector(15 downto 0) --! Signed data output (two's complement)
);
end component offset_gain_s;
component var_sat_s
port (
rst_n_i : in std_logic; --! Reset (active low)
clk_i : in std_logic; --! Clock
sat_i : in std_logic_vector(14 downto 0); --! Unsigned saturation value input
data_i : in std_logic_vector(15 downto 0); --! Signed data input (two's complement)
data_o : out std_logic_vector(15 downto 0) --! Signed data output (two's complement)
);
end component var_sat_s;
component monostable
generic(
g_INPUT_POLARITY : std_logic := '1'; --! trigger_i polarity
......@@ -802,17 +793,9 @@ begin
clk_i => fs_clk,
offset_i => offset_calibr((I+1)*16-1 downto I*16),
gain_i => gain_calibr((I+1)*16-1 downto I*16),
sat_i => sat_val((I+1)*15-1 downto I*15),
data_i => data_calibr_in((I+1)*16-1 downto I*16),
data_o => data_calibr_out_t((I+1)*16-1 downto I*16)
);
cmp_var_sat : var_sat_s
port map (
rst_n_i => fs_rst_n,
clk_i => fs_clk,
sat_i => sat_val((I+1)*15-1 downto I*15),
data_i => data_calibr_out_t((I+1)*16-1 downto I*16),
data_o => data_calibr_out((I+1)*16-1 downto I*16)
data_o => data_calibr_out((I+1)*16-1 downto I*16)
);
end generate l_offset_gain_calibr;
......@@ -1187,10 +1170,27 @@ begin
-- Post-trigger sample must be > 0
-- Shot number must be > 0
-- Number of sample (+time-tag) in multi-shot must be < multi-shot ram size
acq_config_ok <= '0' when (unsigned(post_trig_value) = to_unsigned(0, post_trig_value'length)) else
'0' when (unsigned(shots_value) = to_unsigned(0, shots_value'length)) else
'0' when (unsigned(pre_trig_value)+unsigned(post_trig_value)+4 > to_unsigned(g_multishot_ram_size, pre_trig_value'length) and single_shot = '0') else
'1';
p_acq_cfg_ok: process (sys_clk_i)
begin
if rising_edge(sys_clk_i) then
if sys_rst_n_i = '0' then
acq_config_ok <= '0';
elsif unsigned(post_trig_value) = to_unsigned(0, post_trig_value'length) then
acq_config_ok <= '0';
elsif unsigned(shots_value) = to_unsigned(0, shots_value'length) then
acq_config_ok <= '0';
elsif unsigned(pre_trig_value)+unsigned(post_trig_value)+4 > to_unsigned(g_multishot_ram_size, pre_trig_value'length) and single_shot = '0' then
acq_config_ok <= '0';
else
acq_config_ok <= '1';
end if;
end if;
end process p_acq_cfg_ok;
--acq_config_ok <= '0' when (unsigned(post_trig_value) = to_unsigned(0, post_trig_value'length)) else
-- '0' when (unsigned(shots_value) = to_unsigned(0, shots_value'length)) else
-- '0' when (unsigned(pre_trig_value)+unsigned(post_trig_value)+4 > to_unsigned(g_multishot_ram_size, pre_trig_value'length) and single_shot = '0') else
-- '1';
-- FSM transitions
p_acq_fsm_transitions : process(sys_clk_i, sys_rst_n_i)
......
......@@ -251,6 +251,10 @@ architecture rtl of fmc_adc_mezzanine is
signal cnx_slave_out : t_wishbone_slave_out_array(c_NUM_WB_SLAVES-1 downto 0);
signal cnx_slave_in : t_wishbone_slave_in_array(c_NUM_WB_SLAVES-1 downto 0);
-- Wishbone bus from additional registers
signal xreg_slave_out : t_wishbone_slave_out;
signal xreg_slave_in : t_wishbone_slave_in;
-- Mezzanine system I2C for EEPROM
signal sys_scl_in : std_logic;
signal sys_scl_out : std_logic;
......@@ -294,6 +298,17 @@ begin
------------------------------------------------------------------------------
-- CSR wishbone crossbar
------------------------------------------------------------------------------
-- Additional register to help timing
cmp_xwb_reg : xwb_register_link
port map(
clk_sys_i => sys_clk_i,
rst_n_i => sys_rst_n_i,
slave_i => xreg_slave_in,
slave_o => xreg_slave_out,
master_i => cnx_slave_out(c_WB_MASTER),
master_o => cnx_slave_in(c_WB_MASTER));
cmp_sdb_crossbar : xwb_sdb_crossbar
generic map (
g_num_masters => c_NUM_WB_SLAVES,
......@@ -311,16 +326,16 @@ begin
master_o => cnx_master_out);
-- Connect crossbar slave port to entity port
cnx_slave_in(c_WB_MASTER).adr <= wb_csr_adr_i;
cnx_slave_in(c_WB_MASTER).dat <= wb_csr_dat_i;
cnx_slave_in(c_WB_MASTER).sel <= wb_csr_sel_i;
cnx_slave_in(c_WB_MASTER).stb <= wb_csr_stb_i;
cnx_slave_in(c_WB_MASTER).we <= wb_csr_we_i;
cnx_slave_in(c_WB_MASTER).cyc <= wb_csr_cyc_i;
wb_csr_dat_o <= cnx_slave_out(c_WB_MASTER).dat;
wb_csr_ack_o <= cnx_slave_out(c_WB_MASTER).ack;
wb_csr_stall_o <= cnx_slave_out(c_WB_MASTER).stall;
xreg_slave_in.adr <= wb_csr_adr_i;
xreg_slave_in.dat <= wb_csr_dat_i;
xreg_slave_in.sel <= wb_csr_sel_i;
xreg_slave_in.stb <= wb_csr_stb_i;
xreg_slave_in.we <= wb_csr_we_i;
xreg_slave_in.cyc <= wb_csr_cyc_i;
wb_csr_dat_o <= xreg_slave_out.dat;
wb_csr_ack_o <= xreg_slave_out.ack;
wb_csr_stall_o <= xreg_slave_out.stall;
------------------------------------------------------------------------------
-- Mezzanine system managment I2C master
......
......@@ -12,16 +12,17 @@
--
-- version: 1.0
--
-- description: Offset and gain correction with saturation.
-- description: Offset and gain correction with configurable saturation.
-- Input and output are signed.
-- Latency = 2
--
-- ___ ___ ________
-- | | offset_data | | product | |
-- data_i ---->| + |------------>| X |-------->|saturate|--> data_o
-- |___| |___| |________|
-- ^ ^
-- | |
-- offset_i gain_i
-- ^ ^ ^
-- | | |
-- offset_i gain_i sat_i
--
--
-- dependencies:
......@@ -65,6 +66,7 @@ entity offset_gain_s is
clk_i : in std_logic; --! Clock
offset_i : in std_logic_vector(15 downto 0); --! Signed offset input (two's complement)
gain_i : in std_logic_vector(15 downto 0); --! Unsigned gain input
sat_i : in std_logic_vector(14 downto 0); --! Unsigned saturation value input
data_i : in std_logic_vector(15 downto 0); --! Signed data input (two's complement)
data_o : out std_logic_vector(15 downto 0) --! Signed data output (two's complement)
);
......@@ -76,6 +78,11 @@ end entity offset_gain_s;
------------------------------------------------------------------------------
architecture rtl of offset_gain_s is
------------------------------------------------------------------------------
-- Constants declaration
------------------------------------------------------------------------------
constant c_one : signed(16 downto 0) := to_signed(1, 17);
------------------------------------------------------------------------------
-- Signals declaration
------------------------------------------------------------------------------
......@@ -83,7 +90,10 @@ architecture rtl of offset_gain_s is
signal data_in_d : std_logic_vector(15 downto 0) := (others => '0');
signal data_offset : std_logic_vector(17 downto 0) := (others => '0');
signal gain : std_logic_vector(17 downto 0) := (others => '0');
signal product : std_logic_vector(35 downto 0) := (others => '0');
signal product_t : std_logic_vector(35 downto 0) := (others => '0');
signal product : std_logic_vector(16 downto 0);
signal pos_sat : signed(16 downto 0);
signal neg_sat : signed(16 downto 0);
begin
......@@ -128,7 +138,7 @@ begin
WIDTH_A => 18, -- Multiplier A-input bus width, 1-25
WIDTH_B => 18) -- Multiplier B-input bus width, 1-18
port map (
P => product, -- Multiplier ouput, WIDTH_A+WIDTH_B
P => product_t, -- Multiplier ouput, WIDTH_A+WIDTH_B
A => gain, -- Multiplier input A, WIDTH_A
B => data_offset, -- Multiplier input B, WIDTH_B
CE => '1', -- 1-bit active high input clock enable
......@@ -136,23 +146,35 @@ begin
RST => rst -- 1-bit input active high reset
);
-- Additional register stage to solve timing issues
p_pipeline : process (clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
product <= (others => '0');
else
product <= product_t(31 downto 15);
end if;
end if;
end process p_pipeline;
------------------------------------------------------------------------------
-- Saturate addition and multiplication result
------------------------------------------------------------------------------
pos_sat <= signed("00" & sat_i);
neg_sat <= signed(not(pos_sat))+c_one;
p_saturate : process (clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
data_o <= (others => '0');
elsif signed(product) >= pos_sat then
data_o <= std_logic_vector(pos_sat(15 downto 0)); -- saturate positive
elsif signed(product) <= neg_sat then
data_o <= std_logic_vector(neg_sat(15 downto 0)); -- saturate negative
else
if (data_offset(15) = '1' and data_offset(16) = '0') then
data_o <= X"7FFF"; -- saturate positive
elsif (data_offset(15) = '0' and data_offset(16) = '1') then
data_o <= X"8000"; -- saturate negative
else
data_o <= product(30 downto 15);
end if;
data_o <= product(15 downto 0);
end if;
end if;
end process p_saturate;
......
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