mirror of
https://github.com/MPSU/APS.git
synced 2025-09-15 17:20:10 +00:00
Синхронизация с правками публикуемого издания (#101)
* СП. Обновление предисловия * СП. Обновление введения * СП. Обновление лаб * СП. Обновление доп материалов * СП. Введение * СП. Введение * СП. ЛР№4, 15 * СП. Базовые конструкции Verilog * Update Implementation steps.md * СП. ЛР 4,5,7,8,14 * СП. ЛР№8 * Синхронизация правок * СП. Финал * Исправление ссылки на рисунок * Обновление схемы * Синхронизация правок * Добавление белого фона .drawio-изображениям * ЛР2. Исправление нумерации рисунка
This commit is contained in:
committed by
GitHub
parent
d251574bbc
commit
9739429d6e
@@ -24,35 +24,27 @@
|
||||
|
||||
**Арифметико-логическое устройство** (**АЛУ**, Arithmetic Logic Unit – ALU) – это блок процессора, выполняющий арифметические и поразрядно логические операции. Разница между арифметическими и логическими операциями в отсутствии у последних бита переноса, так как логические операции происходят между 1-битными числами и дают 1-битный результат, а в случае АЛУ (в рамках данной лабораторной работы) одновременно между 32-мя 1-битными парами чисел. В логических операциях результаты значений отдельных битов друг с другом никак не связаны.
|
||||
|
||||
Также, кроме результата операций, АЛУ формирует флаги, которые показывают выполняется ли заданное условие. Например, выведет `1`, если один операнд меньше другого.
|
||||
Также, кроме результата операций, может формировать специальные сигналы-флаги, которые показывают выполняется ли заданное условие. Например, выводить `1`, если один операнд меньше другого, или если в результате суммы произошло переполнение.
|
||||
|
||||
Обычно АЛУ представляет собой комбинационную схему (то есть не имеет элементов памяти), на входы которой поступают информационные (операнды) и управляющие (код операции) сигналы, в ответ на что на выходе появляется результат заданной операции. АЛУ бывает не комбинационной схемой, но это скорее исключение.
|
||||
Обычно АЛУ представляет собой комбинационную схему (то есть не имеет элементов памяти), на входы которой поступают информационные (операнды) и управляющие (код операции) сигналы, в ответ на что на выходе появляется результат заданной операции. АЛУ может быть реализовано и в виде последовательностной логики, но это скорее исключение.
|
||||
|
||||

|
||||
|
||||
_Рисунок 1. Структурное обозначение элемента АЛУ[[1, стр. 305]](https://reader.lanbook.com/book/97336?lms=57991a6f83ced8530d7f0759ce4b95b7)._
|
||||
_Рисунок 1. Структурное обозначение элемента АЛУ[[1, стр. 304]](https://reader.lanbook.com/book/241166?lms=1b8d65a957786d4b32b8201bd30e97f3)._
|
||||
|
||||
На рис. 1 изображен пример АЛУ, используемый в книге "Цифровая схемотехника и архитектура компьютера" Харрис и Харрис. На входы `A` и `B` поступают операнды с разрядностью _N_. На 3-битный вход `F` подается код операции. Например, если туда подать `000`, то на выходе `Y` появится результат операции _логическое И_ между битами операндов `A` и `B`. Если на `F` подать `010`, то на выходе появится результат сложения. Это лишь пример, разрядность и коды могут отличаться в зависимости от количества выполняемых операций и архитектуры.
|
||||
На рис. 1 изображено структурное обозначение АЛУ, используемое в книге "Цифровая схемотехника и архитектура компьютера RISC-V" Харрис и Харрис. На входы `A` и `B` поступают операнды с разрядностью _N_. На 2-битный вход `ALUControl` подается код операции. Например, если туда подать `10`, то на выходе `Y` появится результат операции _логическое И_ между битами операндов `A` и `B`. Если же подать `00`, то на выходе появится результат сложения. Это лишь пример, разрядность и коды могут отличаться в зависимости от количества выполняемых операций и архитектуры.
|
||||
|
||||
Существует несколько подходов к реализации АЛУ, отличающиеся внутренней организацией. В лабораторных работах применяется повсеместно используемый подход мультиплексирования операций, то есть подключения нескольких операционных устройств (которые выполняют какие-то операции, например сложения, логического ИЛИ и т.п.) к мультиплексору, который будет передавать результат нужного операционного устройства на выходы АЛУ.
|
||||
|
||||
Рассмотрим данный подход на примере все того же АЛУ MIPS из книги Харрисов. На рис. 2, в левой его части, изображена внутренняя организация этого АЛУ, справа – таблица соответствия кодов операциям. На выходе схемы (внизу) стоит 4-входовой мультиплексор, управляемый двумя из трех битов `F`. К его входам подключены _N_ логических И (побитовое И _N_-битных операндов), _N_ логических ИЛИ, _N_-битный сумматор и Zero Extend – устройство, дополняющее слева нулями 1-битное число до N-битного.
|
||||
Рассмотрим данный подход на примере всё того же АЛУ из книги Харрисов. На рис. 2, в левой его части, изображена внутренняя организация этого АЛУ, справа – таблица соответствия кодов операциям. На выходе схемы (внизу) стоит 4-входовой мультиплексор, управляемый 2-битным сигналом `ALUControl`. Ко входам мультиплексора подключены выходы `N` логических И (побитовое И N-битных операндов), `N` логических ИЛИ, а выход N-битного сумматора подключён дважды, позволяя выбирать его результат для двух кодов операции.
|
||||
|
||||

|
||||
|
||||
_Рисунок 2. Структурная схема АЛУ MIPS[[1, стр. 305]](https://reader.lanbook.com/book/97336?lms=57991a6f83ced8530d7f0759ce4b95b7)._
|
||||
_Рисунок 2. Структурная схема АЛУ [[1, стр. 305]](https://reader.lanbook.com/book/241166?lms=1b8d65a957786d4b32b8201bd30e97f3)._
|
||||
|
||||
К одному из входов этих операционных устройств подключен без изменений вход `A`, а ко второму подключен выход двухвходового мультиплексора, управляемого оставшимся битом _F_. То есть `F[2]` определяет, что будет вторым операндом: `B` или `~B`. Вдобавок `F[2]` подается на входной перенос сумматора, то есть, когда `F[2] == 1` на выходе сумматора появляется результат операции `A + ~B + 1`, что (с учетом [дополнительного кода](https://ru.wikipedia.org/wiki/Дополнительный_код)) эквивалентно `A – B`.
|
||||
Вход `A` подключается напрямую ко входам этих операционных устройств. Вход `B` тоже — за исключением подключения к сумматору. На вход второго операнда сумматора подаётся результат мультиплексирования сигналов `B` и `~B`. Управляющим сигналом этого мультиплексора является младший бит управляющего сигнала `ALUControl`. Кроме того, этот же младший бит подаётся и на сумматор в качестве входного бита переноса. Это означает, что когда `ALUControl[0] = 0`, вычисляется сумма `A + B + 0`, а когда `ALUControl[0] = 1`, вычисляется сумма `A + ~B + 1`, что (с учётом [дополнительного кода](https://ru.wikipedia.org/wiki/Дополнительный_код) ) эквивалентно `A – B`.
|
||||
|
||||
Посмотрим, что произойдет, если на вход `F` такого АЛУ подать `111`. Будет выполняться операция `SLT`(сокращение от `Set Less Then`) – выдать `1`, если `A` меньше `B`, в противном случае — выдать `0`. Биты `F[1:0]` переключат мультиплексор на выход блока Zero Extend. На вход Zero Extend поступает старший бит выхода сумматора, этот бит отвечает за знак результата. Так как `F[2] == 1`, сумматор вычисляет `A + ~B + 1`, то есть `A – B`. Если `A < B`, то результат вычитания будет отрицательный, а старший бит `Y[N-1] == 1`. Если `A` не меньше `B`, то разность будет неотрицательна, а `Y[N-1] == 0`, как и требуется от этой операции.
|
||||
|
||||
Сравнение двух чисел несколько сложнее чем просто проверка старшего бита разности и зависит от того, сравниваем ли мы знаковые числа или беззнаковые. Если знаковые — то произошло ли переполнение. Для простоты схемы, принято, что схема реализует операцию SLT для знаковых пар чисел, разность которых не вызывает переполнения [[2, 307]](https://reader.lanbook.com/book/241166?lms=1b8d65a957786d4b32b8201bd30e97f3).
|
||||
|
||||

|
||||
|
||||
_Рисунок 3. Пример исполнения операции АЛУ._
|
||||
|
||||
Преимущество такой организации АЛУ в его простой модификации, настройке под нужные коды операций, читаемости кода и масштабируемости. Можно легко добавить или убрать требуемые операции. Подумайте, как бы вы обновили данную схему, если бы от вас потребовалось расширить её функционал операциями XOR (Исключающее ИЛИ) и (SGE операция "больше либо равно")?
|
||||
Преимущество такой организации АЛУ в простоте его модификации, настройке под нужные коды операций, читаемости кода и масштабируемости. Можно легко добавить или убрать требуемые операции. Подумайте, как бы вы обновили данную схему, если бы от вас потребовалось расширить её функционал операциями XOR (Исключающее ИЛИ) и (SGE операция "больше либо равно")?
|
||||
|
||||
## Инструменты
|
||||
|
||||
@@ -64,7 +56,7 @@ _Рисунок 3. Пример исполнения операции АЛУ._
|
||||
|
||||
Очень удобным на практике оказывается использование параметров. Параметры добавляют модулю гибкости, позволяя убрать ["магические"](https://ru.wikipedia.org/wiki/Магическое_число_(программирование)#Плохая_практика_программирования) константы из описания модулей, подставляя вместо них выразительное символьное имя. Параметры отдаленно схожи с макросами `#define` в языке Си, однако стоит понимать, что это не одно и то же. Дефайны представляют собой специальные текстовые макросы, которые автоматически заменяются на этапе препроцессора (как если бы вы прошлись по всем файлам своего кода и вручную заменили бы макросы на их значения). Например, с помощью дефайнов можно писать целые куски кода, а не просто одно какое-то число. При этом у дефайнов глобальная область видимости (объявив их в одном месте, этот макрос будет доступен во всем последующем коде). Параметр в свою очередь может хранить только значение какого-то конкретного типа (т.е. в параметр нельзя поместить фрагмент кода) а область видимости параметра ограничена тем модулем, где он был объявлен.
|
||||
|
||||
Допустим, ваше устройство должно включить тостер, если на вход ему придет сигнал `32'haf3c5bd0`. Человек, не знакомый с устройством, при прочтении этого кода будет недоумевать, что это за число и почему используется именно оно. Однако, скрыв его за параметром `TOASTER_EN`, читающий поймет, что это код включения тостера. Кроме того, если некоторая константа должна использоваться в нескольких местах кода, то определив её через в виде параметра, можно будет менять её в одном месте, и она тут же поменяется везде.
|
||||
Допустим, ваше устройство должно включить тостер, если на вход ему придет сигнал `32'haf3c5bd0`. Человек, не знакомый с устройством, при прочтении этого кода будет недоумевать, что это за число и почему используется именно оно. Однако, скрыв его за параметром `TOASTER_EN`, читающий поймет, что это код включения тостера. Кроме того, если некоторая константа должна использоваться в нескольких местах кода, то определив её в виде параметра, можно будет менять её в одном месте, и она тут же поменяется везде.
|
||||
|
||||
Параметры позволяют влиять на структуру модуля. К примеру, описывая сумматор, можно параметризовать его разрядность и использовать этот параметр при описании модуля (например, в качестве диапазона массива модулей). В этом случае вы сможете создавать множество сумматоров различных разрядностей, подставляя при создании нужное вам значение параметра.
|
||||
|
||||
@@ -83,10 +75,10 @@ module overflow #(parameter WIDTH = 32)(
|
||||
output logic overflow
|
||||
);
|
||||
|
||||
logic [WIDTH : 0] sum;
|
||||
logic [WIDTH : 0] sum;
|
||||
|
||||
assign sum = a + b;
|
||||
assign overflow = sum[WIDTH];
|
||||
assign sum = a + b;
|
||||
assign overflow = sum[WIDTH];
|
||||
|
||||
endmodule
|
||||
```
|
||||
@@ -101,8 +93,8 @@ module toaster(
|
||||
output logic power
|
||||
)
|
||||
|
||||
parameter TOASTER_EN = 32'haf3c5bd0;
|
||||
assign power = command == TOASTER_EN;
|
||||
parameter TOASTER_EN = 32'haf3c5bd0;
|
||||
assign power = command == TOASTER_EN;
|
||||
|
||||
endmodule
|
||||
```
|
||||
@@ -181,19 +173,12 @@ endmodule
|
||||
- `>>` — логический сдвиг вправо
|
||||
- `>>>` — арифметический сдвиг вправо
|
||||
|
||||
<br><br><br><br><br>
|
||||
|
||||
---
|
||||
|
||||
### Особенности реализации сдвига
|
||||
|
||||
**Для ВСЕХ операций сдвига вы должны брать только 5 младших бит операнда B.**
|
||||
|
||||
Сами посмотрите: пятью битами можно описать 32 комбинации [0-31], а у операнда А будет использоваться ровно 32 бита. **Это обязательное требование**, поскольку старшие биты в дальнейшем будут использоваться по другому назначению и, если вы упустите это, ваш будущий процессор станет работать неправильно.
|
||||
|
||||
---
|
||||
|
||||
<br><br><br><br><br>
|
||||
> [!IMPORTANT]
|
||||
> Для **ВСЕХ** операций сдвига вы должны брать только 5 младших бит операнда B.
|
||||
>
|
||||
> Сами посмотрите: выполнять операцию сдвига более чем на 31 для 32-битных чисел не имеет смысла, число полностью заполнится нулями (единицами). Т.е. сдвигая на любое число, большее 31, вы получите один и тот же результат. Для того чтобы закодировать 31 требуется минимум 5 бит, отсюда и это требование. Оно обязательно, поскольку старшие биты в дальнейшем будут использоваться по другому назначению и, если вы упустите это, ваш будущий процессор станет работать неправильно.
|
||||
|
||||
## Задание
|
||||
|
||||
@@ -209,7 +194,7 @@ module alu (
|
||||
output logic [31:0] result_o
|
||||
);
|
||||
|
||||
import alu_opcodes_pkg::*; // импорт параметров, содержащих
|
||||
import alu_opcodes_pkg::*; // импорт параметров, содержащих
|
||||
// коды операций для АЛУ
|
||||
|
||||
endmodule
|
||||
@@ -219,33 +204,33 @@ endmodule
|
||||
|
||||
Для удобства чтения, список инструкций разбит на две таблицы.
|
||||
|
||||
В первой таблице перечислены операции, вычисляющие значение сигнала `result_o`. **При любом коде операции `alu_op_i` не входящим в эту таблицу, сигнал `result_o` должен быть равен нулю**.
|
||||
В первой таблице перечислены операции, вычисляющие значение сигнала `result_o`. **При любом коде операции, не входящим в эту таблицу, сигнал `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 | Побитовое логическое **И** |
|
||||
|Операция|={cmp, mod, opcode}|Выражение | Действие |
|
||||
|--------|-------------------|-----------------------|-------------------------------------------------------|
|
||||
| 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` должен быть равен нулю**.
|
||||
Во второй таблице перечислены операции, вычисляющие значение сигнала `flag_o`. **При любом коде операции, не входящим в эту таблицу, сигнал 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 | Беззнаковое сравнение **≥** |
|
||||
|Операция|={cmp, mod, opcode}| Выражение | Действие |
|
||||
|--------|-------------------|----------------------|-----------------------------------|
|
||||
| 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. Список операций сравнения._
|
||||
|
||||
@@ -280,16 +265,16 @@ _Таблица 2. Список операций сравнения._
|
||||
Конструкция `$signed` говорит САПР интерпретировать число, переданное в качестве операнда, как знаковое.
|
||||
|
||||
```Verilog
|
||||
assign Result = $signed(A) >>> B[4:0];
|
||||
assign Result = $signed(A) / 10;
|
||||
```
|
||||
|
||||
В этом примере некоторому сигналу `Result` присваивают результат сдвига знакового числа `A` на значение количества бит получаемых из младших 5 бит сигнала `B`.
|
||||
В этом примере некоторому сигналу `Result` присваивают результат деления **знакового** числа `A` на `10`.
|
||||
|
||||
Так как используются не все возможные комбинации управляющего сигнала АЛУ, то **при описании через `case` не забывайте использовать `default`**. Если описать АЛУ как задумано, то получится что-то похожее на _рис. 4_. Но не обязательно, зависит от вашего описания.
|
||||
|
||||

|
||||
|
||||
_Рисунок 4. Пример схемы, реализующей АЛУ._
|
||||
_Рисунок 3. Пример схемы, реализующей АЛУ._
|
||||
|
||||
### Порядок выполнения задания
|
||||
|
||||
|
Reference in New Issue
Block a user