--
|
--
|
-- file: p2r_CordicPipe.vhd
|
-- file: p2r_CordicPipe.vhd
|
-- author: Richard Herveille
|
-- author: Richard Herveille
|
-- rev. 1.0 initial release
|
-- rev. 1.0 initial release
|
--
|
--
|
|
|
--
|
--
|
-- This file is come from WWW.OPENCORES.ORG
|
-- This file is come from WWW.OPENCORES.ORG
|
|
|
---------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------
|
--
|
--
|
-- Title : p2r_CordicPipe
|
-- Title : p2r_CordicPipe
|
-- Design : cfft
|
-- Design : cfft
|
--
|
--
|
---------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------
|
--
|
--
|
-- File : p2r_CordicPipe.vhd
|
-- File : p2r_CordicPipe.vhd
|
--
|
--
|
---------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------
|
--
|
--
|
-- Description : Cordic arith pilepline
|
-- Description : Cordic arith pilepline
|
--
|
--
|
---------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------
|
--
|
--
|
-- Revisions : 0
|
-- Revisions : 0
|
-- Revision Number : 1
|
-- Revision Number : 1
|
-- Version : 1
|
-- Version : 1
|
-- Date : Oct 17 2002
|
-- Date : Oct 17 2002
|
-- Modifier : ZHAO Ming <sradio@opencores.org>
|
-- Modifier : ZHAO Ming <sradio@opencores.org>
|
-- Desccription : Data width configurable
|
-- Desccription : Data width configurable
|
--
|
--
|
---------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------
|
|
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_arith.all;
|
use ieee.std_logic_arith.all;
|
|
|
entity p2r_CordicPipe is
|
entity p2r_CordicPipe is
|
generic(
|
generic(
|
WIDTH : natural := 16;
|
WIDTH : natural := 16;
|
PIPEID : natural := 1
|
PIPEID : natural := 1
|
);
|
);
|
port(
|
port(
|
clk : in std_logic;
|
clk : in std_logic;
|
ena : in std_logic;
|
ena : in std_logic;
|
|
|
Xi : in signed(WIDTH -1 downto 0);
|
Xi : in signed(WIDTH -1 downto 0);
|
Yi : in signed(WIDTH -1 downto 0);
|
Yi : in signed(WIDTH -1 downto 0);
|
Zi : in signed(19 downto 0);
|
Zi : in signed(19 downto 0);
|
|
|
Xo : out signed(WIDTH -1 downto 0);
|
Xo : out signed(WIDTH -1 downto 0);
|
Yo : out signed(WIDTH -1 downto 0);
|
Yo : out signed(WIDTH -1 downto 0);
|
Zo : out signed(19 downto 0)
|
Zo : out signed(19 downto 0)
|
);
|
);
|
end entity p2r_CordicPipe;
|
end entity p2r_CordicPipe;
|
|
|
architecture dataflow of p2r_CordicPipe is
|
architecture dataflow of p2r_CordicPipe is
|
|
|
--
|
--
|
-- functions
|
-- functions
|
--
|
--
|
|
|
-- Function CATAN (constante arc-tangent).
|
-- Function CATAN (constante arc-tangent).
|
-- This is a lookup table containing pre-calculated arc-tangents.
|
-- This is a lookup table containing pre-calculated arc-tangents.
|
-- 'n' is the number of the pipe, returned is a 20bit arc-tangent value.
|
-- '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)
|
-- The numbers are calculated as follows: Z(n) = atan(1/2^n)
|
-- examples:
|
-- examples:
|
-- 20bit values => 2^20 = 2pi(rad)
|
-- 20bit values => 2^20 = 2pi(rad)
|
-- 1(rad) = 2^20/2pi = 166886.053....
|
-- 1(rad) = 2^20/2pi = 166886.053....
|
-- n:0, atan(1/1) = 0.7853...(rad)
|
-- n:0, atan(1/1) = 0.7853...(rad)
|
-- 0.7853... * 166886.053... = 131072(dec) = 20000(hex)
|
-- 0.7853... * 166886.053... = 131072(dec) = 20000(hex)
|
-- n:1, atan(1/2) = 0.4636...(rad)
|
-- n:1, atan(1/2) = 0.4636...(rad)
|
-- 0.4636... * 166886.053... = 77376.32(dec) = 12E40(hex)
|
-- 0.4636... * 166886.053... = 77376.32(dec) = 12E40(hex)
|
-- n:2, atan(1/4) = 0.2449...(rad)
|
-- n:2, atan(1/4) = 0.2449...(rad)
|
-- 0.2449... * 166886.053... = 40883.52(dec) = 9FB3(hex)
|
-- 0.2449... * 166886.053... = 40883.52(dec) = 9FB3(hex)
|
-- n:3, atan(1/8) = 0.1243...(rad)
|
-- n:3, atan(1/8) = 0.1243...(rad)
|
-- 0.1243... * 166886.053... = 20753.11(dec) = 5111(hex)
|
-- 0.1243... * 166886.053... = 20753.11(dec) = 5111(hex)
|
--
|
--
|
function CATAN(n :natural) return integer is
|
function CATAN(n :natural) return integer is
|
variable result :integer;
|
variable result :integer;
|
begin
|
begin
|
case n is
|
case n is
|
when 0 => result := 16#020000#;
|
when 0 => result := 16#020000#;
|
when 1 => result := 16#012E40#;
|
when 1 => result := 16#012E40#;
|
when 2 => result := 16#09FB4#;
|
when 2 => result := 16#09FB4#;
|
when 3 => result := 16#05111#;
|
when 3 => result := 16#05111#;
|
when 4 => result := 16#028B1#;
|
when 4 => result := 16#028B1#;
|
when 5 => result := 16#0145D#;
|
when 5 => result := 16#0145D#;
|
when 6 => result := 16#0A2F#;
|
when 6 => result := 16#0A2F#;
|
when 7 => result := 16#0518#;
|
when 7 => result := 16#0518#;
|
when 8 => result := 16#028C#;
|
when 8 => result := 16#028C#;
|
when 9 => result := 16#0146#;
|
when 9 => result := 16#0146#;
|
when 10 => result := 16#0A3#;
|
when 10 => result := 16#0A3#;
|
when 11 => result := 16#051#;
|
when 11 => result := 16#051#;
|
when 12 => result := 16#029#;
|
when 12 => result := 16#029#;
|
when 13 => result := 16#014#;
|
when 13 => result := 16#014#;
|
when 14 => result := 16#0A#;
|
when 14 => result := 16#0A#;
|
when 15 => result := 16#05#;
|
when 15 => result := 16#05#;
|
when 16 => result := 16#03#;
|
when 16 => result := 16#03#;
|
when 17 => result := 16#01#;
|
when 17 => result := 16#01#;
|
when others => result := 16#0#;
|
when others => result := 16#0#;
|
end case;
|
end case;
|
return result;
|
return result;
|
end CATAN;
|
end CATAN;
|
|
|
-- function Delta is actually an arithmatic shift right
|
-- function Delta is actually an arithmatic shift right
|
-- This strange construction is needed for compatibility with Xilinx WebPack
|
-- This strange construction is needed for compatibility with Xilinx WebPack
|
function Delta(Arg : signed; Cnt : natural) return signed is
|
function Delta(Arg : signed; Cnt : natural) return signed is
|
variable tmp : signed(Arg'range);
|
variable tmp : signed(Arg'range);
|
constant lo : integer := Arg'high -cnt +1;
|
constant lo : integer := Arg'high -cnt +1;
|
begin
|
begin
|
for n in Arg'high downto lo loop
|
for n in Arg'high downto lo loop
|
tmp(n) := Arg(Arg'high);
|
tmp(n) := Arg(Arg'high);
|
end loop;
|
end loop;
|
for n in Arg'high -cnt downto 0 loop
|
for n in Arg'high -cnt downto 0 loop
|
tmp(n) := Arg(n +cnt);
|
tmp(n) := Arg(n +cnt);
|
end loop;
|
end loop;
|
return tmp;
|
return tmp;
|
end function Delta;
|
end function Delta;
|
|
|
function AddSub(dataa, datab : in signed; add_sub : in std_logic) return signed is
|
function AddSub(dataa, datab : in signed; add_sub : in std_logic) return signed is
|
begin
|
begin
|
if (add_sub = '1') then
|
if (add_sub = '1') then
|
return dataa + datab;
|
return dataa + datab;
|
else
|
else
|
return dataa - datab;
|
return dataa - datab;
|
end if;
|
end if;
|
end;
|
end;
|
|
|
--
|
--
|
-- ARCHITECTURE BODY
|
-- ARCHITECTURE BODY
|
--
|
--
|
signal dX, Xresult : signed(WIDTH -1 downto 0);
|
signal dX, Xresult : signed(WIDTH -1 downto 0);
|
signal dY, Yresult : signed(WIDTH -1 downto 0);
|
signal dY, Yresult : signed(WIDTH -1 downto 0);
|
signal atan, Zresult : signed(19 downto 0);
|
signal atan, Zresult : signed(19 downto 0);
|
|
|
signal Zneg, Zpos : std_logic;
|
signal Zneg, Zpos : std_logic;
|
|
|
begin
|
begin
|
|
|
dX <= Delta(Xi, PIPEID);
|
dX <= Delta(Xi, PIPEID);
|
dY <= Delta(Yi, PIPEID);
|
dY <= Delta(Yi, PIPEID);
|
atan <= conv_signed( catan(PIPEID), 20);
|
atan <= conv_signed( catan(PIPEID), 20);
|
|
|
-- generate adder structures
|
-- generate adder structures
|
Zneg <= Zi(19);
|
Zneg <= Zi(19);
|
Zpos <= not Zi(19);
|
Zpos <= not Zi(19);
|
|
|
-- xadd
|
-- xadd
|
Xresult <= AddSub(Xi, dY, Zneg);
|
Xresult <= AddSub(Xi, dY, Zneg);
|
|
|
-- yadd
|
-- yadd
|
Yresult <= AddSub(Yi, dX, Zpos);
|
Yresult <= AddSub(Yi, dX, Zpos);
|
|
|
-- zadd
|
-- zadd
|
Zresult <= AddSub(Zi, atan, Zneg);
|
Zresult <= AddSub(Zi, atan, Zneg);
|
|
|
gen_regs: process(clk)
|
gen_regs: process(clk)
|
begin
|
begin
|
if(clk'event and clk='1') then
|
if(clk'event and clk='1') then
|
if (ena = '1') then
|
if (ena = '1') then
|
Xo <= Xresult;
|
Xo <= Xresult;
|
Yo <= Yresult;
|
Yo <= Yresult;
|
Zo <= Zresult;
|
Zo <= Zresult;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
end architecture dataflow;
|
end architecture dataflow;
|
|
|