ЛР2. Разделение таблицы опкодов АЛУ на 2 части.

Это должно повысить читаемость.
This commit is contained in:
Andrei Solodovnikov
2024-01-26 15:45:23 +03:00
parent d0bf82df6c
commit 88b9aa51f3

View File

@@ -205,39 +205,52 @@ import alu_opcodes_pkg::*; // импорт параметров, содер
endmodule
```
Для стандартного набора целочисленных операций архитектуры RISC-V требуется выполнять 16 различных операций. Для кодирования 16 операций было бы достаточно 4 бит, но в лабораторной работе предлагается использовать 5-битный код, что связано с особенностями кодирования инструкций (будет рассмотрено в лекциях 6 и 7). Видно, что старший бит кода операции указывает на то, является ли операция вычислительной или это операция сравнения.
Для стандартного набора целочисленных операций архитектуры RISC-V требуется выполнять 16 различных операций. Для кодирования 16 операций было бы достаточно 4 бит, но в лабораторной работе предлагается использовать 5-битный код, что связано с особенностями кодирования инструкций. Видно, что старший бит кода операции указывает на то, является ли операция вычислительной или это операция сравнения.
|ALUOp|={flag, add/sub, aluop}|Result |Flag |Операция |
|-----|-----------------------|-----------------------------------|-----------------------------------|---------------------------------------------------|
| ADD | 0 0 000 |Result = А + В | Flаg = 0 | Сложение |
| SUB | 0 1 000 |Result = А В | Flаg = 0 | Вычитание |
| SLL | 0 0 001 |Result = А << В | Flаg = 0 | Сдвиг влево |
| SLTS| 0 0 010 |Result = А < В (знаковое сравнение)| Flаg = 0 | Знаковое сравнение |
| SLTU| 0 0 011 |Result = А < В | Flаg = 0 | Беззнаковое сравнение |
| XOR | 0 0 100 |Result = А ^ В | Flаg = 0 | Побитовое исключающее **ИЛИ** |
| SRL | 0 0 101 |Result = А >> В | Flаg = 0 | Сдвиг вправо |
| SRA | 0 1 101 |Result = А >>> В | Flаg = 0 | Арифметический сдвиг вправо (операнд А — знаковый)|
| OR | 0 0 110 |Result = А \| В | Flаg = 0 | Побитовое логическое **ИЛИ** |
| AND | 0 0 111 |Result = А & В | Flаg = 0 | Побитовое логическое **И** |
| EQ | 1 1 000 |Result = 0 | Flаg = (А == В) | Выставить флаг, если **равны** |
| NE | 1 1 001 |Result = 0 | Flаg = (А != В) | Выставить флаг, если **не равны** |
| LTS | 1 1 100 |Result = 0 | Flаg = А < В (знаковое сравнение) | Знаковое сравнение **<** |
| GES | 1 1 101 |Result = 0 | Flаg = А В (знаковое сравнение) | Знаковое сравнение **≥** |
| LTU | 1 1 110 |Result = 0 | Flаg = А < В | Беззнаковое сравнение **<** |
| GEU | 1 1 111 |Result = 0 | Flаg = А В | Беззнаковое сравнение **≥** |
Для удобства чтения, список инструкций разбит на две таблицы.
**Выражения в этой таблице приведены для примера. Не все из них можно просто переписать — часть этих выражений надо дополнить. Чтобы вы не копировали выражения, в них вставлены неподдерживаемые символы.**
В первой таблице перечислены операции, вычисляющие значение сигнала `result_o`. **При любом коде операции `alu_op_i` не входящим в эту таблицу, сигнал `result_o` должен быть равен нулю**.
Обратите внимание на инструкции сравнения. У нас есть две похожие пары инструкций:
|alu_op_i|={cmp, add/sub, alu_op_i}|result_o |Операция |
|--------|-------------------------|-------------------------------------------|-------------------------------------------------------|
| ADD | 0 0 000 |result_o = a_i + b_i | Сложение |
| SUB | 0 1 000 |result_o = a_i b_i | Вычитание |
| SLL | 0 0 001 |result_o = a_i << b_i | Сдвиг влево |
| SLTS | 0 0 010 |result_o = a_i < b_i (знаковое сравнение)| Знаковое сравнение |
| SLTU | 0 0 011 |result_o = a_i < b_i | Беззнаковое сравнение |
| XOR | 0 0 100 |result_o = a_i ^ b_i | Побитовое исключающее **ИЛИ** |
| SRL | 0 0 101 |result_o = a_i >> b_i | Сдвиг вправо |
| SRA | 0 1 101 |result_o = a_i >>> b_i | Арифметический сдвиг вправо (операнд `a_i` — знаковый)|
| OR | 0 0 110 |result_o = a_i \| b_i | Побитовое логическое **ИЛИ** |
| AND | 0 0 111 |result_o = a_i & b_i | Побитовое логическое **И** |
*Таблица 1. Список вычислительных операций.*
В первой таблице перечислены операции, вычисляющие значение сигнала `flag_o`. **При любом коде операции `alu_op_i` не входящим в эту таблицу, сигнал `flag_o` должен быть равен нулю**.
|alu_op_i|={cmp, add/sub, alu_op_i}| flag_o | Операция |
|--------|-------------------------|------------------------------------------|-----------------------------------|
| EQ | 1 1 000 | flag_o = (a_i == b_i) | Выставить флаг, если **равны** |
| NE | 1 1 001 | flag_o = (a_i != b_i) | Выставить флаг, если **не равны** |
| LTS | 1 1 100 | flag_o = a_i < b_i (знаковое сравнение)| Знаковое сравнение **<** |
| GES | 1 1 101 | flag_o = a_i b_i (знаковое сравнение)| Знаковое сравнение **≥** |
| LTU | 1 1 110 | flag_o = a_i < b_i | Беззнаковое сравнение **<** |
| GEU | 1 1 111 | flag_o = a_i b_i | Беззнаковое сравнение **≥** |
*Таблица 2. Список операций сравнения.*
**Выражения в этих двух таблицах приведены для примера. Не все из них можно просто переписать — часть этих выражений надо дополнить. Чтобы вы не копировали выражения, в них вставлены неподдерживаемые символы.**
Несмотря на разделение на вычислительные операции, и операции сравнения, в *Таблице 1* (вычислительных операция) оказалось две операции `SLTS` и `SLTU`, которые выполняют сравнения. В итоге у нас есть две похожие пары инструкций:
- `LTS`
- `LTU`
- `SLTS`
- `SLTU`
Первая пара инструкций вычисляет "ветвительный" результат. Результат операции будет подан на выходной сигнал `Flag` и использован непосредственно при ветвлении.
Первая пара инструкций вычисляет "ветвительный" результат. Результат операции будет подан на выходной сигнал `flag_o` и использован непосредственно при ветвлении.
Вторые две инструкции используются для получения "вычислительного" результата. Т.е. результат сравнения будет подан на выходной сигнал `Result` так же, как подается результат операции `ADD`, и будет использован в неких вычислениях, избегая при этом условного перехода.
Вторые две инструкции используются для получения "вычислительного" результата. Т.е. результат сравнения будет подан на выходной сигнал `result_o` так же, как подается результат операции `ADD`, и будет использован в неких вычислениях, избегая при этом условного перехода.
К примеру, нам необходимо пройтись по массиву из миллиона элементов и убедиться, что все они были неотрицательны. Об этом будет сигнализировать переменная `num_of_err`, значение которой должно быть равно числу элементов массива, меньших нуля. Вычислить значение этой переменной можно двумя способами: