Jump to content

    
Sign in to follow this  
Deflop

Алгоритм Cordic на ПЛИС

Recommended Posts

Здравствуйте, подскажите пожалуйста кто работал с данным алгоритмом.

Хочу на ПЛИС применить данный алгоритм для вычисления Cos и Sin и углов по X,Y. За основу брал готовый исходник с тестбенч. 

Что нужно чтобы алгоритм работал? Как и куда подставить входные данные, чтобы алгоритм полностью функционировал без тестбенча.

verilog_cordic_core-master.zip

Share this post


Link to post
Share on other sites

Странный вопрос.

ПЛИС - это микросхема, которая стоит на какой-то плате. С внешним миром ПЛИС взаимодействует через какие-то интерфейсы, которые реализованы на этой плате. Через эти интерфейсы в ПЛИС и далее на ваш модуль и надо подавать X  и Y. Но чтобы разработать и протестировать этот ваш модуль используется симулятор и тестбенч.

Share this post


Link to post
Share on other sites

Принцип работы ПЛИС я понимаю, проблема в том  в каком виде и в каком месте нужно подставить на вход углы например в радианах? Нужно создавать отдельный модуль или можно уже в представленном выше примере добавить? 

Если не сложно приведите пример как сделать?

Share this post


Link to post
Share on other sites

Вы где эти  X и Y брать собираетесь? Хотите просто задать константой в проекте, откомпилировать и чипскопом/сигналтапом посмотреть результат?

Share this post


Link to post
Share on other sites

А в чём смысл? Константы и на бумаге можно обсчитать :)

А если серьёзно, то при подаче константы синтезатор упростит схему(так сказать "обсчитает на бумаге") и по результатам синтеза не будет понятно ни сколько ресурсов займёт схема, ни максимальная частота её работы. Поэтому лучше, переделать тестбетч, который у вас уже есть, так, чтобы он синтезировался в ПЛИС и сделать его верхним файлом проекта ПЛИС.

Share this post


Link to post
Share on other sites

Вы ничего не сказали про нужные Вам точность и разрядность. Если, точность не велика, то можно обойтись и без Кордика, табличным методом. Например, разбить аргумент - x на две части -- старшие разряды - a, и младшие - b. Тогда:

sin(x) = sin(a + b) = sin(a)*cos(b) + cos(a)*sin(b).    sin(a) и cos(a) - задать таблично, а поскольку b - мал, принять cos(b) = 1, sin(b) = b. В результате sin(x) = sin(a) + b*cos(a).

Share this post


Link to post
Share on other sites
1 hour ago, vladec said:

В результате sin(x) = sin(a) + b*cos(b).

Чисто ради интереса, какую точность можно получить с таким методом? Я когда-то пытался генерировать синусоиду для PWM, но по незнанию я просто записал 1024 значения для четвертьпериода и счётчиком+полярностью задавал нужную фазу/последовательность. Просто интересно насколько у меня хуже получались данные

Share this post


Link to post
Share on other sites
1 час назад, Nick_K сказал:

Чисто ради интереса, какую точность можно получить с таким методом?

Так все зависит от размера таблицы sin и cos. a - это у Вас старшие n - бит  аргумента - x, при этом размер таблицы 2^^n (а это блочная память в ПЛИС). И чем меньше разрядов остается в - b, тем точнее.

Кстати в формуле описался -- исправил.

Share this post


Link to post
Share on other sites
This code calculates sin() and cos() using CORDIC, and compares the results with that of the floating point library. The input angle is scaled so 2^24 is the full circle.

#include "stdafx.h"
#include <stdio.h>
#include <math.h>
#include <stdint.h>

#define PI (3.14159265358979323846)
#define FULL_CIRCLE (1<<24)
#define EIGHTH_CIRCLE (FULL_CIRCLE/8)
#define QUARTER_CIRCLE (FULL_CIRCLE/4)
#define HALF_CIRCLE (FULL_CIRCLE/2)
#define CORDIC_REPS (30)
#define BITS (30)

int64_t initial;
double angles[CORDIC_REPS];
/****************************************************************
* Calculate the values required for CORDIC sin()/cos() function
***************************************************************/
void setup(void) {
int i;
double scale = pow(0.5, 0.5);

for (i = 0; i < CORDIC_REPS; i++) {
double angle = atan(1.0 / pow(2, i + 1));
angles[i] = FULL_CIRCLE angle / (2 PI);
scale *= cos(angle);
printf("angle[%i] = %13.9f\n", i, angles[i]);
}
initial = (int64_t)(scale*pow(2.0, BITS));
}

