Commit a8d5216b authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

dsp: new IPs - integer divide/remainder unit and soft ramping switch

parent cedd8c67
......@@ -14,4 +14,6 @@ files = ["cordic_init.vhd",
"gc_iq_modulator.vhd",
"gc_iq_rotate.vhd",
"gc_pi_regulator.vhd",
"gc_rate_limiter.vhd"];
"gc_rate_limiter.vhd",
"gc_soft_ramp_switch.vhd",
"gc_integer_divide.vhd"];
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity gc_integer_divide is
generic (
g_BITS : integer := 32)
(
clk_i : in std_logic;
rst_i : in std_logic;
is_rem_i : in std_logic;
is_signed_i : in std_logic;
a_i : in std_logic_vector(g_BITS-1 downto 0);
b_i : in std_logic_vector(g_BITS-1 downto 0);
q_o : out std_logic_vector(g_BITS-1 downto 0);
start_i : in std_logic;
ready_o : in std_logic;
done_o : out std_logic
);
end gc_integer_divide;
architecture rtl of gc_integer_divide is
signal state : unsigned(5 downto 0);
signal q, r, n, d : unsigned(g_BITS-1 downto 0);
signal n_sign, d_sign : std_logic;
signal alu_result : unsigned(g_BITS downto 0);
signal alu_op1, alu_op2, r_next : unsigned(g_BITS-1 downto 0);
signal alu_sub : std_logic;
signal is_rem, is_div_by_zero : std_logic;
begin
r_next <= r(g_BITS-1 downto 0) & n(g_BITS - (to_integer(state)-3));
p_alu_ops : process(state)
begin
case state is
when 0 =>
alu_op1 <= (others => 'X');
alu_op2 <= (others => 'X');
when 1 =>
alu_op1 <= (others => '0');
alu_op2 <= n;
when 2 =>
alu_op1 <= (others => '0');
alu_op2 <= d;
when g_BITS + 3 =>
alu_op1 <= (others => '0');
alu_op2 <= q;
when g_BITS + 4 =>
alu_op1 <= (others => '0');
alu_op2 <= r;
when others =>
alu_op1 <= r_next;
alu_op2 <= d;
end case;
end process;
p_alu : process(alu_sub, alu_op1, alu_op2)
begin
if alu_sub = '1' then
alu_result <= ('0'&alu_op1) - ('0'& alu_op2);
else
alu_result <= ('0'&alu_op1) + ('0'& alu_op2);
end if;
end process;
p_flags : process(alu_result, state, done, is_rem, busy, start_i)
begin
alu_ge <= not alu_result(g_BITS);
if alu_result = 0 then
alu_eq <= '1';
else
alu_eq <= '0';
end if;
if state = g_BITS + 5 and is_rem = '1' then
done <= '1';
elsif state = g_BITS + 4 and is_rem = '0' then
done <= '1';
else
done <= '0';
end if;
if state /= 0 and done = '0' then
busy <= '1';
else
busy <= '0';
end if;
start_divide <= start_i and not busy;
end process;
done_o <= done;
busy_o <= busy;
p_alu_select_op : process(state, n_sign, d_sign)
begin
case state is
when 1 =>
alu_sub <= n_sign;
when 2 =>
alu_sub <= d_sign;
when g_BITS + 3 =>
alu_sub <= n_sign xor d_sign;
when g_BITS + 4 =>
alu_sub <= n_sign;
when others =>
alu_sub <= '1';
end case;
end process;
p_state_counter : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_i = '1' or done = '1' then
state <= (others => '0');
elsif state /= 0 or start_divide = '1' then
state <= state + 1;
end if;
end if;
end process;
p_main : process(clk_i)
begin
if rising_edge(clk_i) then
case state is
when 0 =>
if start_divide = '1' then
is_div_by_zero <= '0';
q <= (others => '0');
r <= (others => '0');
is_rem <= is_rem_i;
n <= a_i;
d <= b_i;
if is_signed_i = '0' then
n_sign <= '0';
d_sign <= '0';
else
n_sign <= a_i(g_BITS-1);
d_sign <= b_i(g_BITS-1);
end if;
end if;
when 1 =>
n <= alu_result(g_BITS-1 downto 0);
when 2 =>
d <= alu_result(g_BITS-1 downto 0);
is_div_by_zero <= alu_eq and not (is_rem_i or is_signed_i);
when g_BITS + 3 =>
q_o <= alu_result(g_BITS-1 downto 0);
when g_BITS + 4 =>
q_o <= alu_result(g_BITS-1 downto 0);
when others => -- 3..g_BITS+2 (g_BITS) divider iterations
q <= q(g_BITS-2 downto 0) & alu_ge;
if alu_ge = '1' then
r <= alu_result;
else
r <= r_next;
end if;
end case;
end if;
end process;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.gencores_pkg.all;
entity gc_soft_ramp_switch is
generic (
g_DATA_BITS : positive := 16;
g_NUM_CHANNELS : integer range 1 to 2 := 2
);
port (
clk_i : in std_logic;
rst_i : in std_logic;
rate_i : in std_logic_vector(15 downto 0);
on_i : in std_logic;
is_on_o : out std_logic;
is_off_o : out std_logic;
busy_o : out std_logic;
x_valid_i : in std_logic;
x0_i : in std_logic_vector(g_DATA_BITS-1 downto 0);
x1_i : in std_logic_vector(g_DATA_BITS-1 downto 0) := (others => '0');
x2_i : in std_logic_vector(g_DATA_BITS-1 downto 0) := (others => '0');
x3_i : in std_logic_vector(g_DATA_BITS-1 downto 0) := (others => '0');
y_valid_o : out std_logic;
y0_o : out std_logic_vector(g_DATA_BITS-1 downto 0);
y1_o : out std_logic_vector(g_DATA_BITS-1 downto 0);
y2_o : out std_logic_vector(g_DATA_BITS-1 downto 0);
y3_o : out std_logic_vector(g_DATA_BITS-1 downto 0)
);
end gc_soft_ramp_switch;
architecture rtl of gc_soft_ramp_switch is
type t_SIG_ARRAY is array(0 to 3) of signed(g_DATA_BITS-1 downto 0);
constant c_MUL_BITS : integer := g_DATA_BITS + 18;
constant c_RAMP_INTEG_BITS : integer := 24;
type t_STATE is (SW_OFF, SW_RAMP_UP, SW_ON, SW_RAMP_DOWN);
signal ramp_integ : unsigned(c_RAMP_INTEG_BITS-1 downto 0);
signal state : t_STATE;
signal mulf : unsigned(17 downto 0);
signal xi, yo : t_SIG_ARRAY;
function f_mul_sar(x : signed; y : unsigned; outbits : integer) return signed is
variable tmp : signed(x'length + y'length downto 0);
begin
tmp := x * signed('0'&y);
return tmp(tmp'length-3 downto tmp'length - outbits-2);
end f_mul_sar;
begin
p_switch : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_i = '1' then
state <= SW_OFF;
ramp_integ <= (others => '0');
is_off_o <= '1';
is_on_o <= '0';
busy_o <= '0';
else
case state is
when SW_OFF =>
is_off_o <= '1';
busy_o <= '0';
if on_i = '1' then
ramp_integ <= (others => '0');
state <= SW_RAMP_UP;
end if;
when SW_RAMP_UP =>
busy_o <= '1';
is_off_o <= '0';
if ramp_integ(ramp_integ'length-1) = '1' then
state <= SW_ON;
end if;
ramp_integ <= ramp_integ + unsigned(rate_i);
when SW_ON =>
ramp_integ <= to_unsigned(2**(c_RAMP_INTEG_BITS-1), c_RAMP_INTEG_BITS);
busy_o <= '0';
is_on_o <= '1';
if on_i = '0' then
state <= SW_RAMP_DOWN;
end if;
when SW_RAMP_DOWN =>
is_on_o <= '0';
busy_o <= '1';
if(ramp_integ < unsigned(rate_i)) then
ramp_integ <= (others => '0');
state <= SW_OFF;
else
ramp_integ <= ramp_integ - unsigned(rate_i);
end if;
end case;
end if;
end if;
end process;
xi(0) <= signed(x0_i);
xi(1) <= signed(x1_i);
xi(2) <= signed(x2_i);
xi(3) <= signed(x3_i);
y0_o <= std_logic_vector(yo(0));
y1_o <= std_logic_vector(yo(1));
y2_o <= std_logic_vector(yo(2));
y3_o <= std_logic_vector(yo(3));
p_mulf : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_i = '1' then
y_valid_o <= '0';
mulf <= (others => '0');
else
mulf <= ramp_integ(ramp_integ'length-1 downto ramp_integ'length - 18);
y_valid_o <= x_valid_i;
for i in 0 to g_NUM_CHANNELS loop
yo(i) <= f_mul_sar(xi(i), mulf, g_DATA_BITS);
end loop;
end if;
end if;
end process;
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