cordic¶
Dependencies¶
Description¶
This package provides components and procedures used to implement the CORDIC algorithm for rotations. A variety of implementations are provided to meet different design requirements. These implementations are flexible in all parameters and are not constrained by a fixed arctan table.
A pair of procedures provide pure combinational CORDIC implementations:
- rotate procedure - Combinational CORDIC in rotation mode
- vector procedure - Combinational CORDIC in vectoring mode
The CORDIC components provide both rotation or vectoring mode based on a Mode input:
- cordic_sequential - Iterative algorithm with minimal hardware
- cordic_pipelined - One pipeline stage per iteration
- cordic_flex_pipelined - Selectable pipeline stages independent of
- the number of iterations
A set of wrapper components are provided to conveniently generate sin and cos:
- sincos_sequential - Iterative algorithm with minimal hardware
- sincos_pipelined - One pipeline stage per iteration
These CORDIC implementations take a common set of parameters. There are X, Y, and Z inputs defining the initial vector and angle value. The result is produced in a set of X, Y, and Z outputs. Depending on which CORDIC operation you are using, some inputs may be constants and some outputs may be ignored.
The CORDIC algorithm performs pseudo-rotations that cause an unwanted growth
in the length of the result vector. This growth is a gain parameter that
approaches 1.647 but is dependent on the number of iterations performed. The
cordic_gain()
function produces a real-valued gain for a specified number of
iterations. This can be converted to a synthesizable integer constant with
the following:
gain := integer(cordic_gain(ITERATIONS) * 2.0 ** FRAC_BITS)
With some operations you can adjust the input vector by dividing by the gain ahead of time. In other cases you have to correct for the gain after the CORDIC operation. The gain from pseudo-rotation never affects the Z parameter.
The following are some of the operations that can be performed with the CORDIC algorithm:
sin and cos:
X0 = 1/gain, Y0 = 0, Z0 = angle; rotate → sin(Z0) in Y, cos(Z0) in X
polar to rectangular:
X0 = magnitude, Y0 = 0, Z0 = angle; rotate → gain*X in X, gain*Y in Y
arctan:
Y0 = y, X0 = x, Z0 = 0; vector → arctan(Y0/X0) in Z
rectangular to polar:
Y0 = y, X0 = x, Z0 = 0; vector → gain*magnitude in X, angle in Z
The X and Y parameters are represented as unconstrained signed vectors. You establish the precision of a CORDIC implementation by selecting the width of these vectors. The interpretation of these numbers does not affect the internal CORDIC implementation but most implementations will need them to be fixed point integers with the maximum number of fractional bits possible. When calculating sin and cos, the output is constrained to the range +/-1.0. Thus we only need to reserve two bits for the sign and integral portion of the numbers. The remaining bits can be fractional. Operations that work on larger vectors outside of the unit circle need to ensure that a sufficient number of integer bits are present to prevent overflow of X and Y.
The angle parameter Z should be provided in units of binary-radians or brads. \(2\pi \text{ radians} = 2^\text{size} \text{ brads}\) for “size” number of bits. This maps the entire binary range of Z to the unit circle. The Z parameter is represented by the signed type in all of these CORDIC implementations but it can be viewed as an unsigned value. Because of the circular mapping, signed and unsigned angles are equivalent. It is easiest to think of the angle Z as an integer without fractional bits like X and Y. There is no risk of overflowing Z becuase of the circular mapping.
The circular CORDIC algorithm only converges between angles of +/- 99.7
degrees. If you want to use angles covering all four quadrants you must
condition the inputs to the CORDIC algorithm using the adjust_angle()
procedure. This will perform conditional negation on X and Y and flip the
sign bit on Z to bring vectors in quadrants 2 and 3 (1-based) into quadrants
1 and 4.
Example usage¶
You can use the two functions rotate()
and
vector()
to perform a single iteration cycle of CORDIC.
This can be used for simulation purposes or wrapped in a registered process for specialized
synthesis implementations. The entire CORDIC core will be synthesized as a combinational blob. You can use register retiming techniques to improve the performance.
signal X, Y, Z, Xr, Yr, Zr : signed(9 downto 0);
constant ITERATIONS : integer : 5;
...
reg: process(clock, reset) is
begin
if reset = '1' then
Xr <= (others => '0');
Yr <= (others => '0');
Zr <= (others => '0');
elsif rising_edge(clock) then
rotate(ITERATIONS, X, Y, Z, Xr, Yr, Zr);
end if;
end process;
The components implemented in this package offer a number of different synthesizable CORDIC implementations and wrappers to generate Sine and Cosine waveforms.
constant ITERATIONS : positive := 8;
-- 1 sign bit + 1 integer bit + 8 fraction bits
signal X, Y, Z, Xr, Yr, Zr : signed(9 downto 0);
-- Sequential implementation
cs: cordic_sequential
generic map (
SIZE => X'length,
ITERATIONS => ITERATIONS
)
port map (
Clock => clock,
Reset => reset,
Data_valid => data_valid,
Busy => busy,
Result_valid => result_valid,
Mode => cordic_rotate,
X => X,
Y => Y,
Z => Z,
X_result => Xr,
Y_result => Yr,
Z_result => Zr
);
Components¶
cordic_pipelined¶
-
cordic.
cordic_pipelined
¶ CORDIC with pipeline registers between each stage.
Generics: - SIZE (positive) – Width of operands
- ITERATIONS (positive) – Number of iterations for CORDIC algorithm
- RESET_ACTIVE_LEVEL (std_ulogic) – Asynch. reset control level
Port: - Clock (in std_ulogic) – System clock
- Reset (in std_ulogic) – Asynchronous reset
- Mode (in cordic_mode) – Rotation or vector mode selection
- X (in signed(SIZE-1 downto 0)) – X coordinate
- Y (in signed(SIZE-1 downto 0)) – Y coordinate
- Z (in signed(SIZE-1 downto 0)) – Z coordinate (angle in brads)
- X_result (out signed(SIZE-1 downto 0)) – X result
- Y_result (out signed(SIZE-1 downto 0)) – Y result
- Z_result (out signed(SIZE-1 downto 0)) – Z result
cordic_sequential¶
-
cordic.
cordic_sequential
¶ CORDIC with a single stage applied iteratively.
Generics: - SIZE (positive) – Width of operands
- ITERATIONS (positive) – Number of iterations for CORDIC algorithm
- RESET_ACTIVE_LEVEL (std_ulogic) – Asynch. reset control level
Port: - Clock (in std_ulogic) – System clock
- Reset (in std_ulogic) – Asynchronous reset
- Data_valid (in std_ulogic) – Load new input data
- Busy (out std_ulogic) – Generating new result
- Result_valid (out std_ulogic) – Flag when result is valid
- Mode (in cordic_mode) – Rotation or vector mode selection
- X (in signed(SIZE-1 downto 0)) – X coordinate
- Y (in signed(SIZE-1 downto 0)) – Y coordinate
- Z (in signed(SIZE-1 downto 0)) – Z coordinate (angle in brads)
- X_result (out signed(SIZE-1 downto 0)) – X result
- Y_result (out signed(SIZE-1 downto 0)) – Y result
- Z_result (out signed(SIZE-1 downto 0)) – Z result
cordic_flex_pipelined¶
-
cordic.
cordic_flex_pipelined
¶ CORDIC with pipelining implemented with register retiming. This variant can be used to have more or fewer pipeline stages than the number of iterations to fine tune performance and resource usage.
Generics: - SIZE (positive) – Width of operands
- ITERATIONS (positive) – Number of iterations for CORDIC algorithm
- PIPELINE_STAGES (natural) – Number of register stages
- RESET_ACTIVE_LEVEL (std_ulogic) – Asynch. reset control level
Port: - Clock (in std_ulogic) – System clock
- Reset (in std_ulogic) – Asynchronous reset
- Mode (in cordic_mode) – Rotation or vector mode selection
- X (in signed(SIZE-1 downto 0)) – X coordinate
- Y (in signed(SIZE-1 downto 0)) – Y coordinate
- Z (in signed(SIZE-1 downto 0)) – Z coordinate (angle in brads)
- X_result (out signed(SIZE-1 downto 0)) – X result
- Y_result (out signed(SIZE-1 downto 0)) – Y result
- Z_result (out signed(SIZE-1 downto 0)) – Z result
sincos_pipelined¶
-
cordic.
sincos_pipelined
¶ Compute Sine and Cosine with a pipelined CORDIC implementation.
Generics: - SIZE (positive) – Width of operands
- ITERATIONS (positive) – Number of iterations for CORDIC algorithm
- FRAC_BITS (positive) – Total fractional bits
- MAGNITUDE (real) – Scale factor for vector length
- RESET_ACTIVE_LEVEL (std_ulogic) – Asynch. reset control level
Port: - Clock (in std_ulogic) – System clock
- Reset (in std_ulogic) – Asynchronous reset
- Angle (in signed(SIZE-1 downto 0)) – Angle in brads (2**SIZE brads = 2*pi radians)
- Sin (out signed(SIZE-1 downto 0)) – Sine of Angle
- Cos (out signed(SIZE-1 downto 0)) – Cosine of Angle
sincos_sequential¶
-
cordic.
sincos_sequential
¶ Compute Sine and Cosine with a sequential CORDIC implementation.
Generics: - SIZE (positive) – Width of operands
- ITERATIONS (positive) – Number of iterations for CORDIC algorithm
- FRAC_BITS (positive) – Total fractional bits
- MAGNITUDE (real) – Scale factor for vector length
- RESET_ACTIVE_LEVEL (std_ulogic) – Asynch. reset control level
Port: - Clock (in std_ulogic) – System clock
- Reset (in std_ulogic) – Asynchronous reset
- Data_valid (in std_ulogic) – Load new input data
- Busy (out std_ulogic) – Generating new result
- Result_valid (out std_ulogic) – Flag when result is valid
- Angle (in signed(SIZE-1 downto 0)) – Angle in brads (2**SIZE brads = 2*pi radians)
- Sin (out signed(SIZE-1 downto 0)) – Sine of Angle
- Cos (out signed(SIZE-1 downto 0)) – Cosine of Angle
Subprograms¶
-
cordic.
cordic_gain
(Iterations : positive) → real¶ - Compute vector length gain after applying CORDIC.
Parameters: - Iterations (positive) – Number of iterations
Returns: Gain factor.
-
cordic.
adjust_angle
(X : in signed; Y : in signed; Z : in signed; Xa : out signed; Ya : out signed; Za : out signed)¶ - Correct angle so that it lies in quadrant 1 or 4.
Parameters: - X (in signed) – X coordinate
- Y (in signed) – Y coordinate
- Z (in signed) – Z coordinate (angle)
- Xa (out signed) – Adjusted X coordinate
- Ya (out signed) – Adjusted Y coordinate
- Za (out signed) – Adjusted Z coordinate (angle)
-
cordic.
rotate
(iterations : in integer; X : in signed; Y : in signed; Z : in signed; Xr : out signed; Yr : out signed; Zr : out signed)¶ - Apply a single iteration of CORDIC rotation mode.
Parameters: - X (in signed) – X coordinate
- Y (in signed) – Y coordinate
- Z (in signed) – Z coordinate (angle)
- Xr (out signed) – Rotated X coordinate
- Yr (out signed) – Rotated Y coordinate
- Zr (out signed) – Rotated Z coordinate (angle)
-
cordic.
vector
(iterations : in integer; X : in signed; Y : in signed; Z : in signed; Xr : out signed; Yr : out signed; Zr : out signed)¶ - Apply a single iteration of CORDIC vector mode.
Parameters: - X (in signed) – X coordinate
- Y (in signed) – Y coordinate
- Z (in signed) – Z coordinate (angle)
- Xr (out signed) – Vectored X coordinate
- Yr (out signed) – Vectored Y coordinate
- Zr (out signed) – Vectored Z coordinate (angle)
-
cordic.
effective_fractional_bits
(Iterations : positive; Frac_bits : positive) → real¶ - Compute the number of usable fractional bits in CORDIC result.
Parameters: - Iterations (positive) – Number of CORDIC iterations
- Frac_bits (positive) – Fractional bits in the input coordinates
Returns: Effective number of fractional bits.