VHDL Code for CORDIC Algorithm: Syntax and Example
The
CORDIC algorithm in VHDL is implemented using iterative shift-add operations inside a process block. You define input angle and output sine and cosine signals, then use a loop to rotate vectors step-by-step. This approach efficiently calculates trigonometric functions without multipliers.Syntax
The basic structure of a CORDIC algorithm in VHDL includes defining input and output ports, internal signals for angle and vector components, and a process that performs iterative rotations using shifts and adds.
- entity: Declares inputs (angle) and outputs (sine, cosine).
- architecture: Contains the algorithm logic.
- process: Runs on clock or trigger to perform iterations.
- shift operations: Used instead of multiplication for efficiency.
- lookup table: Holds arctangent values for each iteration.
vhdl
entity cordic is
Port (
clk : in std_logic;
reset : in std_logic;
angle : in signed(15 downto 0); -- input angle in radians (fixed-point)
sine : out signed(15 downto 0); -- output sine value
cosine : out signed(15 downto 0) -- output cosine value
);
end cordic;
architecture Behavioral of cordic is
-- Constants and signals for iterations
constant ITERATIONS : integer := 16;
type atan_array is array (0 to ITERATIONS-1) of signed(15 downto 0);
constant atan_table : atan_array := (
to_signed(25735,16), -- arctan(2^-0) in fixed-point
to_signed(15192,16), -- arctan(2^-1)
to_signed(8027,16), -- arctan(2^-2)
to_signed(4074,16), -- arctan(2^-3)
to_signed(2045,16), -- arctan(2^-4)
to_signed(1023,16), -- arctan(2^-5)
to_signed(512,16), -- arctan(2^-6)
to_signed(256,16), -- arctan(2^-7)
to_signed(128,16), -- arctan(2^-8)
to_signed(64,16), -- arctan(2^-9)
to_signed(32,16), -- arctan(2^-10)
to_signed(16,16), -- arctan(2^-11)
to_signed(8,16), -- arctan(2^-12)
to_signed(4,16), -- arctan(2^-13)
to_signed(2,16), -- arctan(2^-14)
to_signed(1,16) -- arctan(2^-15)
);
signal x, y, z : signed(15 downto 0);
signal x_new, y_new, z_new : signed(15 downto 0);
signal i : integer := 0;
begin
process(clk, reset)
begin
if reset = '1' then
x <= to_signed(16384,16); -- K factor approx 0.607 * 2^14
y <= to_signed(0,16);
z <= angle;
i <= 0;
elsif rising_edge(clk) then
if i < ITERATIONS then
if z(15) = '0' then -- z >= 0
x_new <= x - (y sra i);
y_new <= y + (x sra i);
z_new <= z - atan_table(i);
else
x_new <= x + (y sra i);
y_new <= y - (x sra i);
z_new <= z + atan_table(i);
end if;
x <= x_new;
y <= y_new;
z <= z_new;
i <= i + 1;
end if;
end if;
end process;
sine <= y;
cosine <= x;
end Behavioral;Example
This example shows a complete VHDL implementation of the CORDIC algorithm that calculates sine and cosine for a given fixed-point angle input. It uses 16 iterations for good precision and outputs fixed-point sine and cosine values.
vhdl
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity cordic is
Port (
clk : in std_logic;
reset : in std_logic;
angle : in signed(15 downto 0); -- input angle in radians (Q2.14 format)
sine : out signed(15 downto 0); -- output sine (Q2.14 format)
cosine : out signed(15 downto 0) -- output cosine (Q2.14 format)
);
end cordic;
architecture Behavioral of cordic is
constant ITERATIONS : integer := 16;
type atan_array is array (0 to ITERATIONS-1) of signed(15 downto 0);
constant atan_table : atan_array := (
to_signed(25735,16), to_signed(15192,16), to_signed(8027,16), to_signed(4074,16),
to_signed(2045,16), to_signed(1023,16), to_signed(512,16), to_signed(256,16),
to_signed(128,16), to_signed(64,16), to_signed(32,16), to_signed(16,16),
to_signed(8,16), to_signed(4,16), to_signed(2,16), to_signed(1,16)
);
signal x, y, z : signed(15 downto 0);
signal x_new, y_new, z_new : signed(15 downto 0);
signal i : integer := 0;
begin
process(clk, reset)
begin
if reset = '1' then
x <= to_signed(10000,16); -- approx K factor scaled
y <= to_signed(0,16);
z <= angle;
i <= 0;
elsif rising_edge(clk) then
if i < ITERATIONS then
if z(15) = '0' then
x_new <= x - (y sra i);
y_new <= y + (x sra i);
z_new <= z - atan_table(i);
else
x_new <= x + (y sra i);
y_new <= y - (x sra i);
z_new <= z + atan_table(i);
end if;
x <= x_new;
y <= y_new;
z <= z_new;
i <= i + 1;
end if;
end if;
end process;
sine <= y;
cosine <= x;
end Behavioral;Common Pitfalls
Common mistakes when implementing CORDIC in VHDL include:
- Not scaling the initial vector by the CORDIC gain factor, which causes incorrect amplitude.
- Incorrect fixed-point format causing overflow or loss of precision.
- Using signed arithmetic without proper handling of sign bits.
- Forgetting to limit the number of iterations, leading to infinite loops.
- Misinterpreting the angle input range and format.
Always verify fixed-point formats and initialize signals correctly.
vhdl
---- Wrong: No scaling factor applied x <= to_signed(16384,16); -- should be scaled by K factor (~0.607 * 2^14) ---- Right: Apply scaling factor x <= to_signed(10000,16); -- scaled initial vector for correct amplitude
Quick Reference
Key points for VHDL CORDIC implementation:
- Use fixed-point signed numbers for angle and outputs.
- Precompute arctangent values in a constant table.
- Perform iterative rotations using shifts and adds.
- Initialize vector with scaling factor (~0.607) to get correct amplitude.
- Limit iterations for desired precision and performance.
Key Takeaways
Implement CORDIC in VHDL using iterative shift-add rotations and a lookup table of arctangents.
Always scale the initial vector by the CORDIC gain factor to get correct sine and cosine amplitudes.
Use fixed-point signed arithmetic carefully to avoid overflow and precision loss.
Limit the number of iterations to balance accuracy and hardware resource use.
Test with known angles to verify output correctness.