From 1608f535f42dc4673edc79b62e1b035d272cbb72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Bron=C3=A8s?= <romain.brones@synchrotron-soleil.fr> Date: Thu, 26 Oct 2023 17:25:54 +0200 Subject: [PATCH] feat(average): Add orbit error and correction command moving average * Same generic bloc for operations * Capture the stream of data and retains accumulator in memory * Mirror memory for CPU readout wip: initial commit wip: Now a more generic bloc wip: Add average tables to RDL wip: integrate ma for oe in toplevel wip: first corrections for simulation, alpha declared in package wip: fixes for simulation wip: fixes, secondary memory is smaller, no decimal part wip: true rounding before wrinting to secondary memory wip: Add average for PSC command wip: fix sign extension on average orbit read --- hdl/moving_average.vhd | 177 ++++++++++++++++++++++++++++++++++++++++ hdl/pkg_corrmatrix.vhd | 5 ++ hdl/top_corr_matrix.vhd | 82 +++++++++++++++++++ rdl/corr_matrix.rdl | 21 +++++ tcl/main.tcl | 1 + 5 files changed, 286 insertions(+) create mode 100644 hdl/moving_average.vhd diff --git a/hdl/moving_average.vhd b/hdl/moving_average.vhd new file mode 100644 index 0000000..28b8670 --- /dev/null +++ b/hdl/moving_average.vhd @@ -0,0 +1,177 @@ +-- Block that compute a moving average from a AXIStream of data with ID +-- Results are published in a memory accessible from AXI-MM +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library desy; +use desy.ram_tdp; +use desy.math_signed.all; + +entity moving_average is + generic( + G_W_ID : natural; + G_W_SIGNAL : natural; + G_W_ALPHA : natural + ); + port( + clk : in std_logic; + rst_n : in std_logic; + + -- Moving average alpha + alpha : in signed(G_W_ALPHA-1 downto 0); + + -- Signal input + sig_data : in signed(G_W_SIGNAL-1 downto 0); + sig_id : in std_logic_vector(G_W_ID-1 downto 0); + sig_valid : in std_logic; + + -- AXI-MM Average signal table + asigt_en : in std_logic; + asigt_addr : in std_logic_vector(G_W_ID-1 downto 0); + asigt_rdata : out std_logic_vector(G_W_SIGNAL-1 downto 0) + ); +end entity moving_average; + +architecture rtl of moving_average is + + type arr_slv is array (natural range <>) of std_logic_vector; + + ------------------------ + -- SIGNAL DECLARATION -- + ------------------------ + signal table_wen : std_logic; + signal table_waddr : std_logic_vector(G_W_ID-1 downto 0); + signal table_wdata : std_logic_vector(G_W_SIGNAL+G_W_ALPHA-1 downto 0); + signal table_wdata_sec : std_logic_vector(G_W_SIGNAL-1 downto 0); + signal table_rdata : std_logic_vector(G_W_SIGNAL+G_W_ALPHA-1 downto 0); + + signal sig_id_r : arr_slv(0 to 2)(G_W_ID-1 downto 0); + signal sig_valid_r : std_logic_vector(0 to 2); + + signal pasig : signed(G_W_SIGNAL+G_W_ALPHA-1 downto 0); + + signal sig_alpha : signed(G_W_SIGNAL+G_W_ALPHA-1 downto 0); + signal sig_alpha_r : signed(G_W_SIGNAL+G_W_ALPHA-1 downto 0); + + signal pasig_alpha : signed(G_W_SIGNAL+G_W_ALPHA*2-1 downto 0); + signal pasig_alpha_rnd : signed(G_W_SIGNAL+G_W_ALPHA-1 downto 0); + signal ma_update : signed(G_W_SIGNAL+G_W_ALPHA-1 downto 0); + signal ma_new : signed(G_W_SIGNAL+G_W_ALPHA-1 downto 0); + signal ma_new_rnd : signed(G_W_SIGNAL-1 downto 0); + + +begin + + + -------------------------------- + -- AVERAGE ORBIT ERROR TABLES -- + -------------------------------- + -- main one, used for computation. A reads only, B writes only + + inst_asig_main_table: entity desy.ram_tdp + generic map( + G_ADDR => G_W_ID, + G_DATA => G_W_SIGNAL+G_W_ALPHA + ) + port map( + pi_clk_a => clk, + pi_en_a => '1', + pi_we_a => '0', + pi_addr_a => sig_id, + pi_data_a => (others => '0'), + po_data_a => table_rdata, + pi_clk_b => clk, + pi_en_b => '1', + pi_we_b => table_wen, + pi_addr_b => table_waddr, + pi_data_b => table_wdata, + po_data_b => open + ); + table_wdata <= std_logic_vector(ma_new); + + -- secondary one, used for axi access to result. A reads only, B writes only + -- B port is mirror of previous bloc + -- No need to retain decimal part + + inst_asig_sec_table: entity desy.ram_tdp + generic map( + G_ADDR => G_W_ID, + G_DATA => G_W_SIGNAL + ) + port map( + pi_clk_a => clk, + pi_en_a => asigt_en, + pi_we_a => '0', + pi_addr_a => asigt_addr, + pi_data_a => (others => '0'), + po_data_a => asigt_rdata, + pi_clk_b => clk, + pi_en_b => '1', + pi_we_b => table_wen, + pi_addr_b => table_waddr, + pi_data_b => table_wdata_sec, + po_data_b => open + ); + + -- Round before memorize + table_wdata_sec <= std_logic_vector(ma_new_rnd); + ma_new_rnd <= f_resize_lsb(ma_new, ma_new_rnd'length) when ma_new(G_W_ALPHA-1) = '0' else + f_sum_sat(f_resize_lsb(ma_new, ma_new_rnd'length), to_signed(1, ma_new_rnd'length)); + + + ------------------------ + -- PIPELINE REGISTERS -- + ------------------------ + p_pipe:process(clk, rst_n) + begin + if rst_n = '0' then + sig_id_r <= (others => (others => '0')); + sig_valid_r <= (others => '0'); + elsif rising_edge(clk) then + + sig_valid_r <= sig_valid & sig_valid_r(0 to sig_valid_r'right-1); + + sig_id_r(0) <= sig_id; + for I in 1 to sig_id_r'right loop + sig_id_r(I) <= sig_id_r(I-1); + end loop; + + end if; + end process; + + table_wen <= sig_valid_r(2); + table_waddr <= sig_id_r(2); + + + ----------------- + -- COMPUTATION -- + ----------------- + pasig <= signed(table_rdata); + pasig_alpha <= -pasig * alpha; + pasig_alpha_rnd <= f_resize_lsb(pasig_alpha, pasig_alpha_rnd'length) when pasig_alpha(G_W_ALPHA-1) = '0' else + f_sum_sat(f_resize_lsb(pasig_alpha, pasig_alpha_rnd'length), to_signed(1, pasig_alpha_rnd'length)); + + p_comp:process(clk, rst_n) + begin + if rst_n = '0' then + sig_alpha <= (others => '0'); + sig_alpha_r <= (others => '0'); + ma_update <= (others => '0'); + ma_new <= (others => '0'); + + elsif rising_edge(clk) then + + sig_alpha <= sig_data * alpha; + sig_alpha_r <= sig_alpha; + + ma_update <= f_sum_sat(pasig, pasig_alpha_rnd); + ma_new <= f_sum_sat(sig_alpha_r, ma_update); + + end if; + end process; + + + +end architecture; + diff --git a/hdl/pkg_corrmatrix.vhd b/hdl/pkg_corrmatrix.vhd index cda9122..7854f16 100644 --- a/hdl/pkg_corrmatrix.vhd +++ b/hdl/pkg_corrmatrix.vhd @@ -46,6 +46,11 @@ package pkg_corr_matrix is -- Serializer constant C_W_SER_CNT : natural := 7; -- natural(ceil(log2(real(C_N_MM_PSC)))); + -- Moving average + constant C_W_ALPHA : natural := 16; + constant C_ALPHA_OE : signed(C_W_ALPHA-1 downto 0) := x"0048"; -- 72 dec + constant C_ALPHA_CC : signed(C_W_ALPHA-1 downto 0) := x"0048"; -- 72 dec + ---------------------- -- TYPE DECLARATION -- ---------------------- diff --git a/hdl/top_corr_matrix.vhd b/hdl/top_corr_matrix.vhd index bcddbf7..7fc69a5 100644 --- a/hdl/top_corr_matrix.vhd +++ b/hdl/top_corr_matrix.vhd @@ -136,6 +136,60 @@ begin errbpm_tvalid => errbpm_tvalid ); + ------------------------- + -- ORBIT ERROR AVERAGE -- + ------------------------- + inst_orbit_error_avg_x: entity work.moving_average + generic map( + G_W_ID => C_W_MM_IDCNT, + G_W_SIGNAL => C_W_OE, + G_W_ALPHA => C_W_ALPHA + ) + port map( + clk => clk, + rst_n => rst_n, + + -- Moving average alpha + alpha => C_ALPHA_OE, + + -- Signal input + sig_data => errbpm_x, + sig_id => errbpm_id(C_W_MM_IDCNT-1 downto 0), + sig_valid => errbpm_tvalid, + + -- AXI-MM Average signal table + asigt_en => mm_a2l.ERRORBITX.en, + asigt_addr => mm_a2l.ERRORBITX.addr(C_W_MM_IDCNT-1 downto 0), + asigt_rdata => mm_l2a.ERRORBITX.data(C_W_OE-1 downto 0) + ); + mm_l2a.ERRORBITX.data(31 downto C_W_OE) <= (others => mm_l2a.ERRORBITX.data(C_W_OE-1)); + + inst_orbit_error_avg_y: entity work.moving_average + generic map( + G_W_ID => C_W_MM_IDCNT, + G_W_SIGNAL => C_W_OE, + G_W_ALPHA => C_W_ALPHA + ) + port map( + clk => clk, + rst_n => rst_n, + + -- Moving average alpha + alpha => C_ALPHA_OE, + + -- Signal input + sig_data => errbpm_y, + sig_id => errbpm_id(C_W_MM_IDCNT-1 downto 0), + sig_valid => errbpm_tvalid, + + -- AXI-MM Average signal table + asigt_en => mm_a2l.ERRORBITY.en, + asigt_addr => mm_a2l.ERRORBITY.addr(C_W_MM_IDCNT-1 downto 0), + asigt_rdata => mm_l2a.ERRORBITY.data(C_W_OE-1 downto 0) + ); + mm_l2a.ERRORBITY.data(31 downto C_W_OE) <= (others => mm_l2a.ERRORBITY.data(C_W_OE-1)); + + --------------------------- -- MATRIX MULTIPLICATION -- --------------------------- @@ -251,6 +305,34 @@ begin m_axis_tuser <= ser_tuser; m_axis_tvalid <= ser_tvalid; + ------------------------------- + -- CORRECTOR COMMAND AVERAGE -- + ------------------------------- + inst_corrector_command_avg: entity work.moving_average + generic map( + G_W_ID => C_W_PSCID, + G_W_SIGNAL => C_W_COR, + G_W_ALPHA => C_W_ALPHA + ) + port map( + clk => clk, + rst_n => rst_n, + + -- Moving average alpha + alpha => C_ALPHA_CC, + + -- Signal input + sig_data => ser_tdata(C_W_COR-1 downto 0), + sig_id => ser_tdata(C_W_PSCID+C_W_COR-1 downto C_W_COR), + sig_valid => ser_tvalid, + + -- AXI-MM Average signal table + asigt_en => mm_a2l.CORRCMD.en, + asigt_addr => mm_a2l.CORRCMD.addr(C_W_PSCID-1 downto 0), + asigt_rdata => mm_l2a.CORRCMD.data(C_W_COR-1 downto 0) + ); + mm_l2a.CORRCMD.data(31 downto C_W_COR ) <= (others => mm_l2a.CORRCMD.data(C_W_COR-1)); + -------------------------- -- THRESHOLD LEVEL COMP -- -------------------------- diff --git a/rdl/corr_matrix.rdl b/rdl/corr_matrix.rdl index aea7b59..db5f92f 100644 --- a/rdl/corr_matrix.rdl +++ b/rdl/corr_matrix.rdl @@ -113,6 +113,27 @@ addrmap corr_matrix { mementries = 2**`C_W_MM_IDCNT; } external MATRIXCOEF[`C_N_MM_PSC]; + mem { + desc = "X Average orbit error"; + sw=r; + memwidth = 32; + mementries = 2**`C_W_MM_IDCNT; + } external ERRORBITX; + + mem { + desc = "X Average orbit error"; + sw=r; + memwidth = 32; + mementries = 2**`C_W_MM_IDCNT; + } external ERRORBITY; + + mem { + desc = "Average correction, both planes"; + sw=r; + memwidth = 32; + mementries = 2**`C_W_PSCID; + } external CORRCMD; + }; diff --git a/tcl/main.tcl b/tcl/main.tcl index 616b592..5adc12e 100644 --- a/tcl/main.tcl +++ b/tcl/main.tcl @@ -24,6 +24,7 @@ proc setSources {} { lappend Sources {"../hdl/matrix_mul.vhd" "VHDL 2008"} lappend Sources {"../hdl/orbit_error.vhd" "VHDL 2008"} lappend Sources {"../hdl/data_serializer.vhd" "VHDL 2008"} + lappend Sources {"../hdl/moving_average.vhd" "VHDL 2008"} lappend Sources {"../hdl/top_corr_matrix.vhd" "VHDL 2008"} lappend Sources [list "${::fwfwk::LibPath}/desy_vhdl/hdl/memory/ram/ram_tdp.vhd" "VHDL 2008" "desy"] lappend Sources [list "${::fwfwk::LibPath}/desy_vhdl/hdl/math/pkg_math_utils.vhd" "VHDL 2008" "desy"] -- GitLab