Проектирование блока управления
Практическая работа 10. Проектирование дешифратора инструкций. Блока управления. Сборка процессора
Необходимые материалы для лекции asm+hex.zip, Logisim-10.zip и Verilog-10.zip.
Несмотря на то, что современные RISC процессоры строятся таким образом, что в формате команды заложен код операции и адреса операндов, но может потребоваться дополнительная расшифровка этих самых операций. Для этого потребуется дешифратор команд. Дешифратор команд является конечным автоматом. При этом входным символом является код операции или opcode, а выходным символом будет являться результирующая строка, представляющая собой развёрнутую информацию о команде.
Рассмотрим построение дешифратора команд на примере сложения непосредственным операндом: addi x1, x2, 5 , где x1- регистр результата, x2 - слагаемое, 5 - непосредственное слагаемое. Если разложить данную инструкцию на микрокоманды управления, то их последовательность будет иметь вид:
- Выставить адрес x2 на шине адреса операнда rs1 регистрового файла;
- Коммутировать часть содержащую непосредственные данные на линию второго операнда АЛУ;
- Коммутировать данные с выхода АЛУ на вход данных регистрового файла;
- Включить запись в регистровый файл по адресу регистра x1.
В однотактном процессоре данная операция должна быть совершена за один такт. Задача дешифратора максимально детализировать сигналы, применяемые для активации соответствующих блоков. При этом в период дешифрации инструкций могут быть получены дополнительные признаки: знаковая / беззнаковая операция, наличие переходов.
Графически операция сложения с непосредственным операндом выглядит как показано на рисунке 10.1 (IG - блок непосредственных значений).
Для проектирования дешифратора необходимо коды инструкций, применяемые в процессоре, собрать в единую таблицу (таблица 10.1). Для проектирования будут использованы столбцы opcode и opcode HEX.
Формат инструкции | Мнемоника инструкции | Opcode | Opcode HEX | Funct3 |
---|---|---|---|---|
R-style | add | 0110011 | 0x33 | 000 |
sub | 0110011 | 0x33 | 000 | |
sll | 0110011 | 0x33 | 001 | |
xor | 0110011 | 0x33 | 100 | |
srl | 0110011 | 0x33 | 101 | |
sra | 0110011 | 0x33 | 101 | |
or | 0110011 | 0x33 | 110 | |
and | 0110011 | 0x33 | 111 | |
I-type | lb | 0000011 | 0x3 | 000 |
lh | 0000011 | 0x3 | 001 | |
lw | 0000011 | 0x3 | 010 | |
ld | 0000011 | 0x3 | 011 | |
lbu | 0000011 | 0x3 | 100 | |
lhu | 0000011 | 0x3 | 101 | |
lwu | 0000011 | 0x3 | 110 | |
addi | 0010011 | 0x13 | 000 | |
slli | 0010011 | 0x13 | 001 | |
xori | 0010011 | 0x13 | 100 | |
srli | 0010011 | 0x13 | 101 | |
srai | 0010011 | 0x13 | 101 | |
ori | 0010011 | 0x13 | 110 | |
andi | 0010011 | 0x13 | 111 | |
jalr | 1100111 | 0x67 | 000 | |
S-type | sb | 0100011 | 0x23 | 000 |
sh | 0100011 | 0x23 | 001 | |
sw | 0100011 | 0x23 | 010 | |
sd | 0100011 | 0x23 | 111 | |
SB-type | beq | 1100011 | 0x63 | 000 |
bne | 1100011 | 0x63 | 001 | |
blt | 1100011 | 0x63 | 100 | |
bge | 1100011 | 0x63 | 101 | |
bltu | 1100011 | 0x63 | 110 | |
bgeu | 1100011 | 0x63 | 111 | |
u-type | lui | 0110111 | 0x37 | Не определен |
Uj-type | jal | 1101111 | 0x6f | Не определен |
Так как в данном случае дешифратор должен анализировать входную комбинацию и формировать выходной сигнал, то можно смоделировать его схему по принципу проверки равенства постоянного значения opcode входной комбинации. Для этого используется элемент компаратор. Opcode будут константами. Ширина поля opcode составляет 7 бит.
Создадим новую схему в проекте cpu.circ. Имя присвоим instdec. Разместим на поле 8 компараторов c разрядностью 7 бит (формат числа - беззнаковый) для форматов инструкций: R,S, I (отдельно для Load), а также выпадающих из форматов инструкций: jalr, jal, lui, auipc, beq.
Объединим все входы первых операндов в общую шину и подключим к элементу тоннель. Метке тоннеля задать свойство Inst6_0, а его разрядность определить равной 7. Вторые входы компараторов подключим к константам, соответствующим полю opcode: 33,03,23,63,13,67,6f,37,17. Выходы равенства подключим к элементам выход. Меткам выходов присвоить соответствующие значения: R_format, Load, Store, Branch, I_type, Jalr, Jal, Lui, Auipc. Схема функциональная дешифратора приведена на рисунке 10.2.
Следующим этапом необходимо обратиться к формату инструкций, так как в них, в зависимости от opcode, могут быть закодированы разные функциональные сигналы в одних и тех же позициях. Поле, начиная с 7 адреса может содержать адреса регистров либо непосредственные значения. Для переопределения данных, поступающих в теле инструкций, применяется блок, именуемый Immediate Generator - блок непосредственных значений. При проектировании данного блока необходимо воспользоваться описанием полей для различного формата команд (рисунок 10.3).
Создадим новую схему, присвоим ей наименование IMMGEN. Фактически схема будет представлять собой сплиттер (разветвитель) сигналов шины и сборщик сигналов в шину.
Разместим на поле вход с разрядностью равной 32. Свойство метки зададим instr. Подключим к нему разветвитель с настройками:
Веерный выход - 9;
Разрядность входа - 32;
"Внешний вид" - праворукий;
- Бит 0 - 6 задать настройки (0, сверху);
- Бит 7 - 1;
- Бит 8-11 - 2;
- Бит 12-14 - 3;
- Бит 15-19 - 4;
- Бит 20 - 5;
- Бит 21-24 - 6;
- Бит 25-30 - 7;
- Бит 31 - 8.
К выходу 6-0 подключим элемент "Не подключайтесь" в разделе проводка (задать разрядность 7). Полученный разветвитель приведен на рисунке 10.4.