jenya7 0 30 марта, 2020 Опубликовано 30 марта, 2020 (изменено) · Жалоба Вычисляю так constant ADC_SAMPLES : std_logic_vector(7 downto 0) := X"03"; when ST_ADC_AVG => if (adc_idx < (ADC_SAMPLES+1)) then if (ADC_READY = '0') then ADC_TRIG <= '1'; ChargeState <= ST_ADC_WAIT; end if; else conv_ready <= '1'; adc_average_res <= std_logic_vector( unsigned(adc_average) / unsigned(ADC_SAMPLES) ); ChargeState <= ST_ADC_RES; end if; when ST_ADC_WAIT => if (ADC_READY = '1') then ADC_TRIG <= '0'; adc_average <= adc_average + ADC_VAL_IN; adc_idx := adc_idx + 1; ChargeState <= ST_ADC_AVG; end if; when ST_ADC_RES => case ms_counter is when X"03" => ADC_VAL_3MS <= adc_average_res(17 downto 0); ADC_SAMP_ST <= X"03"; when others => end case; ChargeState <= ST_SAMPLE; Проверяю adc_average = 0xD80 + 0xD5D + 0xD43 = 0x2820 – все верно но конечный результат ADC_VAL_3MS = 0x11EB – это значит adc_average деленное на 2 а не на 3. Это как так выходит? Изменено 30 марта, 2020 пользователем jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 30 марта, 2020 Опубликовано 30 марта, 2020 · Жалоба Приветствую! 6 minutes ago, jenya7 said: Это как так выходит? Вы это синтезируете? С операцией деления на произвольную величину? А вы уверенны что при синтезе у вас деление на переменную не заменяется на деление на ближайшую степень 2ки? Меня в школе учили что деление на x можно заменить умножением на 1/x. Но это давно было - сейчас такому может уже и не учат. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 30 марта, 2020 Опубликовано 30 марта, 2020 (изменено) · Жалоба 1 hour ago, RobFPGA said: Приветствую! Вы это синтезируете? С операцией деления на произвольную величину? А вы уверенны что при синтезе у вас деление на переменную не заменяется на деление на ближайшую степень 2ки? Меня в школе учили что деление на x можно заменить умножением на 1/x. Но это давно было - сейчас такому может уже и не учат. Удачи! Rob. умножением на 1/x? в VHDL? мне только флоут не хватало для полного счастья :)) adc_average_res <= std_logic_vector( unsigned(adc_average) / 3) ); тот же результат. делиться на два. Изменено 30 марта, 2020 пользователем jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 30 марта, 2020 Опубликовано 30 марта, 2020 · Жалоба Приветствую. 9 minutes ago, jenya7 said: умножением на 1/x? в VHDL? мне только флоут не хватало для полного счастья :)) Увы - не будет у вас "полного счастья" - а будет fixed point. Ведь умножение на 1/x можно преобразовать как (value * round(2^N/x)) / 2^N. Выбирая величину числа N будете регулировать точность приближения к "полному счастью" Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 30 марта, 2020 Опубликовано 30 марта, 2020 · Жалоба 1 hour ago, RobFPGA said: Приветствую. Увы - не будет у вас "полного счастья" - а будет fixed point. Ведь умножение на 1/x можно преобразовать как (value * round(2^N/x)) / 2^N. Выбирая величину числа N будете регулировать точность приближения к "полному счастью" Удачи! Rob. я поставил constant ADC_SAMPLES : std_logic_vector(7 downto 0) := X"04"; получил ADC_VAL_3MS = adc_average деленное на 3. оно делиться на ADC_SAMPLES - 1. тут скорее логическая проблема а не арифметическая. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 30 марта, 2020 Опубликовано 30 марта, 2020 · Жалоба 58 minutes ago, jenya7 said: Вычисляю так Проверяю adc_average = 0xD80 + 0xD5D + 0xD43 = 0x2820 – все верно но конечный результат ADC_VAL_3MS = 0x11EB – это значит adc_average деленное на 2 а не на 3. Это как так выходит? 0x11EB*2=0x23D6, у вас вообще не так выходит) ЗЫ. возьмите нормальный симулятор, перед тем как выполнять отладку на плис ЗЗЫ. 99.9% ошибка со времянкой в делителе 32-х битных чисел Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 30 марта, 2020 Опубликовано 30 марта, 2020 (изменено) · Жалоба 0x2820 / 0x11EB = 2 не знаю почему но так работает adc_average_res <= std_logic_vector( unsigned(adc_average) / unsigned(ADC_SAMPLES+1) ); Изменено 30 марта, 2020 пользователем jenya7 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 30 марта, 2020 Опубликовано 30 марта, 2020 · Жалоба On 3/30/2020 at 8:17 PM, jenya7 said: 0x2820 / 0x11EB = 2 а ничего что в режиме "программист" калькулятор виндовз целочисленный? На остальное я уже ответил. ЗЫ. Просидите в состоянии деления тактов 5-6, должно помочь. На будущее, не используйте вот такую реализацию вычисления среднего. Это не МК Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 30 марта, 2020 Опубликовано 30 марта, 2020 · Жалоба Приветствую! 1 hour ago, jenya7 said: оно делиться на ADC_SAMPLES - 1. тут скорее логическая проблема а не арифметическая. Логические проблемы решаются на нормальном симуляторе, а не по неполному куску кода. В купе с предварительным анализом что как можно сделать для оптимальной реализации заданного функционала. Операция деления очень затратная при реализации в FPGA. Фактически это будет комбинаторный делитель! Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrGalaxy 9 30 марта, 2020 Опубликовано 30 марта, 2020 (изменено) · Жалоба 2 часа назад, jenya7 сказал: тут скорее логическая проблема а не арифметическая. Скорее всего. Возможно, что-то связано с переводом из одного типа в другой. Нормально целочисленное деление работает. Спойлер LIBRARY ieee; USE ieee.std_logic_1164.all; -- Entity Declaration ENTITY Divider IS -- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE! PORT ( Clk : IN STD_LOGIC; IN_Data1 : IN Integer range 0 to 255; IN_Data2 : IN Integer range 0 to 255; IN_Data3 : IN Integer range 0 to 255; OUT_Data : OUT Integer range 0 to 255 ); -- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE! END Divider; -- Architecture Body ARCHITECTURE Divider_architecture OF Divider IS BEGIN Process(Clk, IN_Data1, IN_Data2, IN_Data3) begin if rising_edge(Clk) then OUT_Data <= (IN_Data1 + IN_Data2 + IN_Data3) / 3; end if; end process; END Divider_architecture; Спойлер Спойлер Изменено 30 марта, 2020 пользователем MrGalaxy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flip-fl0p 4 30 марта, 2020 Опубликовано 30 марта, 2020 · Жалоба Работаете со массивами, кратными степени двойки. Тогда операцию деления можно будет заменить сдвигом. Вернее даже не сдвигом, а отбрасыванием нулей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Skryppy 0 30 марта, 2020 Опубликовано 30 марта, 2020 · Жалоба Для деления можете использовать ip ядро cordic , в нем есть функция деления, которая нормально в железе работает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jenya7 0 31 марта, 2020 Опубликовано 31 марта, 2020 · Жалоба 14 hours ago, MrGalaxy said: Скорее всего. Возможно, что-то связано с переводом из одного типа в другой. Нормально целочисленное деление работает. может потому что integer. у меня std_logic_vector. 14 hours ago, Flip-fl0p said: Работаете со массивами, кратными степени двойки. Тогда операцию деления можно будет заменить сдвигом. Вернее даже не сдвигом, а отбрасыванием нулей. с шифтом надо попробовать 13 hours ago, Skryppy said: Для деления можете использовать ip ядро cordic , в нем есть функция деления, которая нормально в железе работает. там нет деления. по крайней мере для MAX 10 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 31 марта, 2020 Опубликовано 31 марта, 2020 · Жалоба 14 hours ago, MrGalaxy said: Скорее всего. Возможно, что-то связано с переводом из одного типа в другой. Отнюдь, при всем уважении, но у ТС проблемы с математикой 5 го класса, а не все что описали выше коллеги) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrGalaxy 9 31 марта, 2020 Опубликовано 31 марта, 2020 (изменено) · Жалоба 6 часов назад, des00 сказал: у ТС проблемы с математикой 5 го класса, а не все что описали выше коллеги) Я с кодом до конца не разобрался, мозг закипел от бесконечных STD_LOGIC_VECTOR, и ни одного комментария. 6 часов назад, jenya7 сказал: может потому что integer. у меня std_logic_vector. Кто Вам запрещает? Если в итоге непременно нужен std_logic_vector, делаете арифметику в отдельном блоке и передаёте в другой блок. Шина одна и та же. Повысится наглядность кода, а это много стоит. 6 часов назад, jenya7 сказал: с шифтом надо попробовать Деление на 2 синтезируется как сдвиг. То, что Вы явно в коде укажете сдвиг, ничего в плане быстродействия или экономии ресурсов не даст. (Про Xilinx не скажу, а Квартус синтезирует именно так). Изменено 31 марта, 2020 пользователем MrGalaxy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться