Maverick_ 15 17 мая, 2009 Опубликовано 17 мая, 2009 · Жалоба Доброго всем времени суток! Вопрос который прозвучит возможно покажется глупым (новичковым), но что-то я зашел в тупик. :cranky: Вот собственно сам вопрос: ПЛИС с АЦП получает 12 битные данные (только положительные числа от 0 до 4095) над которыми потом производится двоичная арифметика(сложение, вычитание и умножение). До некоторого момента арифметика производилась только над положительными числами все было прекрасно, а сейчас встал вопрос, что числа после вычитания могут быть как отрицательными так положительными и здесь проблема. Нужно реализовать следующее выражение S = S + b - c где b и с - данные с АЦП. Приведите плиз пример коректного описания. PS что-то мне подсказывает что нужно задавать тип SIGNED и UNSIGNED (сейчас я для входных и выходных данных использую тип std_logic_vector(11 downto 0)), или как-то контролировать старший разряд, т.е. знак числа (тогда наверное вначале каким-то образом нужно преобразовывать входные данные). :help: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexadmin 0 17 мая, 2009 Опубликовано 17 мая, 2009 (изменено) · Жалоба Если не хочется постигать signed/unsigned, то: продолжайте использовать std_logic_vector. используйте знаковый пакет USE IEEE.std_logic_unsigned.all; к вашим входным данным добавьте (конкатенацией) слева нулевой битик (т.к. число всегда положительное). типа signal b_signed, c_signed, dif : std_logic_vector(12 downto 0); ... b_signed <= '0' & b; c_signed <= '0' & c; dif <= b-c; Вуаля. dif - значение разности ваших входов в знаковом виде. Ну а дальше с ним что хотите делайте, помня про расширение разрядности по необходимости. Изменено 17 мая, 2009 пользователем alexadmin Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dimidrol 0 17 мая, 2009 Опубликовано 17 мая, 2009 · Жалоба Если не хочется постигать signed/unsigned, то: продолжайте использовать std_logic_vector. используйте знаковый пакет USE IEEE.std_logic_unsigned.all; к вашим входным данным добавьте (конкатенацией) слева нулевой битик (т.к. число всегда положительное). типа signal b_signed, c_signed, dif : std_logic_vector(12 downto 0); ... b_signed <= '0' & b; c_signed <= '0' & c; dif <= b-c; Вуаля. dif - значение разности ваших входов в знаковом виде. Ну а дальше с ним что хотите делайте, помня про расширение разрядности по необходимости. Как-то сложно все. Если данные с АЦП приходят в дополнительном коде, то мудрить при сложениях/вычитаниях и умножениях вообще не надо. Если данные с АЦП в прямом коде, то я бы перевел их в дополнительный и не парился. т.е. в случае дополнительного кода вот так можно: library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; entity qwerty is port ( a,b,c: in std_logic_vector(11 downto 0); Xout: out std_logic_vector(11 downto 0) ); end entity; architecture qwerty of qwerty is begin Xout <= a + b - c; end architecture; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sefo 0 18 мая, 2009 Опубликовано 18 мая, 2009 · Жалоба Как-то сложно все. Если данные с АЦП приходят в дополнительном коде, то мудрить при сложениях/вычитаниях и умножениях вообще не надо. Если данные с АЦП в прямом коде, то я бы перевел их в дополнительный и не парился. т.е. в случае дополнительного кода вот так можно: Положительные числа что в прямом, что в дополнительном коде выглядят абсолютно одинаково, так что никуда их переводить не нужно. Ваш код не будет корректно работать потому что результат a + b - c может занимать на 2 разряда больше, чем операнды. Поэтому правильный код привел alexadmin, правда он описал только половину того, что нужно сделать. :help: Т.к. результат вычитания в общем случае может иметь диапазон от -4095 до +4095, то разрядность S, как минимум должна быть на 1 бит больше, чем разрядность a и b. Т.к., судя по выражению, вы собираетесь эту разницу накапливать, то разрядность S нужно еще увеличить. На сколько именно зависит от количества накоплений. Если брать общий случай, то если количество накоплений = 2^N, то разрядность S должна вырасти на N бит (если 2^(N-1) < разрядность S < 2^(N), то берем наибольшее т.е. N). Что касается использования std_logic_vector, unsigned или signed, то для сложения/вычитания это безразлично - тем и хорош дополнительный код. Сумматор для любых чисел в дополнительном коде одинаковый (все синтезаторы генерят логику для дополнительного кода) Главное это разрядности правильно рассчитать. Вот код library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity Accumulator is generic ( N : natural := 4 --по умолчанию 16 накоплений ); port ( CLK : in std_logic; RESET : in std_logic; A_i : in std_logic_vector(11 downto 0); -- i просто суффикс обозначающий направлений сигнла B_i : in std_logic_vector(11 downto 0); -- i просто суффикс обозначающий направлений сигнла ACCUM_ro : out std_logic_vector (12+N downto 0) -- ro просто суффикс обозначающий направлений сигнла ); end Accumulator; architecture RTL of Accumulator is signal A : std_logic_vector(ACCUM_ro'high downto 0); signal B : std_logic_vector(ACCUM_ro'high downto 0); signal ACCUM : std_logic_vector(ACCUM_ro'high downto 0); begin A <= (A'high downto 12 => '0') & A_i; B <= (B'high downto 12 => '0') & B_i; process(CLK) begin if(CLK'event and CLK = '1') then -- { if RESET = '1' then -- { ACCUM <= (others => '0'); -- } else -- { ACCUM <= ACCUM + A - B; -- } end if; -- } end if; end process; ACCUM_ro <= ACCUM; end RTL; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dimidrol 0 18 мая, 2009 Опубликовано 18 мая, 2009 · Жалоба Беру свои обратно. Плохо вник в проблему. Полностью согласен с Sefo. Я бы еще вот эту строчку: signal ACCUM : std_logic_vector(ACCUM_ro'high downto 0); переписал бы вот так, чтобы симулировать было удобно: signal ACCUM : std_logic_vector(ACCUM_ro'high downto 0):=(others=>'0'); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 18 мая, 2009 Опубликовано 18 мая, 2009 · Жалоба Спасибо за подсказу и описание! Только я реализовал это ввиде FSM на 3 состояния (в псевдо коде ниже): SIGNAL summ, subb : SIGNED (12 downto 0) := (others=>'0'); SIGNAL а, b : SIGNED (12 downto 0) := (others=>'0'); when s0 => reg_strob <=0; subb <= summ + a; s_next <= s1; when s1 => reg_strob <=0; summ <= subb - b; s_next <= s2; when s2 => reg_strob <=1; s_next <= s0; Сигнал strob дает мне готовность данных ЗЫ мне кажется если сразу написать summ = summ + a - b то выйдет более большая задержка и соответственно скоростные характеристики схемы будут более низкими Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Sefo 0 18 мая, 2009 Опубликовано 18 мая, 2009 · Жалоба ЗЫ мне кажется если сразу написать summ = summ + a - b то выйдет более большая задержка и соответственно скоростные характеристики схемы будут более низкими Любопытно, о каких скоростных характеристиках идет речь? Если частота выборки данных у АЦП является предельной для ПЛИС, то, разумеется, нужно конвееризировать вычисления, но ваш конвеер приведет к тому, что: 1)Если у Вас 2 АЦП то, вы будете обрабатывать только каждый третий отсчет, а если еще и не задержите b на такт, то будете копить разность отсчетов взятых в разные моменты времени. 2)Если АЦП один и a = x(t), а b = x(t+1) то, ваш конвеер будет пропускать каждый третий отсчет АЦП. По-моему FSM для такой простой задачи слишком жирно :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Maverick_ 15 19 мая, 2009 Опубликовано 19 мая, 2009 · Жалоба Любопытно, о каких скоростных характеристиках идет речь? Если частота выборки данных у АЦП является предельной для ПЛИС, то, разумеется, нужно конвееризировать вычисления, но ваш конвеер приведет к тому, что: 1)Если у Вас 2 АЦП то, вы будете обрабатывать только каждый третий отсчет, а если еще и не задержите b на такт, то будете копить разность отсчетов взятых в разные моменты времени. 2)Если АЦП один и a = x(t), а b = x(t+1) то, ваш конвеер будет пропускать каждый третий отсчет АЦП. По-моему FSM для такой простой задачи слишком жирно :) Извините, просто я не захотел описывать полностью задачу, чтобы не засорять форум. Полная математика во вложении. АЦП работает на частоте 6 МГц. Частота работы ПЛИС 96 МГц. 96/6=16 тактов. И в эти 16 тактов нужно положить эту математику, чтобы к следующему приходу данных с АЦП был готов результат. ЗЫ FSM пользуюсь, так как мне легче с помощью него распределить что и когда считается. ЗЫ ЗЫ Вроде вчера задачу реализовал (во всяком случае в симуляторе она отрабатывается). Вроде - потому что еще не было проверки в "железе". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться