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; |
|
|