Skip to content

Commit

Permalink
prbs_sp_distort.vhd: add distortion averaging
Browse files Browse the repository at this point in the history
In order to prevent our power supplies from saturating (hence
introducing non-linear behaviors, undesirable for our sytem
identification applications), moving average filters were added to
the PRBS-based distortion signal. These filters allow us to smooth the
power supply current setpoint transitions, which lowers the needed PI
control effort, (hopefully) keeping it in the linear operation range.
  • Loading branch information
guilhermerc committed Jun 26, 2023
1 parent 2648e8f commit b70ac28
Show file tree
Hide file tree
Showing 11 changed files with 274 additions and 66 deletions.
141 changes: 97 additions & 44 deletions hdl/modules/fofb_sys_id/cheby/doc/wb_fofb_sys_id_regs.html

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions hdl/modules/fofb_sys_id/cheby/wb_fofb_sys_id_regs.cheby
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,30 @@ memory-map:

write 0: distortion disabled
write 1: distortion enabled
- field:
name: sp_distort_mov_avg_num_taps_sel
range: 20-18
description: |
Selects the number of taps for averaging the setpoints
distortion. The number of taps being selected is given by
'2**sp_distort_mov_avg_num_taps_sel'.
NOTE: The maximum value for this field is given by
sp_distort_mov_avg_max_num_taps_sel_cte.

write 0x00: set number of taps to 1 (no averaging)
write 0x01: set number of taps to 2
write 0x02: set number of taps to 8
...
write sp_distort_mov_avg_max_num_taps_sel_cte : set number
of taps to 2**sp_distort_mov_avg_max_num_taps_sel_cte.
- reg:
name: sp_distort_mov_avg_max_num_taps_sel_cte
width: 8
access: ro
address: next
description: |
The maximum allowed value for prbs.ctl
sp_distort_mov_avg_num_taps_sel field.
- block:
name: sp_distort
description: Interface to setpoints distortion levels regs
Expand Down
16 changes: 14 additions & 2 deletions hdl/modules/fofb_sys_id/cheby/wb_fofb_sys_id_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@
#define WB_FOFB_SYS_ID_REGS_PRBS_CTL_LFSR_LENGTH_SHIFT 11
#define WB_FOFB_SYS_ID_REGS_PRBS_CTL_BPM_POS_DISTORT_EN 0x10000UL
#define WB_FOFB_SYS_ID_REGS_PRBS_CTL_SP_DISTORT_EN 0x20000UL
#define WB_FOFB_SYS_ID_REGS_PRBS_CTL_SP_DISTORT_MOV_AVG_NUM_TAPS_SEL_MASK 0x1c0000UL
#define WB_FOFB_SYS_ID_REGS_PRBS_CTL_SP_DISTORT_MOV_AVG_NUM_TAPS_SEL_SHIFT 18

/* The maximum allowed value for prbs.ctl
sp_distort_mov_avg_num_taps_sel field.
*/
#define WB_FOFB_SYS_ID_REGS_PRBS_SP_DISTORT_MOV_AVG_MAX_NUM_TAPS_SEL_CTE 0x1004UL

