Jump to content

    

Математика в VHDL

Как мне такие вычисления перенести в VHDL?

Spoiler

volt_on_a2d_j1 = (double)(fastBuff_posJ1[29] / 4096.0) * 4.99;
volt_3ms_j1 = volt_on_a2d_j1 * 3.74;

volt_on_a2d_j1 = (double)(fastBuff_posJ1[59] / 4096.0) * 4.99;
volt_6ms_j1 = volt_on_a2d_j1 * 3.74;

volt_delta_j1 = volt_6ms_j1 - volt_3ms_j1;
volt_ct_j1 = volt_6ms_j1 + 0.560;

qc_j1 = Ict_439_j1 * 0.003;
ct_j1 = qc_j1 / volt_delta_j1;

//average to reduce the error
for (ii = 0; ii < 10; ii++)
{
	volt_on_a2d_j1 = (double)(fastBuff_negJ1[20+ii] / 4096.0) * 4.99;
	volt_3ms_j1 = volt_on_a2d_j1 * 3.74;

	volt_on_a2d_j2 = (double)(fastBuff_negJ2[20+ii] / 4096.0) * 4.99;
	volt_3ms_j2 = volt_on_a2d_j2 * 3.74;

	volt_on_a2d_j1 = (double)(fastBuff_negJ1[50+ii] / 4096.0) * 4.99;
	volt_6ms_j1 = volt_on_a2d_j1 * 3.74;

	volt_on_a2d_j2 = (double)(fastBuff_negJ2[50+ii] / 4096.0) * 4.99;
	volt_6ms_j2 = volt_on_a2d_j2 * 3.74;

	volt_delta_cf_j1 = volt_6ms_j1 - volt_3ms_j1;
	volt_delta_cf_j2 = volt_6ms_j2 - volt_3ms_j2;

	volt_delta_avg_j1 += volt_delta_cf_j1;
	volt_delta_avg_j2 += volt_delta_cf_j2;
}

volt_delta_avg_j1 /= 10.0;
volt_delta_avg_j2 /= 10.0;

//calculate capacitor charge I * dT
qc_j1 = If_j1 * 0.003;
qc_j2 = If_j2 * 0.003;

//calculate capacitor
cf_j1 = fabs(qc_j1 / volt_delta_avg_j1);  //volt_delta;
cf_j2 = fabs(qc_j2 / volt_delta_avg_j2);

volt_cf_j1 = (volt_delta_avg_j1 * 2) + DIODE_DROP;
volt_cf_j2 = (volt_delta_avg_j2 * 2) + DIODE_DROP;

cs_j1 = (ct_j1*cf_j1) / (ct_j1+cf_j1);
cs_j2 = (ct_j2*cf_j2) / (ct_j2+cf_j2);

double expon_j1 = exp( (-1) * ( fuzeTime1553_j1/(R_TOTAL*cs_j1) ) ); 
double expon_j2 = exp( (-1) * ( fuzeTime1553_j2/(R_TOTAL*cs_j2) ) );

volt_cf_fixed_j1 = ( volt_ct_j1 * ( ct_j1+(cf_j1*expon_j1) ) ) / ( cf_j1 * (1-expon_j1) );
volt_cf_fixed_j2 = ( volt_ct_j2 * ( ct_j2+(cf_j2*expon_j2) ) ) / ( cf_j2 * (1-expon_j2) );


i_fixed_j1 = ( (cf_j1 * (volt_cf_fixed_j1 - volt_cf_j1) ) / 0.034) * (-1.0);  
i_fixed_j2 = ( (cf_j2 * (volt_cf_fixed_j2 - volt_cf_j2) ) / 0.034) * (-1.0);

double temp_j1 = 2E+06*i_fixed_j1*i_fixed_j1 - 722096*i_fixed_j1 + 33179 ;
double temp_j2 = 2E+06*i_fixed_j2*i_fixed_j2 - 722096*i_fixed_j2 + 33179 ;

 

VHDL работает с double?

Share this post


Link to post
Share on other sites

Конечно. Тип real. Так и пишите

signal volt_on_a2d_j1 : real;

volt_on_a2d_j1 <= ...

Правда дальше у вас возникнет вопрос, как ти вычисления разместить в FPGA и это уже совсем другой вопрос.

Share this post


Link to post
Share on other sites
1 minute ago, alexadmin said:

Конечно. Тип real. Так и пишите

signal volt_on_a2d_j1 : real;

volt_on_a2d_j1 <= ...

Правда дальше у вас возникнет вопрос, как ти вычисления разместить в FPGA и это уже совсем другой вопрос.

это сожрет много LE?

Share this post


Link to post
Share on other sites
1 минуту назад, alexadmin сказал:

Конечно. Тип real. Так и пишите 

signal volt_on_a2d_j1 : real;

volt_on_a2d_j1 <= ...

:biggrin::biggrin::biggrin::rofl:

Share this post


Link to post
Share on other sites
5 minutes ago, jenya7 said:

это сожрет много LE?

Нисколько. В логику вещественная арифметика не синтезируется. Но про синтез ведь вопроса не было.

Share this post


Link to post
Share on other sites
6 minutes ago, jenya7 said:

это сожрет много LE?

Скорее всего нет :wink:

