Перейти к содержанию
    

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

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

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

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

verilog_cordic_core-master.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все верно, задать константами, например чтобы вращение было от 0 на 45 град (или 0 до pi/2).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы ничего не сказали про нужные Вам точность и разрядность. Если, точность не велика, то можно обойтись и без Кордика, табличным методом. Например, разбить аргумент - 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).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, vladec said:

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Nick_K сказал:

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 hours ago, Nick_K said:

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

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

Как то так ...

Изменено пользователем Strob

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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).

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Скажите, а почему вы не используете готовый ip блок cordic для задания cos и sin?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...