/* Interface to setpoints distortion levels regs */
#define WB_FOFB_SYS_ID_REGS_PRBS_SP_DISTORT 0x1040UL
Expand Down Expand Up @@ -98,8 +105,13 @@ struct wb_fofb_sys_id_regs {
*/
uint32_t ctl;

/* padding to: 16 words */
uint32_t __padding_0[15];
/* [0x4]: REG (ro) The maximum allowed value for prbs.ctl
sp_distort_mov_avg_num_taps_sel field.
*/
uint8_t sp_distort_mov_avg_max_num_taps_sel_cte;

/* padding to: 64 words */
uint8_t __padding_0[59];

/* [0x40]: BLOCK Interface to setpoints distortion levels regs */
struct sp_distort {
Expand Down
40 changes: 37 additions & 3 deletions hdl/modules/fofb_sys_id/cheby/wb_fofb_sys_id_regs.vhd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-- Do not edit. Generated on Mon May 08 18:02:08 2023 by guilherme.ricioli
-- Do not edit. Generated on Sat May 13 12:01:33 2023 by guilherme.ricioli
-- With Cheby 1.4.0 and these options:
-- -i wb_fofb_sys_id_regs.cheby --hdl vhdl --gen-hdl wb_fofb_sys_id_regs.vhd --doc html --gen-doc doc/wb_fofb_sys_id_regs.html --gen-c wb_fofb_sys_id_regs.h --consts-style vhdl-ohwr --gen-consts ../../../sim/regs/wb_fofb_sys_id_regs_consts_pkg.vhd

Expand Down Expand Up @@ -72,6 +72,25 @@ entity wb_fofb_sys_id_regs is
-- write 1: distortion enabled

prbs_ctl_sp_distort_en_o : out std_logic;
-- Selects the number of taps for averaging the setpoints
-- distortion. The number of taps being selected is given by
-- '2**sp_distort_mov_avg_num_taps_sel'.
-- NOTE: The maximum value for this field is given by
-- sp_distort_mov_avg_max_num_taps_sel_cte.

-- write 0x00: set number of taps to 1 (no averaging)
-- write 0x01: set number of taps to 2
-- write 0x02: set number of taps to 8
-- ...
-- write sp_distort_mov_avg_max_num_taps_sel_cte : set number
-- of taps to 2**sp_distort_mov_avg_max_num_taps_sel_cte.

prbs_ctl_sp_distort_mov_avg_num_taps_sel_o : out std_logic_vector(2 downto 0);

-- The maximum allowed value for prbs.ctl
-- sp_distort_mov_avg_num_taps_sel field.

prbs_sp_distort_mov_avg_max_num_taps_sel_cte_i : in std_logic_vector(7 downto 0);

-- Two signed 16-bit distortion levels in RTM-LAMP ADC
-- counts, one for each PRBS value.
Expand Down Expand Up @@ -278,6 +297,7 @@ architecture syn of wb_fofb_sys_id_regs is
signal prbs_ctl_lfsr_length_reg : std_logic_vector(4 downto 0);
signal prbs_ctl_bpm_pos_distort_en_reg : std_logic;
signal prbs_ctl_sp_distort_en_reg : std_logic;
signal prbs_ctl_sp_distort_mov_avg_num_taps_sel_reg : std_logic_vector(2 downto 0);
signal prbs_ctl_wreq : std_logic;
signal prbs_ctl_wack : std_logic;
signal prbs_sp_distort_ch_0_levels_level_0_reg : std_logic_vector(15 downto 0);
Expand Down Expand Up @@ -418,6 +438,7 @@ begin
prbs_ctl_lfsr_length_o <= prbs_ctl_lfsr_length_reg;
prbs_ctl_bpm_pos_distort_en_o <= prbs_ctl_bpm_pos_distort_en_reg;
prbs_ctl_sp_distort_en_o <= prbs_ctl_sp_distort_en_reg;
prbs_ctl_sp_distort_mov_avg_num_taps_sel_o <= prbs_ctl_sp_distort_mov_avg_num_taps_sel_reg;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
Expand All @@ -426,6 +447,7 @@ begin
prbs_ctl_lfsr_length_reg <= "00000";
prbs_ctl_bpm_pos_distort_en_reg <= '0';
prbs_ctl_sp_distort_en_reg <= '0';
prbs_ctl_sp_distort_mov_avg_num_taps_sel_reg <= "000";
prbs_ctl_wack <= '0';
else
if prbs_ctl_wreq = '1' then
Expand All @@ -434,12 +456,15 @@ begin
prbs_ctl_lfsr_length_reg <= wr_dat_d0(15 downto 11);
prbs_ctl_bpm_pos_distort_en_reg <= wr_dat_d0(16);
prbs_ctl_sp_distort_en_reg <= wr_dat_d0(17);
prbs_ctl_sp_distort_mov_avg_num_taps_sel_reg <= wr_dat_d0(20 downto 18);
end if;
prbs_ctl_wack <= prbs_ctl_wreq;
end if;
end if;
end process;

-- Register prbs_sp_distort_mov_avg_max_num_taps_sel_cte

-- Register prbs_sp_distort_ch_0_levels
prbs_sp_distort_ch_0_levels_level_0_o <= prbs_sp_distort_ch_0_levels_level_0_reg;
prbs_sp_distort_ch_0_levels_level_1_o <= prbs_sp_distort_ch_0_levels_level_1_reg;
Expand Down Expand Up @@ -750,6 +775,9 @@ begin
-- Reg prbs_ctl
prbs_ctl_wreq <= wr_req_d0;
wr_ack_int <= prbs_ctl_wack;
when "000000001" =>
-- Reg prbs_sp_distort_mov_avg_max_num_taps_sel_cte
wr_ack_int <= wr_req_d0;
when "000010000" =>
-- Reg prbs_sp_distort_ch_0_levels
prbs_sp_distort_ch_0_levels_wreq <= wr_req_d0;
Expand Down Expand Up @@ -811,7 +839,7 @@ begin
end process;

-- Process for read requests.
process (adr_int, rd_req_int, bpm_pos_flatenizer_ctl_base_bpm_id_reg, bpm_pos_flatenizer_max_num_cte_i, prbs_ctl_rst_reg, prbs_ctl_step_duration_reg, prbs_ctl_lfsr_length_reg, prbs_ctl_bpm_pos_distort_en_reg, prbs_ctl_sp_distort_en_reg, prbs_sp_distort_ch_0_levels_level_0_reg, prbs_sp_distort_ch_0_levels_level_1_reg, prbs_sp_distort_ch_1_levels_level_0_reg, prbs_sp_distort_ch_1_levels_level_1_reg, prbs_sp_distort_ch_2_levels_level_0_reg, prbs_sp_distort_ch_2_levels_level_1_reg, prbs_sp_distort_ch_3_levels_level_0_reg, prbs_sp_distort_ch_3_levels_level_1_reg, prbs_sp_distort_ch_4_levels_level_0_reg, prbs_sp_distort_ch_4_levels_level_1_reg, prbs_sp_distort_ch_5_levels_level_0_reg, prbs_sp_distort_ch_5_levels_level_1_reg, prbs_sp_distort_ch_6_levels_level_0_reg, prbs_sp_distort_ch_6_levels_level_1_reg, prbs_sp_distort_ch_7_levels_level_0_reg, prbs_sp_distort_ch_7_levels_level_1_reg, prbs_sp_distort_ch_8_levels_level_0_reg, prbs_sp_distort_ch_8_levels_level_1_reg, prbs_sp_distort_ch_9_levels_level_0_reg, prbs_sp_distort_ch_9_levels_level_1_reg, prbs_sp_distort_ch_10_levels_level_0_reg, prbs_sp_distort_ch_10_levels_level_1_reg, prbs_sp_distort_ch_11_levels_level_0_reg, prbs_sp_distort_ch_11_levels_level_1_reg, prbs_bpm_pos_distort_distort_ram_levels_int_dato, prbs_bpm_pos_distort_distort_ram_levels_rack) begin
process (adr_int, rd_req_int, bpm_pos_flatenizer_ctl_base_bpm_id_reg, bpm_pos_flatenizer_max_num_cte_i, prbs_ctl_rst_reg, prbs_ctl_step_duration_reg, prbs_ctl_lfsr_length_reg, prbs_ctl_bpm_pos_distort_en_reg, prbs_ctl_sp_distort_en_reg, prbs_ctl_sp_distort_mov_avg_num_taps_sel_reg, prbs_sp_distort_mov_avg_max_num_taps_sel_cte_i, prbs_sp_distort_ch_0_levels_level_0_reg, prbs_sp_distort_ch_0_levels_level_1_reg, prbs_sp_distort_ch_1_levels_level_0_reg, prbs_sp_distort_ch_1_levels_level_1_reg, prbs_sp_distort_ch_2_levels_level_0_reg, prbs_sp_distort_ch_2_levels_level_1_reg, prbs_sp_distort_ch_3_levels_level_0_reg, prbs_sp_distort_ch_3_levels_level_1_reg, prbs_sp_distort_ch_4_levels_level_0_reg, prbs_sp_distort_ch_4_levels_level_1_reg, prbs_sp_distort_ch_5_levels_level_0_reg, prbs_sp_distort_ch_5_levels_level_1_reg, prbs_sp_distort_ch_6_levels_level_0_reg, prbs_sp_distort_ch_6_levels_level_1_reg, prbs_sp_distort_ch_7_levels_level_0_reg, prbs_sp_distort_ch_7_levels_level_1_reg, prbs_sp_distort_ch_8_levels_level_0_reg, prbs_sp_distort_ch_8_levels_level_1_reg, prbs_sp_distort_ch_9_levels_level_0_reg, prbs_sp_distort_ch_9_levels_level_1_reg, prbs_sp_distort_ch_10_levels_level_0_reg, prbs_sp_distort_ch_10_levels_level_1_reg, prbs_sp_distort_ch_11_levels_level_0_reg, prbs_sp_distort_ch_11_levels_level_1_reg, prbs_bpm_pos_distort_distort_ram_levels_int_dato, prbs_bpm_pos_distort_distort_ram_levels_rack) begin
-- By default ack read requests
rd_dat_d0 <= (others => 'X');
prbs_bpm_pos_distort_distort_ram_levels_rreq <= '0';
Expand Down Expand Up @@ -841,7 +869,13 @@ begin
rd_dat_d0(15 downto 11) <= prbs_ctl_lfsr_length_reg;
rd_dat_d0(16) <= prbs_ctl_bpm_pos_distort_en_reg;
rd_dat_d0(17) <= prbs_ctl_sp_distort_en_reg;
rd_dat_d0(31 downto 18) <= (others => '0');
rd_dat_d0(20 downto 18) <= prbs_ctl_sp_distort_mov_avg_num_taps_sel_reg;
rd_dat_d0(31 downto 21) <= (others => '0');
when "000000001" =>
-- Reg prbs_sp_distort_mov_avg_max_num_taps_sel_cte
rd_ack_d0 <= rd_req_int;
rd_dat_d0(7 downto 0) <= prbs_sp_distort_mov_avg_max_num_taps_sel_cte_i;
rd_dat_d0(31 downto 8) <= (others => '0');
when "000010000" =>
-- Reg prbs_sp_distort_ch_0_levels
rd_ack_d0 <= rd_req_int;
Expand Down
4 changes: 3 additions & 1 deletion hdl/modules/fofb_sys_id/fofb_sys_id_pkg.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ package fofb_sys_id_pkg is
component prbs_sp_distort is
generic (
g_SP_WIDTH : natural := 15;
g_DISTORT_LEVEL_WIDTH : natural := 16
g_DISTORT_LEVEL_WIDTH : natural := 16;
g_MAX_ORDER_SEL : natural := 4
);
port (
clk_i : in std_logic;
Expand All @@ -96,6 +97,7 @@ package fofb_sys_id_pkg is
sp_valid_i : in std_logic;
distort_level_0_i : in signed(g_DISTORT_LEVEL_WIDTH-1 downto 0);
distort_level_1_i : in signed(g_DISTORT_LEVEL_WIDTH-1 downto 0);
order_sel_i : in natural range 0 to g_MAX_ORDER_SEL := 0;
distort_sp_o : out signed(g_SP_WIDTH-1 downto 0);
distort_sp_valid_o : out std_logic;
prbs_o : out std_logic;
Expand Down
76 changes: 66 additions & 10 deletions hdl/modules/fofb_sys_id/prbs_sp_distort.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
-- Date Version Author Description
-- 2023-04-17 1.0 guilherme.ricioli Created
-- 2023-04-19 1.1 guilherme.ricioli Wrap prbs_gen_for_sys_id
-- 2023-05-13 1.2 guilherme.ricioli Add distortion averaging
--------------------------------------------------------------------------------

library ieee;
Expand All @@ -33,7 +34,11 @@ entity prbs_sp_distort is
g_SP_WIDTH : natural := 15;

-- Width of distortion levels
g_DISTORT_LEVEL_WIDTH : natural := 16
g_DISTORT_LEVEL_WIDTH : natural := 16;

-- Moving average maximum order
-- The maximum order being selected is given by '2**g_MAX_ORDER_SEL - 1'
g_MAX_ORDER_SEL : natural := 4
);
port (
-- Clock
Expand Down Expand Up @@ -61,6 +66,8 @@ entity prbs_sp_distort is
prbs_lfsr_length_i : in natural range 2 to 32 := 32;

-- PRBS iteration signal
-- NOTE: The averaged distortion for the new PRBS value will be ready after
-- 4 clock cycles.
prbs_valid_i : in std_logic;

-- Setpoint
Expand All @@ -75,6 +82,10 @@ entity prbs_sp_distort is
-- Distortion level for PRBS value '1'
distort_level_1_i : in signed(g_DISTORT_LEVEL_WIDTH-1 downto 0);

-- Moving average order selector
-- The order being selected is given by '2**order_sel_i - 1'
order_sel_i : in natural range 0 to g_MAX_ORDER_SEL := 0;

-- Distorted setpoint
distort_sp_o : out signed(g_SP_WIDTH-1 downto 0);

Expand All @@ -91,13 +102,46 @@ end entity prbs_sp_distort;

architecture beh of prbs_sp_distort is
signal prbs : std_logic := '0';
signal prbs_valid : std_logic := '0';
signal distort : signed(g_DISTORT_LEVEL_WIDTH-1 downto 0) := (others => '0');
signal distort_valid : std_logic := '0';
signal avgd_distort : signed(g_DISTORT_LEVEL_WIDTH-1 downto 0) := (others => '0');
signal avgd_distort_valid : std_logic := '0';
signal avgd_distort_reg : signed(g_DISTORT_LEVEL_WIDTH-1 downto 0) := (others => '0');
signal sp_valid_d1 : std_logic := '0';
-- 1-bit larger than the largest between sp_i and distort_level_{0,1}_i
-- so to accomodate their sum
signal distort_sp_aux : signed(maximum(g_SP_WIDTH, g_DISTORT_LEVEL_WIDTH) downto 0);
begin
-- This process drives the PRBS distortion averaging.
-- After PRBS iteration, it selects the distortion level (based on PRBS
-- value), drives cmp_mov_avg_dyn with it and registers the averaged
-- distortion on avgd_distort_reg.
-- NOTE: The averaged distortion for a new PRBS value will be ready after 4
-- clock cycles:
-- 1 cc for muxing the distortion levels;
-- 2 cc for averaging the distortion; and
-- 1 cc for registering it.
p_drive_distort_averaging : process(clk_i) is
begin
distort_valid <= '0';
if prbs_valid = '1' then
if prbs = '0' then
distort <= distort_level_0_i;
else -- prbs_i = '1'
distort <= distort_level_1_i;
end if;
distort_valid <= '1';
elsif avgd_distort_valid = '1' then
avgd_distort_reg <= avgd_distort;
end if;
end process p_drive_distort_averaging;

process(clk_i) is
-- This process adds PRBS averaged distortion to the setpoint.
-- NOTE: There's no coordination between this process and
-- p_drive_distort_averaging. It simply uses the averaged distortion
-- registered on avgd_distort_reg.
p_add_avgd_distort : process(clk_i) is
-- 1-bit larger than the largest between sp_i and distort_level_{0,1}_i
-- This is done so there's no {over,under}flow on signed '+' operation
variable v_resized_sp : signed(maximum(g_SP_WIDTH, g_DISTORT_LEVEL_WIDTH) downto 0);
Expand All @@ -109,14 +153,10 @@ begin
else
v_resized_sp := resize(sp_i, maximum(g_SP_WIDTH, g_DISTORT_LEVEL_WIDTH)+1);

-- Pipeline stage 1 of 2: sum or bypass PRBS distortion
-- Pipeline stage 1 of 2: sum or bypass PRBS averaged distortion
-- #####################################################################
if en_distort_i = '1' then
if prbs = '0' then
distort_sp_aux <= v_resized_sp + distort_level_0_i;
else -- prbs_i = '1'
distort_sp_aux <= v_resized_sp + distort_level_1_i;
end if;
distort_sp_aux <= v_resized_sp + avgd_distort_reg;
else -- en_distort_i = '0'
distort_sp_aux <= v_resized_sp;
end if;
Expand All @@ -131,7 +171,7 @@ begin
-- #####################################################################
end if;
end if;
end process;
end process p_add_avgd_distort;

cmp_prbs_gen_for_sys_id : prbs_gen_for_sys_id
port map (
Expand All @@ -143,9 +183,25 @@ begin
valid_i => prbs_valid_i,
busy_o => open,
prbs_o => prbs,
valid_o => prbs_valid_o
valid_o => prbs_valid
);

cmp_mov_avg_dyn : mov_avg_dyn
generic map (
g_MAX_ORDER_SEL => g_MAX_ORDER_SEL,
g_DATA_WIDTH => g_DISTORT_LEVEL_WIDTH
)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
order_sel_i => order_sel_i,
data_i => distort,
valid_i => distort_valid,
avgd_data_o => avgd_distort,
valid_o => avgd_distort_valid
);

prbs_o <= prbs;
prbs_valid_o <= prbs_valid;

end architecture beh;
Loading

0 comments on commit b70ac28

Please sign in to comment.