URL
https://opencores.org/ocsvn/cordic/cordic/trunk
Subversion Repositories cordic
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 5 to Rev 6
- ↔ Reverse comparison
Rev 5 → Rev 6
/trunk/rect2polar/r2p_CordicPipe.vhd
0,0 → 1,142
-- |
-- file: r2p_CordicPipe.vhd |
-- author: Richard Herveille |
-- rev. 1.0 initial release |
-- rev. 1.1 March 19th, 2001. Richard Herveille. Changed function Delta, it is compatible with Xilinx WebPack software now |
-- rev. 1.2 May 18th, 2001. Richard Herveille. Added documentation to function ATAN (by popular request). |
-- rev. 1.3 June 4th, 2001. Richard Herveille. Revised design (made it simpler and easier to understand). |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_arith.all; |
|
entity r2p_CordicPipe is |
generic( |
WIDTH : natural := 16; |
PIPEID : natural := 1 |
); |
port( |
clk : in std_logic; |
ena : in std_logic; |
|
Xi : in signed(WIDTH -1 downto 0); |
Yi : in signed(WIDTH -1 downto 0); |
Zi : in signed(19 downto 0); |
Xo : out signed(WIDTH -1 downto 0); |
Yo : out signed(WIDTH -1 downto 0); |
Zo : out signed(19 downto 0) |
); |
end entity r2p_CordicPipe; |
|
architecture dataflow of r2p_CordicPipe is |
|
-- |
-- functions |
-- |
|
-- Function CATAN (constante arc-tangent). |
-- This is a lookup table containing pre-calculated arc-tangents. |
-- 'n' is the number of the pipe, returned is a 20bit arc-tangent value. |
-- The numbers are calculated as follows: Z(n) = atan(1/2^n) |
-- examples: |
-- 20bit values => 2^20 = 2pi(rad) |
-- 1(rad) = 2^20/2pi = 166886.053.... |
-- n:1, atan(1/2) = 0.4636...(rad) |
-- 0.4636... * 166886.053... = 77376.32(dec) = 12E40(hex) |
-- n:2, atan(1/4) = 0.2449...(rad) |
-- 0.2449... * 166886.053... = 40883.52(dec) = 9FB3(hex) |
-- n:3, atan(1/8) = 0.1243...(rad) |
-- 0.1243... * 166886.053... = 20753.11(dec) = 5111(hex) |
-- |
function CATAN(n :natural) return integer is |
variable result :integer; |
begin |
case n is |
when 0 => result := 16#020000#; |
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 is actually an arithmatic shift right |
-- This strange construction is needed for compatibility with Xilinx WebPack |
function Delta(Arg : signed; Cnt : natural) return signed is |
variable tmp : signed(Arg'range); |
constant lo : integer := Arg'high -cnt +1; |
begin |
for n in Arg'high downto lo loop |
tmp(n) := Arg(Arg'high); |
end loop; |
for n in Arg'high -cnt downto 0 loop |
tmp(n) := Arg(n +cnt); |
end loop; |
return tmp; |
end function Delta; |
|
function AddSub(dataa, datab : in signed; add_sub : in std_logic) return signed is |
begin |
if (add_sub = '1') then |
return dataa + datab; |
else |
return dataa - datab; |
end if; |
end; |
|
-- |
-- ARCHITECTURE BODY |
-- |
signal dX, Xresult : signed(WIDTH -1 downto 0); |
signal dY, Yresult : signed(WIDTH -1 downto 0); |
signal atan, Zresult : signed(19 downto 0); |
|
signal Yneg, Ypos : std_logic; |
|
begin |
|
dX <= Delta(Xi, PIPEID); |
dY <= Delta(Yi, PIPEID); |
atan <= conv_signed( catan(PIPEID), 20); -- Angle can not be negative, catan never returns a negative value, so conv_signed can be used |
|
-- 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/r2p_cordic.vhd
0,0 → 1,100
-- |
-- VHDL implementation of cordic algorithm |
-- |
-- File: cordic.vhd |
-- author: Richard Herveille |
-- rev. 1.0 initial release |
-- rev. 1.1 changed CordicPipe component declaration, Xilinx WebPack issue |
-- rev. 1.2 Revised entire core. Made is simpler and easier to understand. |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_arith.all; |
|
entity r2p_cordic is |
generic( |
PIPELINE : integer := 15; |
WIDTH : integer := 16; |
EXT_PRECISION : integer := 4 |
); |
port( |
clk : in std_logic; |
ena : in std_logic; |
|
Xi : in signed(WIDTH-1 downto 0); |
Yi : in signed(WIDTH-1 downto 0); |
Zi : in signed(19 downto 0) := (others => '0'); |
|
Xo : out signed(WIDTH + EXT_PRECISION -1 downto 0); |
Zo : out signed(19 downto 0) |
); |
end r2p_cordic; |
|
|
architecture dataflow of r2p_cordic is |
|
-- |
-- TYPE defenitions |
-- |
type XYVector is array(PIPELINE downto 0) of signed(WIDTH + EXT_PRECISION -1 downto 0); |
type ZVector is array(PIPELINE downto 0) of signed(19 downto 0); |
|
-- |
-- COMPONENT declarations |
-- |
component r2p_CordicPipe |
generic( |
WIDTH : natural := 16; |
PIPEID : natural := 1 |
); |
port( |
clk : in std_logic; |
ena : in std_logic; |
|
Xi : in signed(WIDTH -1 downto 0); |
Yi : in signed(WIDTH -1 downto 0); |
Zi : in signed(19 downto 0); |
|
Xo : out signed(WIDTH -1 downto 0); |
Yo : out signed(WIDTH -1 downto 0); |
Zo : out signed(19 downto 0) |
); |
end component r2p_CordicPipe; |
|
-- |
-- SIGNALS |
-- |
signal X, Y : XYVector; |
signal Z : ZVector; |
|
-- |
-- ACHITECTURE BODY |
-- |
begin |
-- fill first nodes |
|
X(0)(WIDTH + EXT_PRECISION -1 downto EXT_PRECISION) <= Xi; -- fill MSBs with input data |
X(0)(EXT_PRECISION -1 downto 0) <= (others => '0'); -- fill LSBs with '0' |
|
Y(0)(WIDTH + EXT_PRECISION -1 downto EXT_PRECISION) <= Yi; -- fill MSBs with input data |
Y(0)(EXT_PRECISION -1 downto 0) <= (others => '0'); -- fill LSBs with '0' |
|
Z(0) <= Zi; |
|
-- |
-- generate pipeline |
-- |
gen_pipe: |
for n in 1 to PIPELINE generate |
Pipe: r2p_CordicPipe |
generic map(WIDTH => WIDTH+EXT_PRECISION, PIPEID => n -1) |
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 |
-- |
Xo <= X(PIPELINE); |
Zo <= Z(PIPELINE); |
end dataflow; |
|
/trunk/rect2polar/r2p_post.vhd
0,0 → 1,150
-- |
-- post.vhd |
-- |
-- Cordic post-processing block |
-- |
-- Compensate cordic algorithm K-factor; divide Radius by 1.6467, or multiply by 0.60725. |
-- Approximation: Ra = Ri/2 + Ri/8 - Ri/64 - Ri/512 |
-- Radius = Ra - Ra/4096 = Ri * 0.60727. This is a 0.0034% error. |
-- Implementation: Ra = (Ri/2 + Ri/8) - (Ri/64 + Ri/512) |
-- Radius = Ra - Ra/4096 |
-- Position calculated angle in correct quadrant. |
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_arith.all; |
|
entity r2p_post is |
port( |
clk : in std_logic; |
ena : in std_logic; |
|
Ai : in signed(19 downto 0); |
Ri : in unsigned(19 downto 0); |
Q : in std_logic_vector(2 downto 0); |
|
Ao : out signed(19 downto 0); |
Ro : out unsigned(19 downto 0)); |
end entity r2p_post; |
|
architecture dataflow of r2p_post is |
begin |
radius: block |
signal RadA, RadB, RadC : unsigned(19 downto 0); |
begin |
process(clk) |
begin |
if (clk'event and clk = '1') then |
if (ena = '1') then |
RadA <= ('0' & Ri(19 downto 1)) + ("000" & Ri(19 downto 3)); |
RadB <= ("000000" & Ri(19 downto 6)) + ("000000000" & Ri(19 downto 9)); |
RadC <= RadA - RadB; |
|
Ro <= RadC - RadC(19 downto 12); |
end if; |
end if; |
end process; |
end block radius; |
|
angle: block |
constant const_PI2 : signed(19 downto 0) := conv_signed(16#40000#, 20); -- PI / 2 |
constant const_PI : signed(19 downto 0) := conv_signed(16#80000#, 20); -- PI |
constant const_2PI : signed(19 downto 0) := (others => '0'); -- 2PI |
|
signal dQ : std_logic_vector(2 downto 1); |
signal ddQ : std_logic; |
signal AngStep1 : signed(19 downto 0); |
signal AngStep2 : signed(19 downto 0); |
begin |
angle_step1: process(clk, Ai, Q) |
variable overflow : std_logic; |
variable AngA, AngB, Ang : signed(19 downto 0); |
begin |
-- check if angle is negative, if so set it to zero |
overflow := Ai(19); --and Ai(18); |
|
if (overflow = '1') then |
AngA := (others => '0'); |
else |
AngA := Ai; |
end if; |
|
-- step 1: Xabs and Yabs are swapped |
-- Calculated angle is the angle between vector and Y-axis. |
-- ActualAngle = PI/2 - CalculatedAngle |
AngB := const_PI2 - 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, AngStep1, dQ) |
variable AngA, AngB, Ang : signed(19 downto 0); |
begin |
AngA := AngStep1; |
|
-- step 2: Xvalue is negative |
-- Actual angle is in the second or third quadrant |
-- ActualAngle = PI - CalculatedAngle |
AngB := const_PI - 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, AngStep2, ddQ) |
variable AngA, AngB, Ang : signed(19 downto 0); |
begin |
AngA := AngStep2; |
|
-- step 3: Yvalue is negative |
-- Actual angle is in the third or fourth quadrant |
-- ActualAngle = 2PI - CalculatedAngle |
AngB := const_2PI - AngA; |
|
if (ddQ = '1') then |
Ang := AngB; |
else |
Ang := AngA; |
end if; |
|
if (clk'event and clk = '1') then |
if (ena = '1') then |
Ao <= Ang; |
end if; |
end if; |
end process angle_step3; |
end block angle; |
end; |
|
|
|
|
|
|
|
|
|
/trunk/rect2polar/r2p_pre.vhd
0,0 → 1,83
-- |
-- r2p_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) |
-- |
-- Rev. 1.1 June 4th, 2001. Richard Herveille. Revised entire core. |
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_arith.all; |
|
entity r2p_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 unsigned(14 downto 0); |
Yo : out unsigned(14 downto 0); |
Q : out std_logic_vector(2 downto 0)); |
end entity r2p_pre; |
|
architecture dataflow of r2p_pre is |
signal Xint1, Yint1 : unsigned(14 downto 0); |
signal Xneg, Yneg, swap : std_logic; |
|
begin |
-- |
-- step 1: Determine absolute value of X and Y, set Xneg and Yneg |
-- Loose the sign-bit. |
Step1: process(clk, Xi, Yi) |
begin |
if (clk'event and clk = '1') then |
if (ena = '1') then |
Xint1 <= conv_unsigned(abs(Xi), 15); |
Xneg <= Xi(Xi'left); |
|
Yint1 <= conv_unsigned(abs(Yi), 15); |
Yneg <= Yi(Yi'left); |
end if; |
end if; |
end process Step1; |
|
-- |
-- step 2: Swap X and Y if Y>X |
-- |
Step2: process(clk, Xint1, Yint1) |
variable Xint2, Yint2 : unsigned(14 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 <= Xint2; |
Yo <= Yint2; |
|
Q <= (Yneg, Xneg, swap); |
end if; |
end if; |
end process Step2; |
|
end architecture dataflow; |
|
|
/trunk/rect2polar/r2p_corproc.vhd
0,0 → 1,107
-- |
-- file: r2p_corproc.vhd |
-- |
-- XY to RA coordinate / rectangular to polar coordinates processor |
-- |
-- uses: r2p_pre.vhd, r2p_cordic.vhd, r2p_post.vhd |
-- |
-- rev. 1.1 June 4th, 2001. Richard Herveille. Completely revised core. |
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_arith.all; |
|
entity r2p_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 unsigned(19 downto 0); |
Aout : out signed(19 downto 0) |
); |
end entity r2p_corproc; |
|
architecture dataflow of r2p_corproc is |
constant PipeLength : natural := 15; |
|
component r2p_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 unsigned(14 downto 0); |
Yo : out unsigned(14 downto 0); |
Q : out std_logic_vector(2 downto 0) |
); |
end component r2p_pre; |
|
component r2p_cordic is |
generic( |
PIPELINE : integer; |
WIDTH : integer; |
EXT_PRECISION : integer |
); |
port( |
clk : in std_logic; |
ena : in std_logic; |
Xi : in signed(WIDTH-1 downto 0); |
Yi : in signed(WIDTH-1 downto 0); |
Zi : in signed(19 downto 0) := (others => '0'); |
|
Xo : out signed(WIDTH + EXT_PRECISION -1 downto 0); |
Zo : out signed(19 downto 0)); |
end component r2p_cordic; |
|
component r2p_post is |
port( |
clk : in std_logic; |
ena : in std_logic; |
|
Ai : in signed(19 downto 0); |
Ri : in unsigned(19 downto 0); |
Q : in std_logic_vector(2 downto 0); |
|
Ao : out signed(19 downto 0); |
Ro : out unsigned(19 downto 0)); |
end component r2p_post; |
|
signal Xpre, Ypre : unsigned(15 downto 0); |
signal Acor, Rcor : signed(19 downto 0); |
signal Q, dQ : std_logic_vector(2 downto 0); |
|
begin |
|
-- instantiate components |
u1: r2p_pre port map(clk => clk, ena => ena, Xi => Xin, Yi => Yin, Xo => Xpre(14 downto 0), Yo => Ypre(14 downto 0), Q => Q); |
Xpre(15) <= '0'; |
Ypre(15) <= '0'; |
|
u2: r2p_cordic |
generic map(PIPELINE => PipeLength, WIDTH => 16, EXT_PRECISION => 4) |
port map(clk => clk, ena => ena, Xi => signed(Xpre), Yi => signed(Ypre), Xo => Rcor, Zo => Acor); |
|
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; |
|
u3: r2p_post port map(clk => clk, ena => ena, Ri => unsigned(Rcor), Ai => Acor, Q => dQ, Ao => Aout, Ro => Rout); |
end architecture dataflow; |