Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Problem 01: Sign extension block

Viktor Prutyanov edited this page Feb 12, 2019 · 6 revisions

Блок расширения знака

В этом задании мы научимся работать с шинами wire, некоторыми новыми логическими операциями, вспомним как устроены отрицательные числа в машинной арифметике и сделаем блок расширения знака (в двух вариантах).

В этом руководстве и далее в курсе, а также вообще в языке Verilog принята следующая нотация: самый левый бит в записи N-разрядного двоичного числа — под номером N-1 — наиболее значащий (MSB — most significant bit), самый правый бит — под номером 0 — наименее значащий (LSB — least significant bit).

Число \ номер бита 76543210
5 00000101
11 00001011
43 00101011

В машинной арифметике отрицательные числа представляются дополнительным кодом (для примера взяты 12-битные числа):

Десятичное представление Двоичное представление
в дополнительном коде (12 бит)
Двоичное представление
противоположного числа
в дополнительном коде (12 бит)
7 00000000111 11111111001
1 00000000001 11111111111
0 00000000000 00000000000
-1 11111111111 00000000001
-2 11111111110 00000000010

Можно заметить, что:

  • Старший бит обозначает знак числа. Единица показывает, что число отрицательное.
  • Число и противоположное ему связаны такой формулой: -x = ~x + 1 (~ означает побитовую инверсию, как в языке C)

Теперь возьмем числа 7 и -7 и посмотрим на их представления как 16-битных чисел:

Десятичное представление Двоичное представление
в дополнительном коде
Двоичное представление
противоположного числа
в дополнительном коде
7 000000000000111 111111111111001

Можно заметить, что:

  • Для превращения положительного числа 12-битного числа в 16-битное нужно добавить 4 нуля.
  • Для превращения отрицательного числа 12-битного числа в 16-битное нужно добавить 4 единицы.

Значит, расширять число нужно по-разному в зависимости от старшего бита. В нашем процессоре понадобится расширять 12-битные целые числа до 32-битных. В этом задании мы напишем соответствующий модуль.

Подготовка

Перейдите в каталог problems/01_sign_ext в вашей локальной копии репозитория.

Откройте файл testbench.v. Здесь созданы экземпляры 3 модулей:

  1. Экземпляр модуля расширения знака (первый вариант):
sign_ext se(.imm(imm), .ext_imm(ext_imm));
  1. Экземпляр модуля расширения знака (второй вариант):
sign_ext2 se2(.imm(imm), .ext_imm(ext_imm2));
  1. Экземпляр модуля смены знака целого 32-битного числа:
neg neg(.x(ext_imm), .minus_x(minus_ext_imm));

Задача No1

По заголовку модуля выясните, какая разрядность должна быть у выхода модуля расширения знака. Объявите соответствующую шину в модуле testbench.

Подсказка: Раньше мы пользовались только 1-разрядными шинами, и объявляли их вот так:

wire my_1bit_signal;

N-разрядная шина объявляется таким образом:

wire [N-1:0]my_signal; /* Замените N-1 на подходящее число */

Будьте внимательны, в нашем случае [N-1:0] пишется слева от названия!

Задача No2

Чтобы проверить, что блок смены знака правильно работает, присвойте шине zero значение суммы входа и выхода этого блока.

Подсказка: Устройство суммирования чисел не нужно проектировать каждый раз заново, как в лекции. Просто используйте +.

Задача No3

В модуле neg по формуле из начала лекции опишите логику превращения числа в противоположное.

Задача No4

В модуле sign_ext опишите расширение знака для превращения 12-битного числа в 32-битное.

Указания:

  • Старший бит 12-битной шины (11-ый) получают так:
wire msb = my_signal[11];
  • Объединить 20-битную и 12-битную шину (именно в таком порядке) в 32-битную можно так:
wire [19:0]my_20_bit_signal;
wire [11:0]my_12_bit_signal;
wire [31:0]my_32_bit_signal = {my_20_bit_signal, my_12_bit_signal};
  • Объединить 20 одинаковых шин:
wire [19:0]msb_x20 = {20{msb}};

Задача No5

В модуле sign_ext2 опишите схему расширения знака для превращения 12-битного числа в 32-битное с помощью тернарного оператора. Тернарный оператор op1 ? op2 : op3 имеет три операнда и принимает значение op2, если op1 == 1, иначе op3.

Пример:

wire a;
wire d = а ? 0 : 1 /* Вместо 0 и 1 могут быть сигналы типа wire */;

Вопрос: Какая уже известная нам схема описана в примере?

Задача No6

Запустите симуляцию в Icarus Verilog, посмотрите сигналы в GTKWave. Проверьте, что модуль neg действительно меняет знак, а sign_ext и sign_ext2 правильно расширяют знак.

Чтобы GTKWave показывал десятичные числа со знаком, выделите желаемые сигналы в панели "Signals" и в меню выберите нужный формат "Edit -> Data Format -> Signed Decimal".

Итоговый результат должен выглядеть примерно следующим образом:

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /