Реализация подписанного сумматора

Предположим, что у меня есть два логических вектора:

logic [4:0] a;
logic [4:0] b;

которые содержат 2 дополнительные значения. Я хочу выполнить вычитание и расширить результат на 1 бит. Например, предположим, что я хочу вычислить -12 - 13 и сохранить результат -25:

logic [5:0] sum;
sum = a - b;

Вышеприведенное имитирует, как я ожидаю, и я получаю ожидаемое значение 6'b100111. Работаем с этим вручную:

  1 0 1 0 0   -12
  1 0 0 1 0   invert bits of +13
          1   carry-in
---------------
1 0 0 1 1 1   = -25

Таким образом, MSB результата — это просто перенос сложения. Однако, если я вычисляю 12 - 13, результат должен быть 6'b111111, но вместо этого я получаю смоделированный результат 6'b011111. Работаем с этим примером вручную:

  0 1 1 0 0   12
  1 0 0 1 0   invert bits of +13
          1   carry-in
---------------
0 1 1 1 1 1   = +31

Таким образом, результат неверный, так как перенос в MSB равен нулю.

Я могу исправить смоделированный результат, изменив RTL следующим образом:

logic [5:0] sum;
sum = $signed(a) - $signed(b);

который возвращает ожидаемый результат 6'b111111. Прочитав SystemVerilog LRM, чтобы понять, что здесь происходит, я обнаружил, что сложения выполняются с битовым размером самого большого операнда, включая LHS операций присваивания. Кроме того, использование ключевого слова $signed приводит к тому, что 5-битные входные операнды расширяются по знаку до 6-битных. Принимая это во внимание и снова выполняя операцию вручную:

[0] 0 1 1 0 0   12
[1] 1 0 0 1 0   invert bits of +13
            1   carry-in
---------------
 1  1 1 1 1 1   = -1

где [0] и [1] — биты расширения знака. Отсюда видно, что MSB фактически вычисляется полным сумматором ([0] + [1] + carry-out from previous column).

Мой вопрос таков:

  1. Правильно ли я считаю, что сумматор со знаком действительно требует полного сумматора в старшем бите для вычисления правильного результата?
  2. Если вышесказанное верно, что сделает из этого инструмент синтеза? Будет ли он также знать, что нужно создать экземпляр полного сумматора на MSB?

Я всегда предполагал, что написание сумматора в SystemVerilog, где входные данные имеют ширину n бит, приведет к тому, что инструмент синтеза создаст экземпляр n-битного сумматора, где (n + 1)-битный вывод будет просто переносом этого сумматор.


person Andrew Lees    schedule 05.06.2021    source источник


Ответы (1)


Вы забыли про расширение знака. -13 (10011) в 6-битном воплощении должно быть 110011. Следовательно, вы неправильно интерпретируете второй результат. Это не +31 (6-бит), его следует интерпретировать как -1 в 5-битной версии. Чтобы получить 6-битный результат, выполните вздох-расширение обоих операндов:

  ext
  0 | 0 1 1 0 0   -- 12
  1 | 1 0 0 1 1   -- -13
  ==|==========
  1 | 1 1 1 1 1   -- -1 (6 bit)

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

person Serge    schedule 05.06.2021
comment
Привет Серж, спасибо за ответ. Я согласен с тем, что для получения правильного результата требуется расширение знака, в конце концов я понял это. Тем не менее, я все еще не уверен, правильно ли это интерпретирует инструмент синтеза? Похоже, что для реализации этой схемы требуется 1 дополнительный полный сумматор на MSB по сравнению с сумматором, который работает с беззнаковыми числами. Является ли это правильным способом кодирования подписанного сумматора (используя $signed) или я должен сам явно закодировать его с помощью дополнительного полного сумматора в MSB? - person Andrew Lees; 05.06.2021
comment
нет, не будут. Вам нужно спроектировать свою модель таким образом, чтобы расширение знака было встроено в нее. Итак, при минимальном значении вам понадобятся 6-битные операнды для 6-битного ответа. - person Serge; 06.06.2021
comment
Итак, каков правильный способ кодирования этого? Из того, что вы говорите, этого достаточно? sum = {a[4], a[4:0} - {b[4], b[4:0]}. Это отличается от sum = $signed(a) - $signed(b) ? - person Andrew Lees; 06.06.2021
comment
что-то вроде этого - person Serge; 06.06.2021
comment
Не используйте sum = {a[4], a[4:0} - {b[4], b[4:0]}. Используйте sum = $signed(a) - $signed(b). - person ToTamire; 06.06.2021
comment
$signed синтезируется DC, но вам нужно проверить другие инструменты синтеза, если они там доступны. - person Serge; 06.06.2021