/***************************************************************
* Cordic routine to calculate Sine and Cosine for angles
* from 0.0 to 2*PI
**************************************************************/
void cordic_sine_cosine(double z, int64_t& s, int64_t& c) {
int i, flip_sine_sign = 0, flip_cos_sign = 0;
int64_t x = initial, y = initial;
if (z > HALF_CIRCLE) {
z = FULL_CIRCLE - z;
flip_sine_sign = 1;
}

if (z > QUARTER_CIRCLE) {
z = HALF_CIRCLE - z;
flip_cos_sign = 1;
}
z -= EIGHTH_CIRCLE;
for (i = 0; i < CORDIC_REPS; i++) {
int64_t tx = (x + ((int64_t)1 << i)) >> (i + 1);
int64_t ty = (y + ((int64_t)1 << i)) >> (i + 1);
x -= (z > 0 ? ty : -ty);
y += (z > 0 ? tx : -tx);
z -= (z > 0 ? angles[i] : -angles[i]);
}
c = flip_cos_sign ? -x : x;
s = flip_sine_sign ? -y : y;
}

/**************************************************************/
int main(int argc, char *argv[]) {
double a = 0.8, max = 0.0;
double total_e = 0.0;
int count = 0;
setup();

for (a = 0; a < FULL_CIRCLE; a++) {
int64_t s, c;
double es, ec;

cordic_sine_cosine(a, s, c);
es = s - (int64_t)(sin(a*(2 * PI / FULL_CIRCLE))*(pow(2, BITS)));
ec = c - (int64_t)(cos(a*(2 * PI / FULL_CIRCLE))*(pow(2, BITS)));


if (es > 0) total_e += es;
else total_e -= es;

if (ec > 0) total_e += ec;
else total_e -= ec;

if (max < es) max = es;
if (max < -es) max = -es;
if (max < ec) max = ec;
if (max < -ec) max = -ec;
count++;
}
printf("Error is %13.11f per calcuation out of +/-%f\n", total_e / count, pow(2, BITS));
printf("Max error is %13.11f\n", max);
return 0;
}


Source VHDL: 

cordic_sin_cos.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity cordic_sin_cos is
    Port ( clk        : in  STD_LOGIC;
           angle      : in  STD_LOGIC_VECTOR (23 downto 0);
           signed_sin : out STD_LOGIC_VECTOR (23 downto 0) := (others => '0');
           signed_cos : out STD_LOGIC_VECTOR (23 downto 0) := (others => '0'));
end cordic_sin_cos;

architecture Behavioral of cordic_sin_cos is
    constant stages    : natural := 26;
    constant calc_bits : natural := 28;
    constant z_bits    : natural := 29;

    -- Angles for the CORDIC algorithm in fixed decimal (eg. 0x4b90147 ~= atan(0.5))
    type a_angles is array(0 to stages) of signed(z_bits-2 downto 0);
    constant angles : a_angles := (
            x"4b90147", x"27ece16", x"1444475", x"0a2c350", x"05175f8", x"028bd87",
            x"0145f15", x"00a2f94", x"00517cb", x"0028be6", x"00145f3", x"000a2f9",
            x"000517c", x"00028be", x"000145f", x"0000a2f", x"0000517", x"000028b",
            x"0000145", x"00000a2", x"0000051", x"0000028", x"0000014", x"000000a",
            x"0000005", x"0000002", x"0000001");

    -- Adjusted to give full scale of +0x7FFFF & -0x7FFFF
    constant initial      : signed(calc_bits-1 downto 0) := x"4dba76c";
    
    -- Constants for quadrant calulations
    constant quarter_turn : signed(z_bits-1 downto 0)    := "10000" & x"000000";
    constant eigth_turn   : signed(z_bits-1 downto 0)    := "01000" & x"000000";
    constant zero         : signed(signed_sin'high downto 0) := (others => '0');
    signal quadrant_angle : signed(z_bits-1 downto 0)    := (others => '0');

    -- Pipeline for holding the quadrant information
    signal flip_cos : std_logic_vector(stages+1 downto 0);
    signal flip_sin : std_logic_vector(stages+1 downto 0);
    
    -- Pipeline for CORDIC X, Y & Z state variables positions
    type a_x_or_y is array(0 to stages+1) of signed(calc_bits-1 downto 0);
    type a_z      is array(0 to stages+1) of signed(z_bits-1 downto 0);
    signal x       : a_x_or_y := (0 => initial, others => (others => '0'));
    signal y       : a_x_or_y := (0 => initial, others => (others => '0'));
    signal z       : a_z      := (others => (others => '0'));

begin

    quadrant_angle(quadrant_angle'high-1 downto quadrant_angle'high-angle'high+1)  <= signed(angle(angle'high-2 downto 0));

