Commit f0e7c402 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

modules/dsp: a collection of simple DSP cores from the SY-RF-FB's CommonVisual library.

Note: mostly untested code. Licensing to be fixed.
parent dd3a22e8
......@@ -4,6 +4,7 @@ modules = {
"modules/common",
"modules/genrams",
"modules/wishbone",
"modules/dsp",
"modules/radtol",
"platform"
]
......
files = ["cordic_init.vhd",
"cordic_modulo_360.vhd",
"cordic_xy_logic_hd.vhd",
"cordic_xy_logic_nhd.vhd",
"cordic_xy_logic_nmhd.vhd",
"gc_averager_decimator.vhd",
"gc_cordic_pkg.vhd",
"gc_cordic.vhd",
#"gc_frequency_detector.vhd",
"gc_iq_amplitude_limiter.vhd",
"gc_iq_demodulator.vhd",
"gc_iq_modulator.vhd",
"gc_iq_rotate.vhd",
"gc_pi_regulator.vhd",
"gc_rate_limiter.vhd"];
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.numeric_std.all;
library work;
use work.gc_cordic_pkg.all;
entity cordic_init is
generic
(
g_M : positive := 16;
-- Default angle format S8.7 otherwise FS = 180 deg.
g_ANGLE_MODE : t_CORDIC_ANGLE_FORMAT := S8_7
);
port (
clk_i : in std_logic;
rst_i : in std_logic;
cor_mode_i : in t_CORDIC_MODE;
cor_submode_i : in t_CORDIC_SUBMODE;
x0_i : in std_logic_vector(g_M - 1 downto 0);
y0_i : in std_logic_vector(g_M - 1 downto 0);
z0_i : in std_logic_vector(g_M downto 0);
x1_o : out std_logic_vector(g_M - 1 downto 0);
y1_o : out std_logic_vector(g_M - 1 downto 0);
z1_o : out std_logic_vector(g_M downto 0);
d1_o : out std_logic
);
end cordic_init;
architecture rtl of cordic_init is
signal x0_int, y0_int, x1_int, y1_int : signed (g_M-1 downto 0);
signal z0_int, z1_int : signed (g_M downto 0);
signal d1_int : std_logic;
begin
process (clk_i)
begin
if rising_edge(clk_i) then
if rst_i = '1' then
x1_int <= x0_int;
y1_int <= y0_int;
z1_int <= z0_int;
d1_int <= '0';
else
x1_int <= x0_int;
y1_int <= y0_int;
z1_int <= z0_int;
d1_int <= '1';
if cor_mode_i = VECTOR and cor_submode_i = CIRCULAR then
if x0_int >= c_DegZeroHD(31 downto 31 - (g_M - 1)) and
y0_int >= c_DegZeroHD(31 downto 31 - (g_M - 1)) then
x1_int <= x0_int;
y1_int <= y0_int;
z1_int <= z0_int;
d1_int <= '0';
elsif x0_int >= c_DegZeroHD(31 downto 31 - (g_M - 1)) and
y0_int < c_DegZeroHD(31 downto 31 - (g_M - 1)) then
x1_int <= x0_int;
y1_int <= y0_int;
z1_int <= z0_int;
d1_int <= '1';
elsif g_ANGLE_MODE = S8_7 and
x0_int < c_DegZeroHD(31 downto 31 - (g_M - 1)) and
y0_int >= c_DegZeroHD(31 downto 31 - (g_M - 1)) then
x1_int <= y0_int;
y1_int <= -x0_int; -- not (X0) + 1;
z1_int <= c_DegPlus90HD_X(32 downto 32 - g_M) + z0_int;
d1_int <= '0';
elsif g_ANGLE_MODE = S8_7 and
x0_int < c_DegZeroHD(31 downto 31 - (g_M - 1)) and
y0_int < c_DegZeroHD(31 downto 31 - (g_M - 1)) then
x1_int <= -y0_int; -- not (Y0) + 1;
y1_int <= x0_int;
z1_int <= c_DegMinus90HD_X(32 downto 32 - g_M) + z0_int;
d1_int <= '1';
elsif g_ANGLE_MODE = FULL_SCALE_180 and
x0_int < c_FSDegZeroHD(31 downto 31 - (g_M - 1)) and
y0_int >= c_FSDegZeroHD(31 downto 31 - (g_M - 1)) then
x1_int <= y0_int;
y1_int <= -x0_int; -- not (X0) + 1;
z1_int <= c_FSDegPlus90HD_X(32 downto 32 - g_M) + z0_int;
d1_int <= '0';
elsif g_ANGLE_MODE = FULL_SCALE_180 and
x0_int < c_FSDegZeroHD(31 downto 31 - (g_M - 1)) and
y0_int < c_FSDegZeroHD(31 downto 31 - (g_M - 1)) then
x1_int <= -y0_int; -- not (Y0) + 1;
y1_int <= x0_int;
z1_int <= c_FSDegMinus90HD_X(32 downto 32 - g_M) + z0_int;
d1_int <= '1';
end if;
elsif cor_mode_i = ROTATE and cor_submode_i = CIRCULAR then
if g_ANGLE_MODE = S8_7 and
z0_int <= c_DegPlus90HD_X(32 downto 32 - g_M) and
z0_int >= c_DegZeroHD_X(32 downto 32 - g_M) then
x1_int <= x0_int;
y1_int <= y0_int;
z1_int <= z0_int;
d1_int <= '1';
elsif g_ANGLE_MODE = S8_7 and
z0_int < c_DegZeroHD_X(32 downto 32 - g_M) and
z0_int >= c_DegMinus90HD_X(32 downto 32 - g_M) then
x1_int <= x0_int;
y1_int <= y0_int;
z1_int <= z0_int;
d1_int <= '0';
elsif g_ANGLE_MODE = S8_7 and
z0_int < c_DegMinus90HD_X(32 downto 32 - g_M) and
z0_int >= c_DegMinus180HD_X(32 downto 32 - g_M) then
x1_int <= y0_int;
y1_int <= -x0_int; -- not (X0) + 1;
z1_int <= c_DegPlus90HD_X(32 downto 32 - g_M) + z0_int;
d1_int <= '0';
elsif g_ANGLE_MODE = S8_7 and
z0_int <= c_DegPlus180HD_X(32 downto 32 - g_M) and
z0_int > c_DegPlus90HD_X(32 downto 32 - g_M) then
x1_int <= -y0_int; --not (Y0) + 1;
y1_int <= x0_int;
z1_int <= c_DegMinus90HD_X(32 downto 32 - g_M) + z0_int;
d1_int <= '1';
elsif g_ANGLE_MODE = S8_7 and
z0_int < c_DegMinus180HD_X(32 downto 32 - g_M) then
x1_int <= -x0_int; --not (X0) + 1;
y1_int <= -y0_int; --not (Y0) + 1;
z1_int <= c_DegPlus180HD_X(32 downto 32 - g_M) + z0_int;
d1_int <= '0';
elsif g_ANGLE_MODE = S8_7 and
z0_int > c_DegPlus180HD_X(32 downto 32 - g_M) then
x1_int <= -x0_int; -- not (X0) + 1;
y1_int <= -y0_int; --not (Y0) + 1;
z1_int <= c_DegMinus180HD_X(32 downto 32 - g_M) + z0_int;
d1_int <= '1';
elsif g_ANGLE_MODE = FULL_SCALE_180 and
z0_int <= c_FSDegPlus90HD_X(32 downto 32 - g_M) and
z0_int >= c_FSDegZeroHD_X(32 downto 32 - g_M) then
x1_int <= x0_int;
y1_int <= y0_int;
z1_int <= z0_int;
d1_int <= '1';
elsif g_ANGLE_MODE = FULL_SCALE_180 and
z0_int < c_FSDegZeroHD_X(32 downto 32 - g_M) and
z0_int >= c_FSDegMinus90HD_X(32 downto 32 - g_M) then
x1_int <= x0_int;
y1_int <= y0_int;
z1_int <= z0_int;
d1_int <= '0';
elsif g_ANGLE_MODE = FULL_SCALE_180 and
z0_int < c_FSDegMinus90HD_X(32 downto 32 - g_M) and
z0_int >= c_FSDegMinus180HD_X(32 downto 32 - g_M) then
x1_int <= y0_int;
y1_int <= -x0_int; --not (X0) + 1;
z1_int <= c_FSDegPlus90HD_X(32 downto 32 - g_M) + z0_int;
d1_int <= '0';
elsif g_ANGLE_MODE = FULL_SCALE_180 and
z0_int <= c_FSDegPlus180HD_X(32 downto 32 - g_M) and
z0_int > c_FSDegPlus90HD_X(32 downto 32 - g_M) then
x1_int <= -y0_int; --not (Y0) + 1;
y1_int <= x0_int;
z1_int <= c_FSDegMinus90HD_X(32 downto 32 - g_M) + z0_int;
d1_int <= '1';
elsif g_ANGLE_MODE = FULL_SCALE_180 and
z0_int < c_FSDegMinus180HD_X(32 downto 32 - g_M) then
x1_int <= -x0_int; --not (X0) + 1;
y1_int <= -y0_int; --not (Y0) + 1;
z1_int <= c_FSDegPlus180HD_X(32 downto 32 - g_M) + z0_int;
d1_int <= '0';
elsif g_ANGLE_MODE = FULL_SCALE_180 and
z0_int > c_FSDegPlus180HD_X(32 downto 32 - g_M) then
x1_int <= -x0_int; --not (X0) + 1;
y1_int <= -y0_int; --not (Y0) + 1;
z1_int <= c_FSDegMinus180HD_X(32 downto 32 - g_M) + z0_int;
d1_int <= '1';
end if;
elsif cor_mode_i = VECTOR and cor_submode_i = LINEAR then
if y0_int >= c_DegZeroHD(31 downto 31 - (g_M - 1)) then
x1_int <= x0_int;
y1_int <= y0_int;
z1_int <= z0_int;
d1_int <= '0';
elsif
y0_int < c_DegZeroHD(31 downto 31 - (g_M - 1)) then
x1_int <= x0_int;
y1_int <= y0_int;
z1_int <= z0_int;
d1_int <= '1';
end if;
elsif cor_mode_i = ROTATE and cor_submode_i = LINEAR then
if z0_int >= c_DegZeroHD_X(32 downto 32 - g_M) then
x1_int <= x0_int;
y1_int <= y0_int;
z1_int <= z0_int;
d1_int <= '1';
elsif z0_int < c_DegZeroHD_X(32 downto 32 - g_M) then
x1_int <= x0_int;
y1_int <= y0_int;
z1_int <= z0_int;
d1_int <= '0';
end if;
end if;
end if;
end if;
end process;
end rtl;
-- Angle normalization (Mod-360 degree)
-- If the angle_i argument is greater or smaller than +/-180deg.
-- the system subtracts or adds 360 degrees such that the result
-- lies again within the +/-180 degree range.
-- The number of g_M is by default 16 and can be max. 32 bit number.
-- Within the 32-bit range the number will correctly fit within a sign,
-- 8b Mantissa & 23b Fractional part. Changing the value g_M will only affect
-- to the fractional bits. This option can be selected with the g_ANGLE_MODE to
-- S8_7.
-- On the other hand, when the generic value g_ANGLE_MODE is set to FULL_SCALE the
-- modulo360 block can be used with an angle format maximum of Q1.31 with a sign
-- extension. This format gives a normalized signed representation with fixed
-- fractional bits according to the value of g_M. Changing the value of g_M will
-- affect to the amount of fractional bits. Full-scale format 180 degrees is
-- acquired in this way.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.gc_cordic_pkg.all;
entity cordic_modulo_360 is
generic(
g_M : positive := 16;
g_ANGLE_MODE : t_CORDIC_ANGLE_FORMAT
);
port (
cor_submode_i : in t_CORDIC_SUBMODE;
angle_i : in std_logic_vector(g_M downto 0);
angle_o : out std_logic_vector(g_M-1 downto 0);
lim_o : out std_logic
);
end entity;
architecture rtl of cordic_modulo_360 is
signal gt, lt : std_logic;
constant c_M180D : signed(g_M downto 0) :=
f_pick(g_ANGLE_MODE = S8_7, c_DegMinus180HD_X(32 downto 32 - g_M), c_FSDegMinus180HD_X(32 downto 32-g_M));
constant c_P180D : signed(g_M downto 0) :=
f_pick(g_ANGLE_MODE = S8_7, c_DegPlus180HD_X(32 downto 32 - g_M), c_FSDegPlus180HD_X(32 downto 32-g_M));
constant c_OFFS_ZERO : signed(g_M downto 0) :=
f_pick(g_ANGLE_MODE = S8_7, c_DegZeroHD_X(32 downto 32 - g_M), c_FSDegZeroHD_X(32 downto 32 - g_M));
constant c_OFFS_P360D : signed(g_M downto 0) :=
f_pick(g_ANGLE_MODE = S8_7, c_DegPlus360HD_X(32 downto 32 - g_M), c_FSDegPlus360HD_X(32 downto 32 - g_M));
constant c_OFFS_N360D : signed(g_M downto 0) :=
f_pick(g_ANGLE_MODE = S8_7, c_DegMinus360HD_X(32 downto 32 - g_M), c_FSDegMinus360HD_X(32 downto 32 - g_M));
begin
process(angle_i)
begin
if signed(angle_i) < c_M180D then
lt <= '1';
else
lt <= '0';
end if;
if signed(angle_i) > c_P180D then
gt <= '1';
else
gt <= '0';
end if;
end process;
process(lt, gt, angle_i, cor_submode_i)
variable angle_out : signed(g_M downto 0);
variable lim_out : std_logic;
begin
if cor_submode_i = CIRCULAR then
if(lt = '1' and gt = '0') then
f_limit_add(signed(angle_i), c_OFFS_P360D, angle_out, lim_out);
elsif (lt = '0' and gt = '1') then
f_limit_add(signed(angle_i), c_OFFS_N360D, angle_out, lim_out);
else
f_limit_add(signed(angle_i), c_OFFS_ZERO, angle_out, lim_out);
end if;
else
f_limit_add(signed(angle_i), to_signed(0, g_M), angle_out, lim_out);
end if;
angle_o <= std_logic_vector(angle_out(g_M-1 downto 0));
lim_o <= lim_out;
end process;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.gc_cordic_pkg.all;
entity cordic_xy_logic_hd is
generic(
g_M : positive := 16;
g_J : integer := 0
);
port (
clk_i : in std_logic;
rst_i : in std_logic;
cor_submode_i : in t_CORDIC_SUBMODE;
d_i : in std_logic;
fi_i : in std_logic_vector(g_m-1 downto 0);
lim_x_i : in std_logic;
lim_y_i : in std_logic;
xi_i : in std_logic_vector(g_M-1 downto 0);
yi_i : in std_logic_vector(g_M-1 downto 0);
zi_i : in std_logic_vector(g_M downto 0);
xj_o : out std_logic_vector(g_M-1 downto 0);
yj_o : out std_logic_vector(g_M-1 downto 0);
zj_o : out std_logic_vector(g_M downto 0);
lim_x_o : out std_logic;
lim_y_o : out std_logic;
rst_o : out std_logic
);
end entity;
architecture rtl of cordic_xy_logic_hd is
function f_shift(
vin : signed;
m : integer;
j : integer) return signed is
begin
if j < m - 2 then
return resize(vin(m-1 downto j), m);
else
return to_signed(0, m);
end if;
end f_shift;
signal xi_shifted : signed(g_M -1 downto 0);
signal yi_shifted : signed(g_M -1 downto 0);
signal rst_l, rst_d : std_logic;
begin
xi_shifted <= f_shift(signed(xi_i), g_M, g_J);
yi_shifted <= f_shift(signed(yi_i), g_M, g_J);
p_reset : process(clk_i)
begin
if rising_edge(clk_i) then
rst_d <= rst_i;
end if;
end process;
rst_l <= rst_d or rst_i;
process(clk_i)
variable xi_muxed : signed(g_M-1 downto 0);
variable yi_muxed : signed(g_M-1 downto 0);
variable fi_inv : signed(g_M-1 downto 0);
variable xj_comb : signed(g_M-1 downto 0);
variable yj_comb : signed(g_M-1 downto 0);
variable zj_comb : signed(g_M downto 0);
variable xj_limit : std_logic;
variable yj_limit : std_logic;
begin
if rising_edge(clk_i) then
if rst_l = '1' then
xj_o <= (others => '0');
yj_o <= (others => '0');
zj_o <= (others => '0');
lim_x_o <= '0';
lim_y_o <= '0';
else
case cor_submode_i is
when LINEAR =>
-- scntrl = 1, updmode = 0
yi_muxed := (others => '0');
-- scntrl = 1, updmode = 1
when CIRCULAR =>
yi_muxed := f_limit_negate(yi_shifted, not d_i);
-- scntrl = 0, updmode = 1
when HYPERBOLIC =>
yi_muxed := f_limit_negate(yi_shifted, d_i);
end case;
xi_muxed := f_limit_negate(xi_shifted, not d_i);
f_limit_subtract(signed(xi_i), yi_muxed, xj_comb, xj_limit);
f_limit_add(signed(yi_i), xi_muxed, yj_comb, yj_limit);
fi_inv := f_limit_negate( signed(fi_i), not d_i );
zj_comb := signed(zi_i) - fi_inv;
xj_o <= std_logic_vector(xj_comb);
yj_o <= std_logic_vector(yj_comb);
zj_o <= std_logic_vector(zj_comb);
lim_x_o <= lim_x_i or xj_limit;
lim_y_o <= lim_y_i or yj_limit;
end if;
end if;
end process;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.gc_cordic_pkg.all;
entity cordic_xy_logic_nhd is
generic(
g_M : positive := 16;
g_J : integer := 0;
g_I : integer := 0;
g_ANGLE_MODE : t_CORDIC_ANGLE_FORMAT
);
port (
clk_i : in std_logic;
rst_i : in std_logic;
cor_submode_i : in t_CORDIC_SUBMODE;
cor_mode_i : in t_CORDIC_MODE;
lim_x_i : in std_logic;
lim_y_i : in std_logic;
xi_i : in std_logic_vector(g_M-1 downto 0);
yi_i : in std_logic_vector(g_M-1 downto 0);
zi_i : in std_logic_vector(g_M downto 0);
xj_o : out std_logic_vector(g_M-1 downto 0);
yj_o : out std_logic_vector(g_M-1 downto 0);
zj_o : out std_logic_vector(g_M downto 0);
lim_x_o : out std_logic;
lim_y_o : out std_logic;
rst_o : out std_logic
);
end entity;
architecture rtl of cordic_xy_logic_nhd is
function f_shift(
vin : signed;
m : integer;
j : integer) return signed is
begin
if j < m - 2 then
return resize(vin(m-1 downto j), m);
else
return to_signed(0, m);
end if;
end f_shift;
signal xi_shifted : signed(g_M -1 downto 0);
signal yi_shifted : signed(g_M -1 downto 0);
signal fi : signed(g_M-1 downto 0);
signal di_int : std_logic;
signal rst_l, rst_d : std_logic;
begin
fi <= f_phi_lookup( g_I, cor_submode_i, g_ANGLE_MODE )(g_M-1 downto 0);
xi_shifted <= f_shift(signed(xi_i), g_M, g_J);
yi_shifted <= f_shift(signed(yi_i), g_M, g_J);
p_gen_di: process(cor_mode_i, yi_i, zi_i)
begin
di_int <= '0';
if cor_mode_i = VECTOR then
di_int <= yi_i(g_M-1);
else
di_int <= zi_i(g_M);
end if;
end process;
p_reset : process(clk_i)
begin
if rising_edge(clk_i) then
rst_d <= rst_i;
end if;
end process;
rst_l <= rst_d or rst_i;
p_pipe: process(clk_i)
variable xi_muxed : signed(g_M-1 downto 0);
variable yi_muxed : signed(g_M-1 downto 0);
variable fi_inv : signed(g_M-1 downto 0);
variable xj_comb : signed(g_M-1 downto 0);
variable yj_comb : signed(g_M-1 downto 0);
variable zj_comb : signed(g_M downto 0);
variable xj_limit : std_logic;
variable yj_limit : std_logic;
begin
if rising_edge(clk_i) then
if rst_l = '1' then
xj_o <= (others => '0');
yj_o <= (others => '0');
zj_o <= (others => '0');
lim_x_o <= '0';
lim_y_o <= '0';
else
case cor_submode_i is
when LINEAR =>
-- scntrl = 1, updmode = 0
yi_muxed := (others => '0');
when CIRCULAR =>
-- scntrl = 1, updmode = 1
yi_muxed := f_limit_negate(yi_shifted, not di_int);
when HYPERBOLIC =>
-- scntrl = 0, updmode = 1
yi_muxed := f_limit_negate(yi_shifted, di_int);
end case;
xi_muxed := f_limit_negate(xi_shifted, not di_int);
f_limit_subtract(signed(xi_i), yi_muxed, xj_comb, xj_limit);
f_limit_add(signed(yi_i), xi_muxed, yj_comb, yj_limit);
fi_inv := f_limit_negate( signed(fi), not di_int );
zj_comb := signed(zi_i) - fi_inv;
xj_o <= std_logic_vector(xj_comb);
yj_o <= std_logic_vector(yj_comb);
zj_o <= std_logic_vector(zj_comb);
lim_x_o <= lim_x_i or xj_limit;
lim_y_o <= lim_y_i or yj_limit;
end if;
end if;
end process;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.gc_cordic_pkg.all;
entity cordic_xy_logic_nmhd is
generic(
-- Number of XYlogicNHD cells instantiated
g_N : positive := 12;
--M = Word-width (maximum = 32)
g_M : positive := 16;
--AngleMode = Default angle format S8.7 otherwise FS = 180 deg.
g_ANGLE_MODE : t_CORDIC_ANGLE_FORMAT := S8_7
);
port (
clk_i : in std_logic;
rst_i : in std_logic;
cor_mode_i : in t_CORDIC_MODE;
cor_submode_i : in t_CORDIC_SUBMODE;
d_i : in std_logic;
fi1_i : in std_logic_vector(g_m-1 downto 0);
lim_x_i : in std_logic;
lim_y_i : in std_logic;
xi_i : in std_logic_vector(g_M-1 downto 0);
yi_i : in std_logic_vector(g_M-1 downto 0);
zi_i : in std_logic_vector(g_M downto 0);
xj_o : out std_logic_vector(g_M-1 downto 0);
yj_o : out std_logic_vector(g_M-1 downto 0);
zj_o : out std_logic_vector(g_M downto 0);
lim_x_o : out std_logic;
lim_y_o : out std_logic;
rst_o : out std_logic
);
end entity;
architecture rtl of cordic_xy_logic_nmhd is
type t_xy_bus is array (0 to g_N-2) of std_logic_vector(g_M-1 downto 0);
type t_z_bus is array (0 to g_N-2) of std_logic_vector(g_M downto 0);
signal loc_Rst : std_logic_vector(g_N-2 downto 0);
signal loc_LimX : std_logic_vector(g_N-2 downto 0);
signal loc_LimY : std_logic_vector(g_N-2 downto 0);
signal loc_X : t_xy_bus;
signal loc_Y : t_xy_bus;
signal loc_Z : t_z_bus;
begin
B_Cell0 : entity work.cordic_xy_logic_hd
generic map(
g_M => g_M,
g_J => 0)
port map(
clk_i => clk_i,
rst_i => rst_i,
cor_submode_i => cor_submode_i,
lim_x_i => lim_x_i,
lim_y_i => lim_y_i,
d_i => d_i,
xi_i => xi_i,
yi_i => yi_i,
Zi_i => zi_i,
fi_i => fi1_i,
rst_o => loc_Rst(0),
lim_x_o => loc_LimX(0),
lim_y_o => loc_LimY(0),
xj_o => loc_X(0),
yj_o => loc_Y(0),
zj_o => loc_Z(0));
B_CellN_1 : entity work.cordic_xy_logic_nhd
generic map(
g_M => g_M,
g_J => g_N - 1,
g_I => g_N - 1,
g_ANGLE_MODE => g_ANGLE_MODE)
port map(
clk_i => clk_i,
rst_i => loc_Rst(g_N-2),
cor_submode_i => cor_submode_i,
cor_mode_i => cor_mode_i,
lim_x_i => loc_LimX(g_N-2),
lim_y_i => loc_LimY(g_N-2),
xi_i => loc_X(g_N-2),
yi_i => loc_Y(g_N-2),
zi_i => loc_Z(g_N-2),
Rst_o => Rst_o,
lim_x_o => lim_x_o,
lim_y_o => lim_y_o,
xj_o => xj_o,
yj_o => yj_o,
zj_o => zj_o);
GXYlogic : for K in 1 to g_N-2 generate
B_CellN : entity work.cordic_xy_logic_nhd
generic map(
g_M => g_M,
g_J => K,
g_ANGLE_MODE => g_ANGLE_MODE,
g_I => K)
port map(
clk_i => clk_i,
rst_i => loc_Rst(K-1),
lim_x_i => loc_LimX(K-1),
lim_y_i => loc_LimY(K-1),
xi_i => loc_X(K-1),
yi_i => loc_Y(K-1),
zi_i => loc_Z(K-1),
cor_submode_i => cor_submode_i,
cor_mode_i => cor_mode_i,
Rst_o => loc_Rst(K),
lim_x_o => loc_LimX(K),
lim_y_o => loc_LimY(K),
xj_o => loc_X(K),
yj_o => loc_Y(K),
zj_o => loc_Z(K));
end generate GXYlogic;
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.gc_cordic_pkg.all;
entity gc_cordic is
generic(
-- Number of XYlogicNHD cells instantiated
g_N : positive := 12;
--M = Word-width (maximum = 32)
g_M : positive := 16;
--AngleMode = Default angle format S8.7 otherwise FS = 180 deg.
g_ANGLE_MODE : t_CORDIC_ANGLE_FORMAT := S8_7
);
port (
clk_i : in std_logic;
rst_i : in std_logic;
cor_mode_i : in t_CORDIC_MODE;
cor_submode_i : in t_CORDIC_SUBMODE;
lim_x_i : in std_logic;
lim_y_i : in std_logic;
x0_i : in std_logic_vector(g_M-1 downto 0);
y0_i : in std_logic_vector(g_M-1 downto 0);
z0_i : in std_logic_vector(g_M-1 downto 0);
xn_o : out std_logic_vector(g_M-1 downto 0);
yn_o : out std_logic_vector(g_M-1 downto 0);
zn_o : out std_logic_vector(g_M-1 downto 0);
lim_x_o : out std_logic;
lim_y_o : out std_logic;
rst_o : out std_logic
);
end entity;
architecture rtl of gc_cordic is
signal r_lim_x, r_lim_y : std_logic;
signal z0_int : std_logic_vector(g_M downto 0);
signal x1, y1 : std_logic_vector(g_M-1 downto 0);
signal z1 : std_logic_vector(g_M downto 0);
signal d1 : std_logic;
signal fi1 : std_logic_vector(31 downto 0);
signal zj_int : std_logic_vector(g_M downto 0);
signal rst_o_int, rst_o_int_d : std_logic;
begin
fi1 <= std_logic_vector(f_phi_lookup(0, cor_submode_i, g_ANGLE_MODE));
z0_int <= std_logic_vector(resize (signed(z0_i), g_M + 1));
p_latch_lims : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_i = '1' then
r_lim_x <= '0';
r_lim_y <= '0';
else
r_lim_x <= lim_x_i;
r_lim_y <= lim_y_i;
end if;
end if;
end process;
U_Cordic_Init : entity work.cordic_init
generic map (
g_M => g_M,
g_ANGLE_MODE => g_ANGLE_MODE)
port map (
clk_i => clk_i,
rst_i => rst_i,
cor_mode_i => cor_mode_i,
cor_submode_i => cor_submode_i,
x0_i => x0_i,
y0_i => y0_i,
z0_i => z0_int,
x1_o => x1,
y1_o => y1,
z1_o => z1,
d1_o => d1);
U_Cordic_Core: entity work.cordic_xy_logic_nmhd
generic map (
g_N => g_N-1,
g_M => g_M,
g_ANGLE_MODE => g_ANGLE_MODE)
port map (
clk_i => clk_i,
rst_i => rst_i,
cor_mode_i => cor_mode_i,
cor_submode_i => cor_submode_i,
d_i => d1,
fi1_i => fi1(31 downto 31 - g_M - 1),
lim_x_i => r_lim_x,
lim_y_i => r_lim_y,
xi_i => x1,
yi_i => y1,
zi_i => z1,
xj_o => xn_o,
yj_o => yn_o,
zj_o => zj_int,
lim_x_o => lim_x_o,
lim_y_o => lim_y_o,
rst_o => rst_o_int);
U_Fixup_Angle : entity work.cordic_modulo_360
generic map (
g_M => g_M,
g_ANGLE_MODE => g_ANGLE_MODE)
port map (
cor_submode_i => cor_submode_i,
angle_i => zj_int,
angle_o => zn_o,
lim_o => open);
p_delay_reset : process(clk_i)
begin
if rising_edge(clk_i) then
rst_o_int_d <= rst_o_int;
end if;
end process;
rst_o <= rst_o_int_d or rst_o_int;
end rtl;
This diff is collapsed.
------------------------------------------
------------------------------------------
-- Date : Sat Jul 11 15:15:22 2015
--
-- Author : Daniel Valuch
--
-- Company : CERN BE/RF/FB
--
-- Description :
--
------------------------------------------
------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
entity gc_iq_demodulator is
generic (
-- number of data bits
g_N : positive := 16
);
port (
clk_i : in std_logic;
en_i : in std_logic;
sync_i : in std_logic;
rst_i : in std_logic;
adc_data_i : in std_logic_vector(g_N-1 downto 0);
dec_factor_i : in std_logic_vector(3 downto 0);
i_o : out std_logic_vector(23 downto 0);
q_o : out std_logic_vector(23 downto 0);
valid_o : out std_logic
);
end gc_iq_demodulator;
architecture rtl of gc_iq_demodulator is
type t_IQ_STATE is (S_0, S_PI2, S_PI, S_3PI2);
signal decim_cnt : unsigned(15 downto 0);
signal decim_cnt_init : unsigned(15 downto 0);
signal iacc, qacc : signed(28 downto 0);
signal state : t_IQ_STATE;
begin
decim_cnt_init <= to_unsigned(2**to_integer(unsigned(dec_factor_i))-1, decim_cnt'length);
process(clk_i)
begin
if rising_edge(clk_i) then
if rst_i = '1' or sync_i = '1' then
state <= S_0;
iacc <= (others => '0');
qacc <= (others => '0');
i_o <= (others => '0');
q_o <= (others => '0');
valid_o <= '0';
decim_cnt <= decim_cnt_init;
elsif en_i = '1' then
case state is
when S_0 =>
state <= S_PI2;
if decim_cnt = 0 then
valid_o <= '1';
iacc <= signed(adc_data_i);
qacc <= (others => '0');
decim_cnt <= decim_cnt_init;
-- I_out <= Std_logic_vector(Resize(shift_right(Iacc, To_Integer(Unsigned(Dec_factor))+1), 16)); -- Iacc + Signed(ADC_data)
-- Q_out <= Std_logic_vector(Resize(shift_right(Qacc, To_Integer(Unsigned(Dec_factor))+1), 16));
case dec_factor_i is
when X"0" =>
I_o <= std_logic_vector(iacc(16 downto 0)&"0000000");
Q_o <= std_logic_vector(qacc(16 downto 0)&"0000000");
when X"1" =>
I_o <= std_logic_vector(iacc(17 downto 0)&"000000");
Q_o <= std_logic_vector(qacc(17 downto 0)&"000000");
when X"2" =>
I_o <= std_logic_vector(iacc(18 downto 0)&"00000");
Q_o <= std_logic_vector(Qacc(18 downto 0)&"00000");
when X"3" =>
I_o <= std_logic_vector(Iacc(19 downto 0)&"0000");
Q_o <= std_logic_vector(Qacc(19 downto 0)&"0000");
when X"4" =>
I_o <= std_logic_vector(Iacc(20 downto 0)&"000");
Q_o <= std_logic_vector(Qacc(20 downto 0)&"000");
when X"5" =>
I_o <= std_logic_vector(Iacc(21 downto 0)&"00");
Q_o <= std_logic_vector(Qacc(21 downto 0)&"00");
when X"6" =>
I_o <= std_logic_vector(Iacc(22 downto 0)&"0");
Q_o <= std_logic_vector(Qacc(22 downto 0)&"0");
when X"7" =>
I_o <= std_logic_vector(Iacc(23 downto 0));
Q_o <= std_logic_vector(Qacc(23 downto 0));
when X"8" =>
I_o <= std_logic_vector(Iacc(24 downto 1));
Q_o <= std_logic_vector(Qacc(24 downto 1));
when X"9" =>
I_o <= std_logic_vector(Iacc(25 downto 2));
Q_o <= std_logic_vector(Qacc(25 downto 2));
when X"A" =>
I_o <= std_logic_vector(Iacc(26 downto 3));
Q_o <= std_logic_vector(Qacc(26 downto 3));
when X"B" =>
I_o <= std_logic_vector(Iacc(27 downto 4));
Q_o <= std_logic_vector(Qacc(27 downto 4));
when X"C" =>
I_o <= std_logic_vector(Iacc(28 downto 5));
Q_o <= std_logic_vector(Qacc(28 downto 5));
when others =>
I_o <= X"000000";
Q_o <= X"000000";
end case;
else
decim_cnt <= decim_cnt - 1;
iacc <= iacc + signed(adc_data_i);
end if;
when S_PI2 =>
state <= S_PI;
valid_o <= '0';
qacc <= qacc + signed(adc_data_i);
when S_PI =>
state <= S_3PI2;
iacc <= iacc - signed(adc_data_i);
when S_3PI2 =>
state <= S_0;
qacc <= qacc - signed(adc_data_i);
end case;
end if;
end if;
end process;
end rtl;
------------------------------------------
------------------------------------------
-- Date : Fri May 08 16:16:48 2015
--
-- Author : Gregoire Hagmann
--
-- Company : CERN BE-RF
--
-- Description : Complex IQ modulator Fs/4
--
-- I_i, Q_i : IQ data in baseband
-- Q_o, Q_o : modulated IQ data
--
-- Sync : Synchronization pulse for
-- modulator reset (Cnt=0).
-- 1 clk period width
--
-- ModEna: Activation of the modulator
-- '1' : Modulator on
-- '0' : Modulator off
-- (I_o=I_i)
-- (Q_o=Q_i)
--
-- Rst : output reset ('0' output)
--
-- Latency is 2 clk period
--
-- cnt= 0 / 1 / 2 / 3
-- I' = I / -Q / -I / Q
-- Q' = Q / I / -Q / -I
------------------------------------------
------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
entity gc_iq_modulator is
generic (
-- number of data bits
g_N : positive := 16
);
port (
clk_i : in std_logic;
en_i : in std_logic;
sync_i : in std_logic;
rst_i : in std_logic;
i_i : in std_logic_vector(g_N-1 downto 0);
q_i : in std_logic_vector(g_N-1 downto 0);
i_o : out std_logic_vector(g_N-1 downto 0);
q_o : out std_logic_vector(g_N-1 downto 0)
);
end gc_iq_modulator;
architecture rtl of gc_iq_modulator is
type t_IQ_STATE is (S_0, S_PI2, S_PI, S_3PI2);
signal state : t_IQ_STATE;
signal sync : std_logic;
signal iin, qin : signed(i_i'range);
signal iout, qout : signed(i_o'range);
begin
--Input signal Synchronization
p_latch_input : process(clk_i)
begin
if rising_edge(clk_i) then
iin <= signed(i_i);
qin <= signed(q_i);
sync <= sync_i;
end if;
end process;
p_modulator : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_i = '1' then
state <= S_0;
iout <= (others => '0');
qout <= (others => '0');
elsif en_i = '0' then
state <= S_0;
iout <= iin;
qout <= qin;
elsif sync = '1' or state = S_3PI2 then
state <= S_0;
iout <= iin;
qout <= qin;
elsif state = S_0 then
state <= S_PI2;
iout <= -qin;
qout <= iin;
elsif state = S_PI2 then
state <= S_PI;
iout <= -iin;
qout <= -qin;
elsif state = S_PI then
state <= S_3PI2;
iout <= qin;
qout <= -iin;
end if;
end if;
end process;
--output IQ data in std_logic format
i_o <= std_logic_vector(iout);
q_o <= std_logic_vector(qout);
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
--use work.gencores_pkg.all;
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
);
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);
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);
p_gain_i : in std_logic_vector(15 downto 0);
i_gain_i : in std_logic_vector(15 downto 0);
p_lim_o : out std_logic;
i_lim_o : out std_logic;
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_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-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);
signal sum : signed(g_OUT_BITS+1 downto 0);
signal itrunc, ptrunc : signed(g_OUT_BITS-1 downto 0);
procedure f_clamp (x : signed; minval : signed; maxval : signed;
y : out signed; limit : out std_logic) is
begin
if(x > maxval) then
y := maxval;
limit := '1';
elsif (x < minval) then
y := minval;
limit := '1';
else
y := x;
limit := '0';
end if;
end f_clamp;
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);
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;
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';
else
y_o <= std_logic_vector(resize(sum, g_OUT_BITS));
lim_o <= '0';
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