OpenCores
URL https://opencores.org/ocsvn/cordic/cordic/trunk

Subversion Repositories cordic

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/rect2polar/CordicPipe.vhd
0,0 → 1,111
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
 
entity CordicPipe is
generic(
WIDTH : natural;
AWIDTH : natural;
PIPEID : natural);
port(
clk : in std_logic;
ena : in std_logic;
 
Xi : in std_logic_vector(WIDTH -1 downto 0);
Yi : in std_logic_vector(WIDTH -1 downto 0);
Zi : in std_logic_vector(AWIDTH -1 downto 0);
Xo : out std_logic_vector(WIDTH -1 downto 0);
Yo : out std_logic_vector(WIDTH -1 downto 0);
Zo : out std_logic_vector(AWIDTH -1 downto 0));
end entity CordicPipe;
 
architecture dataflow of CordicPipe is
 
--
-- functions
--
function CATAN(n :natural) return integer is
variable result :integer;
begin
case n is
when 1 => result := 16#012E40#;
when 2 => result := 16#09FB4#;
when 3 => result := 16#05111#;
when 4 => result := 16#028B1#;
when 5 => result := 16#0145D#;
when 6 => result := 16#0A2F#;
when 7 => result := 16#0518#;
when 8 => result := 16#028C#;
when 9 => result := 16#0146#;
when 10 => result := 16#0A3#;
when 11 => result := 16#051#;
when 12 => result := 16#029#;
when 13 => result := 16#014#;
when 14 => result := 16#0A#;
when 15 => result := 16#05#;
when 16 => result := 16#03#;
when 17 => result := 16#01#;
when others => result := 16#0#;
end case;
return result;
end CATAN;
 
