Commit cedd8c67 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

dsp: rewrite gc_pi_regulator

parent 5e934bac
......@@ -10,119 +10,120 @@ use work.gc_cordic_pkg.all;
entity gc_pi_regulator is
generic (
g_DATA_BITS : positive := 24;
g_OUT_BITS : positive := 16;
g_OUT_SHIFT : integer := 12;
g_SETPOINT_SHIFT : integer := 8;
g_MUL_MIN : signed;
g_MUL_MAX : signed
g_DATA_BITS : positive := 24;
g_GAIN_BITS : integer := 16;
g_GAIN_FRAC_BITS : integer := 10;
g_INTEGRATOR_BITS : integer := 32;
g_OUTPUT_BITS : positive := 16
);
port (
clk_i : in std_logic;
rst_i : in std_logic;
enable_i : in std_logic;
integ_tick_i : in std_logic := '1';
setpoint_i : in std_logic_vector(15 downto 0);
setpoint_i : in std_logic_vector(g_DATA_BITS-1 downto 0);
x_i : in std_logic_vector(g_DATA_BITS-1 downto 0);
y_o : out std_logic_vector(g_OUT_BITS-1 downto 0);
p_y_o : out std_logic_vector(g_OUT_BITS-1 downto 0);
i_y_o : out std_logic_vector(g_OUT_BITS-1 downto 0);
x_valid_i : in std_logic;
x_i : in std_logic_vector(g_DATA_BITS-1 downto 0);
p_gain_i : in std_logic_vector(15 downto 0);
i_gain_i : in std_logic_vector(15 downto 0);
y_valid_o : out std_logic;
y_o : out std_logic_vector(g_OUTPUT_BITS-1 downto 0);
p_lim_o : out std_logic;
i_lim_o : out std_logic;
lim_o : out std_logic
kp_i : in std_logic_vector(g_GAIN_BITS-1 downto 0);
ki_i : in std_logic_vector(g_GAIN_BITS-1 downto 0);
lim_o : out std_logic
);
end gc_pi_regulator;
architecture rtl of gc_pi_regulator is
constant c_MUL_BITS : integer := g_DATA_BITS + g_OUT_BITS;
constant c_MUL_BITS : integer := g_DATA_BITS + g_GAIN_BITS + 1;
constant c_INTEG_MIN : signed(g_INTEGRATOR_BITS-1 downto 0) := to_signed(2**g_INTEGRATOR_BITS-1, g_INTEGRATOR_BITS);
constant c_INTEG_MAX : signed(g_INTEGRATOR_BITS-1 downto 0) := to_signed(-2**g_INTEGRATOR_BITS, g_INTEGRATOR_BITS);
constant c_OUT_MAX : signed(g_OUT_BITS -1 downto 0) := to_signed(2**g_OUT_BITS-1, g_OUT_BITS);
constant c_OUT_MIN : signed(g_OUT_BITS -1 downto 0) := to_signed(-2**g_OUT_BITS, g_OUT_BITS);
signal xerror : signed(g_DATA_BITS downto 0);
signal setpoint : signed(g_DATA_BITS downto 0);
signal pmul, imul : signed(c_MUL_BITS-1 downto 0);
signal integ : signed(g_INTEGRATOR_BITS-1 downto 0);
signal sum : signed(g_INTEGRATOR_BITS downto 0);
signal xerror : signed(g_DATA_BITS-1 downto 0);
signal setpoint : signed(g_DATA_BITS -1 downto 0);
signal xsw : signed(g_DATA_BITS-1 downto 0);
signal imul, pmul, iloop_d : signed(c_MUL_BITS-1 downto 0);
signal integ : signed(c_MUL_BITS-1 downto 0);
procedure f_clamp_add (
x : signed;
y : signed;
o : out signed;
limit : out std_logic) is
signal sum : signed(g_OUT_BITS+1 downto 0);
variable sum : signed(o'length downto 0);
constant c_min : signed(o'length downto 0) :=
to_signed( - (2**(o'length-1)), o'length+1 );
signal itrunc, ptrunc : signed(g_OUT_BITS-1 downto 0);
constant c_max : signed(o'length downto 0) :=
to_signed( (2**(o'length-1)) - 1, o'length+1 );
procedure f_clamp (x : signed; minval : signed; maxval : signed;
y : out signed; limit : out std_logic) is
begin
if(x > maxval) then
y := maxval;
sum := resize(x+y, sum'length);
if(sum > c_max) then
o := resize(c_max, o'length);
limit := '1';
elsif (x < minval) then
y := minval;
elsif (sum < c_min) then
o := resize(c_min, o'length);
limit := '1';
else
y := x;
o := sum(o'length-1 downto 0);
limit := '0';
end if;
end f_clamp;
end f_clamp_add;
function f_sra(x : signed; shift : integer; out_bits : integer) return signed is
variable ret : signed(out_bits-1 downto 0);
begin
ret := resize(x(x'length-1 downto shift), out_bits);
return ret;
end f_sra;
signal integ_limit_hit : std_logic;
begin
setpoint <= resize (signed(setpoint_i) & to_signed(0, g_SETPOINT_SHIFT), setpoint'length);
xsw <= signed(x_i) when enable_i = '1' else (others => '0');
xerror <= xsw - resize(signed(setpoint_i), xerror'length);
setpoint <= resize (signed(setpoint_i), setpoint'length);
xerror <= resize(signed(x_i), setpoint'length) - setpoint;
p_the_pi : process(clk_i)
variable iloop : signed(c_MUL_BITS-1 downto 0);
variable ploop : signed(c_MUL_BITS-1 downto 0);
variable ilim, plim : std_logic;
variable v_integ_next : signed(g_INTEGRATOR_BITS-1 downto 0);
variable v_integ_limit_hit : std_logic;
variable v_sum_next : signed(g_INTEGRATOR_BITS downto 0);
variable v_sum_limit_hit : std_logic;
begin
if rising_edge(clk_i) then
imul <= xerror * signed(i_gain_i);
pmul <= xerror * signed(p_gain_i);
f_limit_add(imul, integ, iloop, ilim);
if signed(i_gain_i) = 0 or rst_i = '1' then
integ <= (others => '0');
elsif integ_tick_i = '1' then
integ <= integ + iloop;
end if;
i_lim_o <= ilim;
f_clamp(pmul, g_MUL_MIN, g_MUL_MAX, ploop, plim);
ptrunc <= ploop(g_OUT_BITS + g_OUT_SHIFT - 1 downto g_OUT_SHIFT);
itrunc <= iloop(g_OUT_BITS + g_OUT_SHIFT - 1 downto g_OUT_SHIFT);
p_lim_o <= plim;
sum <= itrunc + ptrunc + signed(setpoint_i);
if sum > c_OUT_MAX then
y_o <= std_logic_vector(c_OUT_MAX);
lim_o <= '1';
elsif sum < c_OUT_MIN then
y_o <= std_logic_vector(c_OUT_MIN);
lim_o <= '1';
if rising_edge(clk_i) then
if rst_i = '1' then
y_o <= (others => '0');
y_valid_o <= '0';
integ <= (others => '0');
imul <= (others => '0');
pmul <= (others => '0');
else
y_o <= std_logic_vector(resize(sum, g_OUT_BITS));
lim_o <= '0';
if signed(ki_i) = 0 then
integ <= (others => '0');
elsif x_valid_i = '1' then
pmul <= resize(xerror * signed(kp_i), pmul'length);
imul <= resize(xerror * signed(ki_i), imul'length);
f_clamp_add(integ, imul, v_integ_next, v_integ_limit_hit);
integ <= v_integ_next;
f_clamp_add(integ, pmul, v_sum_next, v_sum_limit_hit);
y_o <= std_logic_vector(v_sum_next(g_OUTPUT_BITS + g_GAIN_FRAC_BITS - 1 downto g_GAIN_FRAC_BITS));
sum <= v_sum_next;
end if;
end if;
end if;
end process;
p_y_o <= std_logic_vector(ptrunc);
i_y_o <= std_logic_vector(itrunc);
end rtl;
......
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