Среднее арифметическое регистра в vhdl

Для проекта, над которым я сейчас работаю, я пытаюсь взять некоторые входные данные, сохранить их в регистре, а затем найти среднее арифметическое регистра. Все мои входы имеют длину 24 бита. Мои регистры имеют длину 4 входа, поэтому я просто удаляю последние 3 цифры наименее значащих бит при делении их на 4, чтобы вычислить среднее арифметическое, а затем просто добавляю их.

среднее — это мой register(95 downto 0) (4 x 24 = 96), а mean_medium — это тип unsigned.

Когда я кодирую следующую строку

signal mean_medium : unsigned (23 downto 0) := (others => '0');
mean_medium <= unsigned(medium (95 downto 75)) +
               unsigned(medium (71 downto 51)) +
               unsigned(medium (47 downto 27)) +
               unsigned(medium (23 downto 3)) ;

Я принял следующее предупреждение:

Несоответствие ширины. mean_medium имеет ширину 24 бита, но присваиваемое выражение имеет ширину 21 бит.

Есть ли у вас какие-либо предложения, чтобы исправить это?


person mqwert97    schedule 17.05.2017    source источник


Ответы (3)


Ошибка уже в том, что вы делите на четыре, сдвигая 3 бита. Вам нужно всего лишь сдвинуть 2 бита.

Но для правильной/точной арифметики вы не должны не предварительно сдвигать операнты этого выражения, так как вы теряете точность из-за усечения. Сначала добавьте все 4 полных 24-битных значения к одному 26-битному выводу. Затем сдвиньте и округлите вывод. Пример

signal mean_medium : unsigned (23 downto 0); -- redundant := (others => '0');
signal mean_temp : unsigned(25 downto 0);

mean_temp <=
    resize(unsigned(medium (95 downto 72)), mean_Temp'length) +
    resize(unsigned(medium (71 downto 48)), mean_Temp'length) +
    resize(unsigned(medium (47 downto 24)), mean_Temp'length) +
    resize(unsigned(medium (23 downto 0)), mean_Temp'length) +
    2; -- round factor

mean_medium <= shift_right(mean_temp, 2); --divide by 4

p.s. вы также можете объединить это в одну строку, устраняя необходимость mean_temp.

person JHBonarius    schedule 18.05.2017

Я делаю предположение, что вы используете пакет numeric_std.

В пакете numeric_std оператор + требует, чтобы ширина суммы равнялась ширине самого широкого из операндов. Ваши операнды имеют ширину 21 бит, ваша сумма имеет ширину 24 бита. Итак, вам также нужно сделать ваши операнды шириной 24 бита. Вы можете сделать это, используя функцию resize в numeric_std. На самом деле этого должно быть достаточно:

mean_medium <= resize(unsigned(medium (95 downto 75)),24) +
               unsigned(medium (71 downto 51)) +
               unsigned(medium (47 downto 27)) +
               unsigned(medium (23 downto 3)) ;

но вы также можете сделать это, если считаете это более аккуратным:

mean_medium <= resize(unsigned(medium (95 downto 75)),24) +
               resize(unsigned(medium (71 downto 51)),24) +
               resize(unsigned(medium (47 downto 27)),24) +
               resize(unsigned(medium (23 downto 3)) ,24) ;

Или некоторые варианты этого еще лучше:

mean_medium <= resize(unsigned(medium (95 downto 75)),mean_medium'length) +
               unsigned(medium (71 downto 51)) +
               unsigned(medium (47 downto 27)) +
               unsigned(medium (23 downto 3)) ;
person Matthew Taylor    schedule 17.05.2017

две части уравнения должны иметь одинаковый размер, вы можете использовать функцию изменения размера или вы можете использовать 24-битный временный сигнал и сделать так:

signal temp : std_logic_vector(23 downto 0); temp(23 downto 21) <= "000"; temp(20 downto 0) <= medium (95 downto 75); mean_medium <= temp + ....

person Sajad Sani    schedule 17.05.2017