Найти тему
IT. Как это работает?

Verilog. Прямой и дополнительный код. Сумматор.

Оглавление

Видео в конце...

В вычислительной технике применяется две основные формы представления чисел. Это числа в прямом и дополнительном коде. Другие рассматривать не будем.

Пример чисел в прямом и обратном коде
Пример чисел в прямом и обратном коде

У чисел в прямом коде существует явный признак положительности и отрицательности. Это состояние старшего разряда. Ноль в старшем разряде указывает на положительное число, единица на отрицательное. Остальные биты кодируют абсолютное значение, модуль числа. В связи с этим, появляется такой недостаток, как существование двух нулей. У нормального нуля все разряды нулевые, но если в старшем бите поставить единицу, то получается отрицательный ноль. Такой формат чисел удобен при умножении, о чем мы поговорим в следующих выпусках. Но вот

при сложении чисел прямой код числа абсолютно неудобен.

Целые числа в компьютерах традиционно представлены в виде так называемого дополнительного кода. Положительная часть таких чисел выглядит довольно естественно. У единственного нуля все разряды нулевые. Отрицательного нуля не существует. У числа -1 все разряды единицы. Далее в сторону уменьшения чисел из двоичного кода числа каждый шаг вычитается единица. Это выглядит весьма странно, но зато

сложение и вычитание чисел в дополнительном коде невероятно удобно.

Для этого используется один и тот же сумматор.

Знаковые и беззнаковые числа

Одни и те же целые числа в компьютерах могут быть интерпретированы по разному.

Диапазоны знаковых и беззнаковых чисел
Диапазоны знаковых и беззнаковых чисел

К примеру, восьмибитное число может быть интерпретировано как беззнаковое и как знаковое. Без всяких изменений разрядов числа одну и ту же комбинацию бит можно воспринимать по разному. Да, серьезно, это всего лишь наше воображение и работа стандартных библиотек ввода вывода в языках программирования. Все единицы восьмибитного числа могут быть числом 255 и так же без проблем это может быть -1.

Рассмотрим несколько примеров сложения и вычитания в двоичном коде чтобы стало немного понятнее.

Примеры сложения и вычитания
Примеры сложения и вычитания

Два положительных числа 7 и 3 складываются и результат равен 10. Сумма не превышает диапазон допустимых значений как для знаковых, так и беззнаковых чисел. Никаких проблем нет. Тем кто не знаком со сложением в двоичном виде рекомендуется посмотреть эту статью. Давайте подберем слагаемые так, чтобы результат сложения выходил за рамки допустимых чисел. 129 плюс 128 равно 257, что превышает 255. Если под сумму выделено также 8 бит, то результат можно интерпретировать как ошибочный. Единица это не то, что мы ждали.

В микропроцессорах для помощи в такой ситуации предназначен флаг переноса, это специальный регистр, в котором хранится бит переноса. Если его правильно обработать, то результат операции будет корректным. Бит переноса в девятом разряде интерпретируется как 256 и в совокупностью с единицей в первом разряде получается правильный результат 257.

Для защиты от потенциальных ошибок под результат суммы выделяется на один бит больше, чем разрядность слагаемых.

Если повышение разрядности не уместно, то нужно ограничить величину слагаемых.

Теперь представим, что работаем со знаковыми числами. Из числа 9 вычитаем единицу, а это значит складываем с минус единицей. Сумматор совершает те же самые действия, что и обычно. При сложении в восьми битах результата получаем правильный ответ. При этом неизбежно в бит переноса уходит единица. Если мы никак ее не интерпретируем, то все отлично и поводов для опасений нет.

Беззнаковый сумматор

Разработаем беззнаковый сумматор и за одно разберем одну из важных синтаксических конструкций.

Беззнаковый сумматор на языке Verilog
Беззнаковый сумматор на языке Verilog

На входе сумматора бит переноса от предыдущего сумматора. Если такой вход не нужен, то на него подается ноль. Также на входе два слагаемых a,b разрядностью 8 бит. На выходе модуля восьмибитный результат sum и бит переноса cout.

В фигурных скобках через запятую перечисляется склейка из линий и шин.

В данном случае под результат суммы выделено как раз 9 бит. Это склейка из одного бита линии переноса cout и восьми бит шины результата sum. Старший бит слева, младшие правее. Совершенно ничего сложного и если запомнить это, то все будет очень наглядно.

Синтезированная схема модуля представляется в виде двух сумматоров.

Синтезированная схема сумматора
Синтезированная схема сумматора

Разрядность первого сумматора 9 бит. Слагаемые дополняются незначащими нулями до 9 бит. Следующий сумматор складывает результат с битом переноса. Тут такая же история дополнения однобитного числа до 9-битного незначащими нулями. Результат сложения расщепляется собственно на сам результат и бит переноса. В действительности, конечно же, никаких аппаратных сумматоров в низкобюджетных ПЛИС не используется, все реализуется на логических ячейках.

Протестируем разработанный сумматор целых чисел. Для этого напишем простой модуль тестирования.

Модуль теста сумматора
Модуль теста сумматора

Включаем в состав теста разработанный сумматор, связываем его с проводами теста. Каждый 100 пикосекунд меняем воздействие. Бит переноса на входе один раз сделаем нулевым и больше менять не будем. Сначала сложим единицы, потом 255 и 255 и после 255 и 7. Конечно же, результат сложения превысит максимально допустимое значение, но именно это стоит посмотреть.

-8

Сложение двух единиц прошло без проблем, а вот дальше есть нюансы. Строго говоря, 8 бит суммы показывают неверный результат, но если принимать во внимание единицу бита переноса, то все в порядке. Такая же история дальше. Результат операции нужно интерпретировать как 9-битное число совместно со старшим битом переноса.

Знаковый сумматор

Для указания компилятору о том, что числа знаковые, служит ключевое слово signed.

Знаковый сумматор на языке Verilog
Знаковый сумматор на языке Verilog

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

Моделирование сложения знаковых чисел
Моделирование сложения знаковых чисел

1 и 1 дают 2, тут все верно. -1 и -1 дают -2. И тут тоже все правильно. 7 - 1 дает 6. Все верно.

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

Сумматор чисел разной разрядности
Сумматор чисел разной разрядности

На входе будет 8-битное и 6-битное слагаемое. На всякий случай, под результат предусмотрим 8 бит. При моделировании укажем, что на один из входов подается 6-битное число. В дополнительном коде 6-битная минус единица будет выглядеть так 111111.

Тест сложения чисел разной разрядности
Тест сложения чисел разной разрядности

И теперь очень интересно как компилятор выберется из такой ситуации.

Сложение и вычитание чисел разной разрядности
Сложение и вычитание чисел разной разрядности

По нашим представлениям, в этом случае сработает дополнение 6-битного числа незначащими нулями. Но в случае с отрицательным слагаемым дополнение нулями даст неверный результат -128 не равно 192.

Дополнение единицами вполне решит проблему. Усаживаемся удобнее и посмотрим что произойдет. Второе слагаемое 6-битное. 1 + 1 = 2. -1 + -1 = -2. 7-1=6.

Моделирование сложения чисел разной разрядности
Моделирование сложения чисел разной разрядности

Разная разрядность шин и при этом компилятор легко переварил положительные и отрицательные числа. Уважение таким компиляторам.

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