function Delta(Arg : std_logic_vector; Cnt : natural) return std_logic_vector is
variable tmp : std_logic_vector(Arg'range);
begin
tmp := Arg;
for n in 1 to cnt loop
tmp := ( tmp(Arg'high) & tmp(Arg'high downto 1) );
end loop;
return tmp;
end function Delta;
 
function AddSub(dataa, datab : in std_logic_vector; add_sub : in std_logic) return std_logic_vector is
begin
if (add_sub = '1') then
return unsigned(dataa) + unsigned(datab);
else
return unsigned(dataa) - unsigned(datab);
end if;
end;
 
--
-- ARCHITECTURE BODY
--
signal dX, Xresult : std_logic_vector(WIDTH -1 downto 0);
signal dY, Yresult : std_logic_vector(WIDTH -1 downto 0);
signal atan, Zresult : std_logic_vector(AWIDTH -1 downto 0);
 
signal Yneg, Ypos : std_logic;
begin
 
dX <= Delta(Xi, PIPEID);
dY <= Delta(Yi, PIPEID);
atan <= std_logic_vector(conv_unsigned( catan(PIPEID), AWIDTH) );
 
-- generate adder structures
Yneg <= Yi(WIDTH -1);
Ypos <= not Yi(WIDTH -1);
 
-- xadd
Xresult <= AddSub(Xi, dY, YPos);
 
-- yadd
Yresult <= AddSub(Yi, dX, Yneg);
 
-- zadd
Zresult <= AddSub(Zi, atan, Ypos);
 
gen_regs: process(clk)
begin
if(clk'event and clk='1') then
if (ena = '1') then
Xo <= Xresult;
Yo <= Yresult;
Zo <= Zresult;
end if;
end if;
end process;
 
end architecture dataflow;
/trunk/rect2polar/cordic.vhd
0,0 → 1,102
--
-- VHDL implementation of cordic algorithm
--
--
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
 
entity Cordic is
generic(
PIPELINE : integer := 15;
WIDTH : integer := 16;
AWIDTH : integer := 16;
EXTEND_PRECISION : integer := 4);
port(
clk : in std_logic;
ena : in std_logic;
 
Xi : in std_logic_vector(WIDTH-1 downto 0);
Yi : in std_logic_vector(WIDTH-1 downto 0);
R : out std_logic_vector(WIDTH + EXTEND_PRECISION -1 downto 0);
A : out std_logic_vector(AWIDTH -1 downto 0));
constant ANG : natural := 20;
constant PRECISION : natural := WIDTH + EXTEND_PRECISION;
end Cordic;
 
 
architecture dataflow of Cordic is
 
--
-- TYPE defenitions
--
type XYVector is array(PIPELINE downto 0) of std_logic_vector(PRECISION downto 0);
type ZVector is array(PIPELINE downto 0) of std_logic_vector(ANG -1 downto 0);
 
--
-- COMPONENT declarations
--
component CordicPipe
generic(
WIDTH : natural;
AWIDTH : natural;
PIPEID : natural);
port(
clk : in std_logic;
ena : in std_logic;
 
Xi, Yi : in std_logic_vector(PRECISION downto 0);
Zi : in std_logic_vector(ANG -1 downto 0);
Xo, Yo : out std_logic_vector(PRECISION downto 0);
Zo : out std_logic_vector(ANG -1 downto 0));
end component CordicPipe;
 
--
-- SIGNALS
--
signal X, Y : XYVector;
signal Z : ZVector;
 
--
-- ACHITECTURE BODY
--
begin
-- fill first nodes
 
X(0)(PRECISION downto EXTEND_PRECISION) <= ('0' & Xi); -- fill msb of X0
fill_x:
for n in EXTEND_PRECISION -1 downto 0 generate -- fill lsb with '0'
X(0)(n) <= '0';
end generate;
 
Y(0)(PRECISION downto EXTEND_PRECISION) <= (Yi(WIDTH -1) & Yi);
fill_y:
for n in EXTEND_PRECISION -1 downto 0 generate -- fill lsb with '0'
Y(0)(n) <= '0';
end generate;
 
fill_z:
for n in ANG -1 downto 0 generate -- fill Z with '0'
Z(0)(n) <= '0';
end generate;
 
--
-- generate pipeline
--
gen_pipe:
for n in 1 to PIPELINE generate
Pipe: CordicPipe
generic map(WIDTH => PRECISION +1, AWIDTH => ANG, PIPEID => n)
port map ( clk, ena, X(n-1), Y(n-1), Z(n-1), X(n), Y(n), Z(n) );
end generate gen_pipe;
 
--
-- assign outputs
--
R <= X(PIPELINE)(PRECISION -1 downto 0);
A <= Z(PIPELINE)(ANG -1 downto ANG -AWIDTH);
end dataflow;
/trunk/rect2polar/post.vhd
0,0 → 1,148
--
-- post.vhd
--
-- Cordic post-processing block
--
-- Compensate cordic algorithm K-factor; divide Radius by 1.165.
-- Actual implementation: Radius := Ri * 0.859
--
-- Position calculated angle in correct quadrant.
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
 
entity post is
port(
clk : in std_logic;
ena : in std_logic;
 
Ai : in std_logic_vector(15 downto 0);
Ri : in std_logic_vector(19 downto 0);
Q : in std_logic_vector(2 downto 0);
 
Ao : out std_logic_vector(15 downto 0);
Ro : out std_logic_vector(19 downto 0));
 
constant cPI2 : natural := 2**14; -- Pi/2 = 0x4000
constant cPI : natural := 2**15; -- Pi/2 = 0x8000
constant c2PI : natural := 2**16; -- Pi = 0x10000 = 0x0000
end entity post;
 
architecture dataflow of post is
begin
radius: block
signal RadA, RadB, RadC : natural range 0 to 2**20;
begin
process(clk)
variable tmp : natural;
begin
tmp := conv_integer( unsigned(Ri) );
 
if (clk'event and clk = '1') then
if (ena = '1') then
RadA <= tmp - (tmp / 8);
RadB <= RadA - (RadA / 64);
RadC <= RadB - (RadB / 512);
end if;
end if;
end process;
 
-- assign output
Ro <= std_logic_vector(conv_unsigned(RadC, 20));
end block radius;
 
angle: block
signal dQ : std_logic_vector(2 downto 1);
signal ddQ : std_logic;
signal AngStep1 : unsigned(14 downto 0);
signal AngStep2 : unsigned(15 downto 0);
signal AngStep3 : unsigned(16 downto 0);
begin
angle_step1: process(clk)
variable overflow : std_logic;
variable AngA, AngB, Ang : unsigned(14 downto 0);
begin
-- check if angle is negative, if so set it to zero
overflow := Ai(14) and Ai(13);
 
if (overflow = '1') then
Anga := (others => '0');
else
AngA := unsigned('0' & Ai(13 downto 0));
end if;
 
-- step 1: Xabs and Yabs are swapped
-- Calculated angle is the angle between vector and Y-axis.
-- ActualAngle = PI/2 - CalculatedAngle
AngB := cPI2 - AngA;
 
if (Q(0) = '1') then
Ang := AngB;
else
Ang := AngA;
end if;
 
if (clk'event and clk = '1') then
if (ena = '1') then
AngStep1 <= Ang;
dQ <= q(2 downto 1);
end if;
end if;
end process angle_step1;
 
 
angle_step2: process(clk)
variable AngA, AngB, Ang : unsigned(15 downto 0);
begin
AngA := ('0' & AngStep1);
 
-- step 2: Xvalue is negative
-- Actual angle is in the second or third quadrant
-- ActualAngle = PI - CalculatedAngle
AngB := cPI - AngA;
 
if (dQ(1) = '1') then
Ang := AngB;
else
Ang := AngA;
end if;
 
if (clk'event and clk = '1') then
if (ena = '1') then
AngStep2 <= Ang;
ddQ <= dQ(2);
end if;
end if;
end process angle_step2;
 
 
angle_step3: process(clk)
variable AngA, AngB, Ang : unsigned(16 downto 0);
begin
AngA := ('0' & AngStep2);
 
-- step 3: Yvalue is negative
-- Actual angle is in the third or fourth quadrant
-- ActualAngle = 2PI - CalculatedAngle
AngB := c2PI - AngA;
 
if (ddQ = '1') then
Ang := AngB;
else
Ang := AngA;
end if;
if (clk'event and clk = '1') then
if (ena = '1') then
AngStep3 <= Ang;
end if;
end if;
end process angle_step3;
 
Ao <= std_logic_vector( AngStep3(15 downto 0) );
end block angle;
end;
 
 
/trunk/rect2polar/pre.vhd
0,0 → 1,78
--
-- pre.vhd
--
-- Cordic pre-processing block
--
--
-- step 1: determine quadrant and generate absolute value of X and Y
-- Q1: Xnegative
-- Q2: Ynegative
--
-- step 2: swap X and Y values if Y>X
-- Q3: swapped (Y > X)
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
 
entity pre is
port(
clk : in std_logic;
ena : in std_logic;
 
Xi : in signed(15 downto 0);
Yi : in signed(15 downto 0);
 
Xo : out std_logic_vector(15 downto 0);
Yo : out std_logic_vector(15 downto 0);
Q : out std_logic_vector(2 downto 0));
end entity pre;
 
architecture dataflow of pre is
signal Xint1, Yint1 : unsigned(15 downto 0);
signal Xneg, Yneg, swap : std_logic;
 
begin
--
-- step 1: Determine absolute value of X and Y, set Xneg and Yneg
--
Step1: process(clk, Xi, Yi)
begin
if (clk'event and clk = '1') then
if (ena = '1') then
Xint1 <= conv_unsigned(abs(Xi), 16);
Xneg <= Xi(Xi'left);
 
Yint1 <= conv_unsigned(abs(Yi), 16);
Yneg <= Yi(Yi'left);
end if;
end if;
end process Step1;
 
--
-- step 2: Swap X and Y if Y>X
--
Step2: process(clk)
variable Xint2, Yint2 : unsigned(15 downto 0);
begin
if (Yint1 > Xint1) then
swap <= '1';
Xint2 := Yint1;
Yint2 := Xint1;
else
swap <= '0';
Xint2 := Xint1;
Yint2 := Yint1;
end if;
if(clk'event and clk = '1') then
if (ena = '1') then
Xo <= std_logic_vector(Xint2);
Yo <= std_logic_vector(Yint2);
 
Q <= (Yneg, Xneg, swap);
end if;
end if;
end process Step2;
 
end architecture dataflow;
/trunk/rect2polar/corproc.vhd
0,0 → 1,107
--
-- corproc.vhd
--
-- XY to RA coordinate processor
--
-- uses: pre.vhd, cordic.vhd, post.vhd
--
--
--
-- system delay: 21 (data out delay: 20)
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
 
entity corproc is
port(
clk : in std_logic;
ena : in std_logic;
Xin : in signed(15 downto 0);
Yin : in signed(15 downto 0);
Rout : out std_logic_vector(19 downto 0);
Aout : out std_logic_vector(15 downto 0));
end entity corproc;
 
architecture dataflow of corproc is
constant PipeLength : natural := 15;
 
component pre is
port(
clk : in std_logic;
ena : in std_logic;
Xi : in signed(15 downto 0);
Yi : in signed(15 downto 0);
 
Xo : out std_logic_vector(15 downto 0);
Yo : out std_logic_vector(15 downto 0);
Q : out std_logic_vector(2 downto 0));
end component pre;
 
component cordic is
generic(
PIPELINE : integer;
WIDTH : integer;
AWIDTH : integer;
EXTEND_PRECISION : integer);
port(
clk : in std_logic;
ena : in std_logic;
Xi : in std_logic_vector(WIDTH-1 downto 0);
Yi : in std_logic_vector(WIDTH-1 downto 0);
R : out std_logic_vector(WIDTH + EXTEND_PRECISION -1 downto 0);
A : out std_logic_vector(AWIDTH -1 downto 0));
end component cordic;
 
component post is
port(
clk : in std_logic;
ena : in std_logic;
 
Ai : in std_logic_vector(15 downto 0);
Ri : in std_logic_vector(19 downto 0);
Q : in std_logic_vector(2 downto 0);
 
Ao : out std_logic_vector(15 downto 0);
Ro : out std_logic_vector(19 downto 0));
end component post;
 
signal Xpre, Ypre, Acor : std_logic_vector(15 downto 0);
signal Rcor : std_logic_vector(19 downto 0);
signal Q, dQ : std_logic_vector(2 downto 0);
 
begin
 
-- instantiate components
u1: pre port map(clk => clk, ena => ena, Xi => Xin, Yi => Yin, Xo => Xpre, Yo => Ypre, Q => Q);
 
u2: cordic
generic map(PIPELINE => PipeLength, WIDTH => 16, AWIDTH => 16, EXTEND_PRECISION => 4)
port map(clk, ena, Xpre, Ypre, Rcor, Acor);
 
u3: post port map(clk => clk, ena => ena, Ri => Rcor, Ai => Acor, Q => dQ, Ao => Aout, Ro => Rout);
 
delay: block
type delay_type is array(PipeLength -1 downto 0) of std_logic_vector(2 downto 0);
signal delay_pipe :delay_type;
begin
process(clk, Q)
begin
if (clk'event and clk = '1') then
if (ena = '1') then
delay_pipe(0) <= Q;
for n in 1 to PipeLength -1 loop
delay_pipe(n) <= delay_pipe(n -1);
end loop;
end if;
end if;
end process;
dQ <= delay_pipe(PipeLength -1);
end block delay;
 
end architecture dataflow;
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.