0
0
VhdlHow-ToIntermediate · 4 min read

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.