process(clk)
    begin
        if rising_edge(clk) then
            -- The Output stages
            if flip_sin(stages+1) = '0' then
                signed_sin <= STD_LOGIC_VECTOR (zero + y(stages+1)(calc_bits-1 downto calc_bits-signed_sin'length));
            else
                signed_sin <= STD_LOGIC_VECTOR (zero - y(stages+1)(calc_bits-1 downto calc_bits-signed_sin'length));
            end if;

            if flip_cos(stages+1) = '0' then
                signed_cos <= STD_LOGIC_VECTOR (zero + x(stages+1)(calc_bits-1 downto calc_bits-signed_cos'length));
            else
                signed_cos <= STD_LOGIC_VECTOR (zero - x(stages+1)(calc_bits-1 downto calc_bits-signed_cos'length));
            end if;
            
            -- The actual CORDIC stages
            for i in 0 to stages loop
                if z(i)(z_bits-1) = '0' then
                    x(i+1) <= x(i) - resize(y(i)(calc_bits-1 downto i+1),calc_bits);
                    y(i+1) <= y(i) + resize(x(i)(calc_bits-1 downto i+1),calc_bits);
                    z(i+1) <= z(i) - angles(i);
                else
                    x(i+1) <= x(i) + resize(y(i)(calc_bits-1 downto i+1),calc_bits);
                    y(i+1) <= y(i) - resize(x(i)(calc_bits-1 downto i+1),calc_bits);
                    z(i+1) <= z(i) + angles(i);
                end if;
                flip_sin(i+1) <= flip_sin(i);
                flip_cos(i+1) <= flip_cos(i);
            end loop;

            -- Setup for the CORDIC algorithm, which only works on the first quadrant of a circle
            case angle(angle'high downto angle'high-1) is
                when "00" =>
                    flip_sin(0) <= '0';
                    flip_cos(0) <= '0';
                    z(0) <=                quadrant_angle - eigth_turn;
                when "01" =>  
                    flip_sin(0) <= '0';
                    flip_cos(0) <= '1';
                    z(0) <= quarter_turn - quadrant_angle - eigth_turn;
                when "10" =>
                    flip_sin(0) <= '1';
                    flip_cos(0) <= '1';
                    z(0) <=                quadrant_angle - eigth_turn;
                when others =>
                    flip_sin(0) <= '1';
                    flip_cos(0) <= '0';
                    z(0) <= quarter_turn - quadrant_angle - eigth_turn;
            end case;
        end if;
    end process;
end Behavioral;

 

Share this post


Link to post
Share on other sites
4 hours ago, Nick_K said:

Чисто ради интереса, какую точность можно получить с таким методом?

Если добавить пару таблиц для малых углов, то точность будет предельная, или очень к ней близкая. Даже не оптимизируя по памяти, в 1024 ячейки можно вместить 4 таблицы, полный оборот для синуса и косинуса, малые углы для синуса и косинуса. 4 таблицы по 256 значений. 8 бит грубых углов, 8 бит точных углов. Итого угол 16 бит. В 16 раза точнее Вашего. Оптимизируя, можно уместить в 576 ячеек. Делая иное разбиение разрядов, можно и меньше. 

Как то так ...

Edited by Strob

Share this post


Link to post
Share on other sites
8 hours ago, vladec said:

Вы ничего не сказали про нужные Вам точность и разрядность. Если, точность не велика, то можно обойтись и без Кордика, табличным методом. Например, разбить аргумент - x на две части -- старшие разряды - a, и младшие - b. Тогда:

sin(x) = sin(a + b) = sin(a)*cos(b) + cos(a)*sin(b).    sin(a) и cos(a) - задать таблично, а поскольку b - мал, принять cos(b) = 1, sin(b) = b. В результате sin(x) = sin(a) + b*cos(a).

Высокая точность не важна пока. Можете привести пример программы как сделать без реализации данного алгоритма (табличным методом). 

Share this post


Link to post
Share on other sites
1 hour ago, Deflop said:

Высокая точность не важна пока. Можете привести пример программы как сделать без реализации данного алгоритма (табличным методом). 

Как пример реализовать генерацию синуса приведено ниже:

-- Module Name: sine_table - Behavioral
-- Description: A lookup table with interpolation for sin(x) function
-- 
-- To help with the coding, this actually returns sin(x+2*pi/8192)
-- subtract 0x70 from 'phase' to keep the zero crossing at zero.  
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity sine_table is
    Port ( clk : in STD_LOGIC;
           phase : in STD_LOGIC_VECTOR (17 downto 0);
           sine : out STD_LOGIC_VECTOR (19 downto 0));
end sine_table;

architecture Behavioral of sine_table is
    signal sine_sum    : unsigned(9+phase'high downto 0) := (others => '0');
    
    signal sine_mult_1 : unsigned(9+phase'high downto 0)  := (others => '0');
    signal frac_1      : unsigned(phase'high-11 downto 0) := (others => '0');
    signal sine_1      : unsigned(19 downto 0)            := (others => '0');
    signal index_1     : unsigned(11 downto 0)            := (others => '0');
    signal quad_1      : unsigned( 1 downto 0)            := (others => '0');
    signal entry_1     : unsigned( 9 downto 0)            := (others => '0');

    signal sine_mult_2 : unsigned(9+phase'high downto 0) := (others => '0');
    signal frac_2      : unsigned(phase'high-11 downto 0) := (others => '0');
    signal sine_2      : unsigned(19 downto 0)            := (others => '0');
    signal quad_2      : unsigned(1 downto 0)             := (others => '0');
    signal entry_2     : unsigned(9 downto 0)             := (others => '0');
    signal index_2     : unsigned(11 downto 0)            := (others => '0');

    signal frac        : unsigned(phase'high-12 downto 0);

    constant frac_max  : unsigned(phase'high-11 downto 0) := (phase'high-11 => '1', others => '0');
    constant table_max : unsigned(9 downto 0)  := (others => '1');
    constant midrange  : unsigned(19 downto 0) := x"80000";

    type a_mem is array (0 to 1023) of unsigned (19 downto 0);
    signal mem : a_mem := (
        x"000C9", x"0025B", x"003ED", x"0057F", x"00711", x"008A3", x"00A35", x"00BC7",
        x"00D59", x"00EEC", x"0107E", x"01210", x"013A2", x"01534", x"016C6", x"01858",
        x"019EA", x"01B7C", x"01D0E", x"01EA0", x"02032", x"021C4", x"02355", x"024E7",
        x"02679", x"0280B", x"0299D", x"02B2F", x"02CC0", x"02E52", x"02FE4", x"03175",
        x"03307", x"03499", x"0362A", x"037BC", x"0394D", x"03ADF", x"03C70", x"03E02",
        x"03F93", x"04124", x"042B6", x"04447", x"045D8", x"04769", x"048FA", x"04A8B",
        x"04C1C", x"04DAD", x"04F3E", x"050CF", x"05260", x"053F1", x"05582", x"05712",
        x"058A3", x"05A34", x"05BC4", x"05D55", x"05EE5", x"06075", x"06206", x"06396",
        x"06526", x"066B6", x"06846", x"069D6", x"06B66", x"06CF6", x"06E86", x"07016",
        x"071A5", x"07335", x"074C5", x"07654", x"077E3", x"07973", x"07B02", x"07C91",
        x"07E20", x"07FAF", x"0813E", x"082CD", x"0845C", x"085EB", x"08779", x"08908",
        x"08A96", x"08C25", x"08DB3", x"08F41", x"090CF", x"0925D", x"093EB", x"09579",
        x"09707", x"09894", x"09A22", x"09BB0", x"09D3D", x"09ECA", x"0A057", x"0A1E5",
        x"0A372", x"0A4FF", x"0A68B", x"0A818", x"0A9A5", x"0AB31", x"0ACBE", x"0AE4A",
        x"0AFD6", x"0B162", x"0B2EE", x"0B47A", x"0B606", x"0B792", x"0B91D", x"0BAA9",
        x"0BC34", x"0BDBF", x"0BF4A", x"0C0D5", x"0C260", x"0C3EB", x"0C575", x"0C700",
        x"0C88A", x"0CA15", x"0CB9F", x"0CD29", x"0CEB3", x"0D03C", x"0D1C6", x"0D350",
        x"0D4D9", x"0D662", x"0D7EC", x"0D975", x"0DAFD", x"0DC86", x"0DE0F", x"0DF97",
        x"0E120", x"0E2A8", x"0E430", x"0E5B8", x"0E740", x"0E8C7", x"0EA4F", x"0EBD6",
        x"0ED5D", x"0EEE5", x"0F06C", x"0F1F2", x"0F379", x"0F500", x"0F686", x"0F80C",
        x"0F992", x"0FB18", x"0FC9E", x"0FE24", x"0FFA9", x"1012E", x"102B3", x"10438",
        x"105BD", x"10742", x"108C6", x"10A4B", x"10BCF", x"10D53", x"10ED7", x"1105B",
        x"111DE", x"11362", x"114E5", x"11668", x"117EB", x"1196E", x"11AF0", x"11C73",
        x"11DF5", x"11F77", x"120F9", x"1227A", x"123FC", x"1257D", x"126FE", x"1287F",
        x"12A00", x"12B81", x"12D01", x"12E81", x"13002", x"13181", x"13301", x"13481",
        x"13600", x"1377F", x"138FE", x"13A7D", x"13BFC", x"13D7A", x"13EF8", x"14076",
        x"141F4", x"14372", x"144EF", x"1466C", x"147E9", x"14966", x"14AE3", x"14C5F",
        x"14DDC", x"14F58", x"150D3", x"1524F", x"153CB", x"15546", x"156C1", x"1583C",
        x"159B6", x"15B31", x"15CAB", x"15E25", x"15F9F", x"16118", x"16292", x"1640B",
        x"16584", x"166FC", x"16875", x"169ED", x"16B65", x"16CDD", x"16E55", x"16FCC",
        x"17143", x"172BA", x"17431", x"175A7", x"1771E", x"17894", x"17A0A", x"17B7F",
        x"17CF5", x"17E6A", x"17FDF", x"18153", x"182C8", x"1843C", x"185B0", x"18724",
        x"18897", x"18A0A", x"18B7E", x"18CF0", x"18E63", x"18FD5", x"19147", x"192B9",
        x"1942B", x"1959C", x"1970D", x"1987E", x"199EF", x"19B5F", x"19CCF", x"19E3F",
        x"19FAF", x"1A11E", x"1A28D", x"1A3FC", x"1A56B", x"1A6D9", x"1A847", x"1A9B5",
        x"1AB23", x"1AC90", x"1ADFD", x"1AF6A", x"1B0D6", x"1B243", x"1B3AF", x"1B51B",
        x"1B686", x"1B7F1", x"1B95C", x"1BAC7", x"1BC31", x"1BD9C", x"1BF06", x"1C06F",
        x"1C1D9", x"1C342", x"1C4AA", x"1C613", x"1C77B", x"1C8E3", x"1CA4B", x"1CBB3",
        x"1CD1A", x"1CE81", x"1CFE7", x"1D14E", x"1D2B4", x"1D419", x"1D57F", x"1D6E4",
        x"1D849", x"1D9AE", x"1DB12", x"1DC76", x"1DDDA", x"1DF3E", x"1E0A1", x"1E204",
        x"1E366", x"1E4C9", x"1E62B", x"1E78D", x"1E8EE", x"1EA4F", x"1EBB0", x"1ED11",
        x"1EE71", x"1EFD1", x"1F131", x"1F290", x"1F3EF", x"1F54E", x"1F6AC", x"1F80B",
        x"1F968", x"1FAC6", x"1FC23", x"1FD80", x"1FEDD", x"20039", x"20195", x"202F1",
        x"2044C", x"205A8", x"20702", x"2085D", x"209B7", x"20B11", x"20C6A", x"20DC4",
        x"20F1D", x"21075", x"211CD", x"21325", x"2147D", x"215D4", x"2172B", x"21882",
        x"219D8", x"21B2E", x"21C84", x"21DDA", x"21F2F", x"22083", x"221D8", x"2232C",
        x"2247F", x"225D3", x"22726", x"22879", x"229CB", x"22B1D", x"22C6F", x"22DC0",
        x"22F11", x"23062", x"231B3", x"23303", x"23452", x"235A2", x"236F1", x"2383F",
        x"2398E", x"23ADC", x"23C29", x"23D77", x"23EC4", x"24010", x"2415D", x"242A9",
        x"243F4", x"2453F", x"2468A", x"247D5", x"2491F", x"24A69", x"24BB2", x"24CFB",
        x"24E44", x"24F8D", x"250D5", x"2521C", x"25364", x"254AB", x"255F1", x"25738",
        x"2587E", x"259C3", x"25B08", x"25C4D", x"25D92", x"25ED6", x"26019", x"2615D",
        x"262A0", x"263E2", x"26525", x"26666", x"267A8", x"268E9", x"26A2A", x"26B6A",
        x"26CAA", x"26DEA", x"26F29", x"27068", x"271A7", x"272E5", x"27423", x"27560",
        x"2769D", x"277DA", x"27916", x"27A52", x"27B8D", x"27CC8", x"27E03", x"27F3D",
        x"28077", x"281B1", x"282EA", x"28423", x"2855B", x"28693", x"287CB", x"28902",
        x"28A39", x"28B6F", x"28CA5", x"28DDB", x"28F10", x"29045", x"2917A", x"292AE",
        x"293E2", x"29515", x"29648", x"2977A", x"298AC", x"299DE", x"29B0F", x"29C40",
        x"29D71", x"29EA1", x"29FD0", x"2A100", x"2A22F", x"2A35D", x"2A48B", x"2A5B9",
        x"2A6E6", x"2A813", x"2A93F", x"2AA6B", x"2AB97", x"2ACC2", x"2ADED", x"2AF17",
        x"2B041", x"2B16B", x"2B294", x"2B3BD", x"2B4E5", x"2B60D", x"2B734", x"2B85B",
        x"2B982", x"2BAA8", x"2BBCE", x"2BCF3", x"2BE18", x"2BF3D", x"2C061", x"2C184",
        x"2C2A8", x"2C3CA", x"2C4ED", x"2C60F", x"2C730", x"2C851", x"2C972", x"2CA92",
        x"2CBB2", x"2CCD2", x"2CDF0", x"2CF0F", x"2D02D", x"2D14B", x"2D268", x"2D385",
        x"2D4A1", x"2D5BD", x"2D6D8", x"2D7F3", x"2D90E", x"2DA28", x"2DB42", x"2DC5B",
        x"2DD74", x"2DE8C", x"2DFA4", x"2E0BC", x"2E1D3", x"2E2EA", x"2E400", x"2E515",
        x"2E62B", x"2E740", x"2E854", x"2E968", x"2EA7B", x"2EB8E", x"2ECA1", x"2EDB3",
        x"2EEC5", x"2EFD6", x"2F0E7", x"2F1F7", x"2F307", x"2F416", x"2F525", x"2F634",
        x"2F742", x"2F850", x"2F95D", x"2FA69", x"2FB76", x"2FC81", x"2FD8D", x"2FE97",
        x"2FFA2", x"300AC", x"301B5", x"302BE", x"303C7", x"304CF", x"305D6", x"306DD",
        x"307E4", x"308EA", x"309F0", x"30AF5", x"30BFA", x"30CFE", x"30E02", x"30F06",
        x"31009", x"3110B", x"3120D", x"3130E", x"3140F", x"31510", x"31610", x"31710",
        x"3180F", x"3190D", x"31A0B", x"31B09", x"31C06", x"31D03", x"31DFF", x"31EFB",
        x"31FF6", x"320F1", x"321EB", x"322E5", x"323DF", x"324D7", x"325D0", x"326C8",
        x"327BF", x"328B6", x"329AC", x"32AA2", x"32B98", x"32C8D", x"32D81", x"32E75",
        x"32F69", x"3305C", x"3314E", x"33240", x"33332", x"33423", x"33513", x"33603",
        x"336F3", x"337E2", x"338D0", x"339BF", x"33AAC", x"33B99", x"33C86", x"33D72",
        x"33E5D", x"33F48", x"34033", x"3411D", x"34207", x"342F0", x"343D8", x"344C0",
        x"345A8", x"3468F", x"34775", x"3485B", x"34941", x"34A26", x"34B0A", x"34BEE",
        x"34CD2", x"34DB5", x"34E97", x"34F79", x"3505B", x"3513C", x"3521C", x"352FC",
        x"353DC", x"354BA", x"35599", x"35677", x"35754", x"35831", x"3590D", x"359E9",
        x"35AC4", x"35B9F", x"35C79", x"35D53", x"35E2C", x"35F05", x"35FDD", x"360B5",
        x"3618C", x"36262", x"36339", x"3640E", x"364E3", x"365B8", x"3668C", x"3675F",
        x"36832", x"36905", x"369D6", x"36AA8", x"36B79", x"36C49", x"36D19", x"36DE8",
        x"36EB7", x"36F85", x"37053", x"37120", x"371EC", x"372B8", x"37384", x"3744F",
        x"3751A", x"375E4", x"376AD", x"37776", x"3783E", x"37906", x"379CD", x"37A94",
        x"37B5A", x"37C20", x"37CE5", x"37DAA", x"37E6E", x"37F31", x"37FF4", x"380B7",
        x"38178", x"3823A", x"382FB", x"383BB", x"3847B", x"3853A", x"385F8", x"386B7",
        x"38774", x"38831", x"388EE", x"389AA", x"38A65", x"38B20", x"38BDA", x"38C94",
        x"38D4D", x"38E06", x"38EBE", x"38F75", x"3902C", x"390E3", x"39199", x"3924E",
        x"39303", x"393B7", x"3946B", x"3951E", x"395D0", x"39683", x"39734", x"397E5",
        x"39895", x"39945", x"399F4", x"39AA3", x"39B51", x"39BFF", x"39CAC", x"39D58",
        x"39E04", x"39EB0", x"39F5B", x"3A005", x"3A0AE", x"3A158", x"3A200", x"3A2A8",
        x"3A350", x"3A3F7", x"3A49D", x"3A543", x"3A5E8", x"3A68C", x"3A731", x"3A7D4",
        x"3A877", x"3A919", x"3A9BB", x"3AA5D", x"3AAFD", x"3AB9D", x"3AC3D", x"3ACDC",
        x"3AD7A", x"3AE18", x"3AEB6", x"3AF52", x"3AFEE", x"3B08A", x"3B125", x"3B1C0",
        x"3B259", x"3B2F3", x"3B38B", x"3B424", x"3B4BB", x"3B552", x"3B5E9", x"3B67F",
        x"3B714", x"3B7A9", x"3B83D", x"3B8D0", x"3B963", x"3B9F6", x"3BA88", x"3BB19",
        x"3BBAA", x"3BC3A", x"3BCCA", x"3BD59", x"3BDE7", x"3BE75", x"3BF02", x"3BF8F",
        x"3C01B", x"3C0A6", x"3C131", x"3C1BC", x"3C245", x"3C2CF", x"3C357", x"3C3DF",
        x"3C467", x"3C4EE", x"3C574", x"3C5FA", x"3C67F", x"3C703", x"3C787", x"3C80B",
        x"3C88E", x"3C910", x"3C992", x"3CA13", x"3CA93", x"3CB13", x"3CB92", x"3CC11",
        x"3CC8F", x"3CD0D", x"3CD8A", x"3CE06", x"3CE82", x"3CEFD", x"3CF78", x"3CFF2",
        x"3D06B", x"3D0E4", x"3D15C", x"3D1D4", x"3D24B", x"3D2C2", x"3D337", x"3D3AD",
        x"3D421", x"3D496", x"3D509", x"3D57C", x"3D5EE", x"3D660", x"3D6D1", x"3D742",
        x"3D7B2", x"3D821", x"3D890", x"3D8FE", x"3D96C", x"3D9D9", x"3DA46", x"3DAB1",
        x"3DB1D", x"3DB87", x"3DBF1", x"3DC5B", x"3DCC4", x"3DD2C", x"3DD94", x"3DDFB",
        x"3DE61", x"3DEC7", x"3DF2C", x"3DF91", x"3DFF5", x"3E059", x"3E0BC", x"3E11E",
        x"3E180", x"3E1E1", x"3E241", x"3E2A1", x"3E301", x"3E35F", x"3E3BD", x"3E41B",
        x"3E478", x"3E4D4", x"3E530", x"3E58B", x"3E5E5", x"3E63F", x"3E699", x"3E6F1",
        x"3E749", x"3E7A1", x"3E7F8", x"3E84E", x"3E8A4", x"3E8F9", x"3E94D", x"3E9A1",
        x"3E9F5", x"3EA47", x"3EA99", x"3EAEB", x"3EB3C", x"3EB8C", x"3EBDC", x"3EC2B",
        x"3EC79", x"3ECC7", x"3ED14", x"3ED61", x"3EDAD", x"3EDF8", x"3EE43", x"3EE8D",
        x"3EED7", x"3EF20", x"3EF68", x"3EFB0", x"3EFF7", x"3F03E", x"3F084", x"3F0C9",
        x"3F10E", x"3F152", x"3F196", x"3F1D9", x"3F21B", x"3F25D", x"3F29E", x"3F2DE",
        x"3F31E", x"3F35D", x"3F39C", x"3F3DA", x"3F417", x"3F454", x"3F491", x"3F4CC",
        x"3F507", x"3F542", x"3F57B", x"3F5B4", x"3F5ED", x"3F625", x"3F65C", x"3F693",
        x"3F6C9", x"3F6FF", x"3F734", x"3F768", x"3F79C", x"3F7CF", x"3F801", x"3F833",
        x"3F864", x"3F895", x"3F8C5", x"3F8F4", x"3F923", x"3F951", x"3F97F", x"3F9AC",
        x"3F9D8", x"3FA04", x"3FA2F", x"3FA59", x"3FA83", x"3FAAC", x"3FAD5", x"3FAFD",
        x"3FB24", x"3FB4B", x"3FB71", x"3FB97", x"3FBBC", x"3FBE0", x"3FC04", x"3FC27",
        x"3FC4A", x"3FC6B", x"3FC8D", x"3FCAD", x"3FCCD", x"3FCED", x"3FD0C", x"3FD2A",
        x"3FD47", x"3FD64", x"3FD81", x"3FD9C", x"3FDB8", x"3FDD2", x"3FDEC", x"3FE05",
        x"3FE1E", x"3FE36", x"3FE4D", x"3FE64", x"3FE7A", x"3FE90", x"3FEA5", x"3FEB9",
        x"3FECD", x"3FEE0", x"3FEF3", x"3FF05", x"3FF16", x"3FF26", x"3FF36", x"3FF46",
        x"3FF55", x"3FF63", x"3FF70", x"3FF7D", x"3FF8A", x"3FF95", x"3FFA1", x"3FFAB",
        x"3FFB5", x"3FFBE", x"3FFC7", x"3FFCF", x"3FFD6", x"3FFDD", x"3FFE3", x"3FFE9",
        x"3FFEE", x"3FFF2", x"3FFF6", x"3FFF9", x"3FFFB", x"3FFFD", x"3FFFE", x"3FFFF"
    );
begin
    sine <= std_logic_vector(sine_sum(sine_sum'high-1 downto sine_sum'high-sine'high-1));
    index_1 <= UNSIGNED(phase(phase'high downto phase'high-11));
    index_2 <= UNSIGNED(phase(phase'high downto phase'high-11))+1;
             
clk_proc: process(clk)
    begin
        if rising_edge(clk) then
            -- Sage 4 - 
            sine_sum  <= sine_mult_1 + sine_mult_2;
            
            -- Pipeline stage 3 - generate the final value
            sine_mult_1 <= sine_1 * frac_1;
            sine_mult_2 <= sine_2 * frac_2;
            
            -- Pipeline state 2 - look up the values in the table
            case quad_1 is
                when "00"   => sine_1 <= midrange+mem(to_integer(entry_1));
                when "01"   => sine_1 <= midrange+mem(to_integer(entry_1));
                when "10"   => sine_1 <= midrange-mem(to_integer(entry_1));
                when others => sine_1 <= midrange-mem(to_integer(entry_1));
            end case;

            case quad_2 is
                when "00"   => sine_2 <= midrange+mem(to_integer(entry_2));
                when "01"   => sine_2 <= midrange+mem(to_integer(entry_2));
                when "10"   => sine_2 <= midrange-mem(to_integer(entry_2));
                when others => sine_2 <= midrange-mem(to_integer(entry_2));
            end case;
            frac_1 <= frac_max - frac;
            frac_2 <= "0" & frac;

            -- Pipeline state 1 - break out the phase components into table indexes
             quad_1  <= index_1(11 downto 10);
             if index_1(10) = '0' then
                entry_1 <= index_1(9 downto 0);
             else 
                entry_1 <= table_max - index_1(9 downto 0);
             end if;

             quad_2  <= index_2(11 downto 10);
             if index_2(10) = '0' then
                entry_2 <= index_2(9 downto 0);
             else 
                entry_2 <= table_max - index_2(9 downto 0);
             end if;

             frac <= unsigned(phase(phase'high-12 downto 0));
        end if;
    end process;
end Behavioral;

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this