Но Вам придётся придумать как числа с плавающей точкой уместить в фиксированной логике и выполнить вычисления на DSP блоках. По-другому оно даже не засинтезирует

Share this post


Link to post
Share on other sites
17 minutes ago, Nick_K said:

Скорее всего нет :wink:

Но Вам придётся придумать как числа с плавающей точкой уместить в фиксированной логике и выполнить вычисления на DSP блоках. По-другому оно даже не засинтезирует

не понял. после Pace&Route что мы увидим в RTL? математика требует сумматоры, дивайдеры, что он там еще вставляет. это же должно быть реализовано в железе.

сделал для примера

signal volt_on_a2d_j1 : real; 

volt_on_a2d_j1 <= (0.003 * 120) / 0.5;

получаю

Error (10414):  cannot synthesize non-constant real objects or values

 

Share this post


Link to post
Share on other sites
2 minutes ago, jenya7 said:

не понял. после Pace&Route что мы увидим в RTL? математика требует сумматоры, дивайдеры, что он там еще вставляет. это же должно быть реализовано в железе.

Всё верно... Если мы говорим про целочисленные или с фиксированной точкой. Для вычислений с плавающей запятой этот номер не проканает. Можно, наверное, использовать какие-то либы, чтобы оно попробовало синтезировать, но я таких фокусов не знаю (разве только через Матлаб).

UPD Однако оказывается, что VHDL-2008 поддерживает синтез чисел с плавающей запятой. Стало и самому интересно как оно это всё разведёт. По прикидкам подозреваю, что одна операция умножения real'а займёт раза в 3 больше логики, чем аналогичная с фиксированной точкой. Ну и сумма/разница раза в 1.5-2 раза больше. Короче очень много.

Share this post


Link to post
Share on other sites
15 minutes ago, Nick_K said:

Всё верно... Если мы говорим про целочисленные или с фиксированной точкой. Для вычислений с плавающей запятой этот номер не проканает. Можно, наверное, использовать какие-то либы, чтобы оно попробовало синтезировать, но я таких фокусов не знаю (разве только через Матлаб).

UPD Однако оказывается, что VHDL-2008 поддерживает синтез чисел с плавающей запятой. Стало и самому интересно как оно это всё разведёт. По прикидкам подозреваю, что одна операция умножения real'а займёт раза в 3 больше логики, чем аналогичная с фиксированной точкой. Ну и сумма/разница раза в 1.5-2 раза больше. Короче очень много.

а если умножить все  на 1000 и работать с integer? если все так грустно... скорее всего я потеряю точность и выйду за рамки допустимой ошибки :(

Edited by jenya7

Share this post


Link to post
Share on other sites
6 минут назад, jenya7 сказал:

а если умножить все  на 1000 и работать с integer? если все так грустно.

Именно так и делают: превращают плавующую точку в фиксированную. Но обычно умножают на степень двойки.

Это всё делается до того, как написать VHDL-код и превратить его в железо.

 

Share this post


Link to post
Share on other sites
4 minutes ago, jenya7 said:

а если умножить все  на 1000 и работать с integer? если все так грустно.

В десятки раз проще будет. Или использовать хотя бы single-precision значения.

Просмотрел IP ядра, которые используются для генерации одной операции для работы с числами с плавающей точкой:

1. Float single-precision multiply: 2-3 DSP

2. Float double-precision multiply: 10-11DSP

3. Float single-precision add/substrate : 1-2 DSP

4. Float double-precision add/substrate: 3 DSP

Хочу подчеркнуть - это только на одну операцию. Впринципе если у вас виртекс лежит в тумбочке, то может и влезет.

Share this post


Link to post
Share on other sites
7 minutes ago, andrew_b said:

Именно так и делают: превращают плавующую точку в фиксированную. Но обычно умножают на степень двойки.

Это всё делается до того, как написать VHDL-код и превратить его в железо.

 

я потеряю точность. на что мне умножить 0.0000001234.

Share this post


Link to post
Share on other sites

Задайтесь сперва вопросом - с какой скоростью вам надо проводить эти вычисления? Возможно, что поставить процессор будет наилучшим решением. Еще один вариант - задествовать High Level Synthesis и из Си получить готовый HDL-код.

Share this post


Link to post
Share on other sites
1 minute ago, alexadmin said:

Задайтесь сперва вопросом - с какой скоростью вам надо проводить эти вычисления? Возможно, что поставить процессор будет наилучшим решением. Еще один вариант - задествовать High Level Synthesis и из Си получить готовый HDL-код.

нужно очень высокое быстродействие. поэтому решено всю математику перенести в FPGA.

Share this post


Link to post
Share on other sites
9 минут назад, jenya7 сказал:

я потеряю точность.

А вы думаете, вам IEEE 754 гарантирует точное представлние чисел? Я вас разочарую. Из-за ограничения разрядной сетки точность теряется в любом случае.

36 минут назад, Nick_K сказал:

Однако оказывается, что VHDL-2008 поддерживает синтез чисел с плавающей запятой.

Там есть специальные типы для этого. Вектор (N downto -M) содержит целую (N downto 0) и дробную части (-1 downto -M). Помнится, Xilinx, что-ли, не поддерживал векторы с отрицательными границами. Учитывая, в каком состоянии у них в целом поддержка VHDL'2008, не удивлюсь, если всё так и осталось.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now