Уровень 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 | Операция |
|---|---|---|---|
| 0 | add | 5 | srl |
| 1 | sll | 6 | or |
| 2 | slt | 7 | and |
| 3 | sltu | 8 | sub |
| 4 | xor | 9 | sra |
Коды 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 — они дают разные ответы.