www.pudn.com > Cordic_suanfa.rar > post.vhd
--
-- 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;