Уровень 50: АЛУ на 32 бита

Открыть уровень →

Задание

Цель: собрать АЛУ учебного RV32I-подмножества. Девять операций вы строите сами — add/sub/sll/srl/slt/sltu/and/or/xor, десятая sra уже готова: модуль sra32.v только для чтения. Кодов op десять (0–9) — производная funct3/funct7: 0 add, 1 sll, 2 slt, 3 sltu, 4 xor, 5 srl, 6 or, 7 and, 8 sub, 9 sra.

Соберите арифметико-логическое устройство учебного RV32I-подмножества — блок Alu32. Девять операций вы строите сами: add, sub, sll, srl, slt, sltu, and, or, xor. Десятая, sra (арифметический сдвиг вправо), уже готова — модуль sra32.v в проекте только для чтения, его нужно переиспользовать.

Проект многофайловый:

  • alu.v — главный файл: декодер op, все операционные блоки и итоговый мьюкс.
  • fa32.v — полный сумматор (уровень 34): xor/and/or, из него вы соберёте 32-битную цепочку.
  • sra32.v — только для чтения: готовый арифметический сдвиг.

Интерфейс Alu32: входы a[31:0], b[31:0], op[3:0]; выходы r[31:0], zero.

Коды op — производная от полей funct3/funct7 настоящей команды:

opОперацияopОперация
0add5srl
1sll6or
2slt7and
3sltu8sub
4xor9sra

Коды 10–15 не используются: на них эталон выдаёт r=0 и zero=1. Структурные требования: инстанс Sra32 в alu.v и не меньше 32 инстансов FA32 в цепочке переносов. Схема проверяет АЛУ на всех десяти операциях против эталонной модели — с граничными значениями: 0, −1, 0x80000000, 0x7FFFFFFF, сдвиги на 0, 31 и 32 позиции.

Решение для самопроверки

Сначала попробуйте собрать АЛУ сами. Ниже — контрольный список сборки.

Что должно получиться: АЛУ совпадает с эталоном на всех десяти операциях с граничными значениями 0, −1, 0x80000000, 0x7FFFFFFF и сдвигами на 0, 31 и 32 позиции; флаг zero считается nor-деревом по 32 битам результата.

Шаг 1 — one-hot декод op. Четыре инвертора по битам op, и-цепочки на сигналы sel0…sel9. Один активный sel включает свой блок и его строку в итоговом мьюксе.

Шаг 2 — сумматор и вычитание одним трактом. Цепочка из 32 FA32. Вычитание — дополнительный код: bx = b ^ binv, входной перенос cin = binv, где binv = 1 для sub, slt и sltu (binv = op[1] | op[3]). Сложение и вычитание используют один и тот же сумматор.

Шаг 3 — сравнения. sltu — это NOT выходного переноса: беззнаковое «a меньше b» ровно тогда, когда вычитание заняло за пределы разрядности. slt тоньше: slt = sum[31] ^ ovf, где ovf = (a31^b31) & (sum31^a31) — переполнение дополнительного кода. Оба результата 32-битные: все нули или …001. Именно тракт вычитания из шага 2 делает оба сравнения корректными — перепутанные slt и sltu — классическая ошибка этого уровня: на отрицательных числах они дают разные ответы (предсказание уровня проверяет пару a=0x80000000, b=1).

Шаг 4 — сдвиги. Barrel-сдвиг: 5 ступеней, ступень k управляется битом b[k] — каждая ступень либо пропускает биты насквозь, либо сдвигает на 2^k. sll сдвигает влево, srl — вправо с нулями. sra подключите готовым инстансом Sra32(sr, a, b[4:0]) — арифметический сдвиг копирует старший бит, сохраняя знак.

Шаг 5 — итоговый мьюкс и zero. По битам: 10 вентилей AND (по одному на sel) и or-дерево. zero — nor-дерево по всем 32 битам r: единица, когда результат равен нулю. Это внутренний сигнал нашего АЛУ — он пригодится командам beq/bne на уровнях 53–54. Архитектурного регистра флагов в RV32I нет.

Проверь себя

Почему slt и sltu нельзя перепутать?

sltu — это NOT выходного переноса вычитания, а slt учитывает переполнение дополнительного кода (slt = sum[31] ^ ovf). На отрицательных числах — например, a = 0x80000000, b = 1 — они дают разные ответы.