From 1ef6fd9c5c0d21119c703a37bfbe1c509e9a8d2f Mon Sep 17 00:00:00 2001 From: Andrei Solodovnikov Date: Mon, 3 Mar 2025 12:19:52 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9B=D0=A02.=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B8=D0=BD=D1=84=D0=BE=D1=80?= =?UTF-8?q?=D0=BC=D0=B0=D1=86=D0=B8=D0=B8=20=D0=BF=D0=BE=20=D0=B1=D0=B8?= =?UTF-8?q?=D1=82=D0=BE=D0=B2=D1=8B=D0=BC=20=D1=81=D0=B4=D0=B2=D0=B8=D0=B3?= =?UTF-8?q?=D0=B0=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .pic/Labs/lab_02_alu/fig_03.drawio.svg | 4 ++ .pic/Labs/lab_02_alu/fig_04.drawio.svg | 4 ++ .../lab_02_alu/{fig_04.png => fig_05.png} | Bin Labs/02. Arithmetic-logic unit/README.md | 46 +++++++++++++++--- 4 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 .pic/Labs/lab_02_alu/fig_03.drawio.svg create mode 100644 .pic/Labs/lab_02_alu/fig_04.drawio.svg rename .pic/Labs/lab_02_alu/{fig_04.png => fig_05.png} (100%) diff --git a/.pic/Labs/lab_02_alu/fig_03.drawio.svg b/.pic/Labs/lab_02_alu/fig_03.drawio.svg new file mode 100644 index 0000000..0f5ba04 --- /dev/null +++ b/.pic/Labs/lab_02_alu/fig_03.drawio.svg @@ -0,0 +1,4 @@ + + + +
1
0
0
1
1
0
1
0
0
0
1
1
0
1
0
0
0
1
0
0
1
1
0
1
0
0
1
0
0
1
1
0
1
0

Исходное число

Результат сдвига

Исходное число

Результат сдвига

\ No newline at end of file diff --git a/.pic/Labs/lab_02_alu/fig_04.drawio.svg b/.pic/Labs/lab_02_alu/fig_04.drawio.svg new file mode 100644 index 0000000..041b143 --- /dev/null +++ b/.pic/Labs/lab_02_alu/fig_04.drawio.svg @@ -0,0 +1,4 @@ + + + +
1
0
0
1
1
0
1
0
0
0
1
1
0
1
0
0
0
1
0
0
1
1
0
1
0
1
1
0
0
1
1
0
1

Исходное число

Результат сдвига

Исходное число

Результат сдвига

\ No newline at end of file diff --git a/.pic/Labs/lab_02_alu/fig_04.png b/.pic/Labs/lab_02_alu/fig_05.png similarity index 100% rename from .pic/Labs/lab_02_alu/fig_04.png rename to .pic/Labs/lab_02_alu/fig_05.png diff --git a/Labs/02. Arithmetic-logic unit/README.md b/Labs/02. Arithmetic-logic unit/README.md index bc8d285..9e0e243 100644 --- a/Labs/02. Arithmetic-logic unit/README.md +++ b/Labs/02. Arithmetic-logic unit/README.md @@ -167,16 +167,46 @@ endmodule --- -При реализации АЛУ, вам также потребуется использовать [операции сдвига](https://ru.wikipedia.org/wiki/Битовый_сдвиг), к которым относятся: +Реализуемое в данной лабораторной работе АЛУ использует операции битового сдвига. **Битовый сдвиг** — это операция, при которой все биты числа смещаются на заданное количество позиций. Сдвиг числа на _N_ бит эквивалентен _N_ сдвигам на 1 бит. В архитектуре RISC-V используются два типа сдвигов: **логический** и **арифметический**. -- `<<` — логический сдвиг влево -- `>>` — логический сдвиг вправо -- `>>>` — арифметический сдвиг вправо +При **логическом сдвиге** биты сдвигаются влево или вправо, а освободившиеся позиции заполняются нулями. При этом разряды, "вытолкнутые" за пределы разрядной сетки числа, пропадают. Например, если выполнить логический сдвиг двоичного числа _10011010_ на один бит влево, получится _00110100_. Обратите внимание, что старшая единица была вытолкнута за границу и исчезла. + +![../../.pic/Labs/lab_02_alu/fig_03.drawio.svg](../../.pic/Labs/lab_02_alu/fig_03.drawio.svg) + +_Рисунок 3. Иллюстрация преобразования двоичного числа при логическом сдвиге._ + +При арифметическом сдвиге заполнение освобождённых битов выполняется так, чтобы сохранился знак числа. В дополнительном коде знак определяется старшим битом, поэтому: + +- при **арифметическом сдвиге вправо** освободившиеся позиции заполняются значением старшего бита исходного числа. Это позволяет сохранить знак. Например, арифметический сдвиг на два бита вправо числа _10011010_ даёт _11100110_; +- **арифметический сдвиг влево** эквивалентен логическому, так как заполнение младших битов нулями не влияет на знак числа. + +![../../.pic/Labs/lab_02_alu/fig_04.drawio.svg](../../.pic/Labs/lab_02_alu/fig_04.drawio.svg) + +_Рисунок 4. Иллюстрация преобразования двоичного числа при арифметическом сдвиге._ + +Битовый сдвиг имеет важный арифметический смысл — он соответствует умножению или делению числа на степень двойки: + +- сдвиг влево на _N_ бит эквивалентен умножению на _2N_, +- сдвиг вправо на _N_ бит эквивалентен целочисленному делению на _2N_. + +Этот приём знаком должен быть знаком вам при работе с десятичной системой: умножая число на 10, мы просто дописываем справа ноль. То же самое работает и для деления: если отрезать последний разряд у числа 42, получится 4, что соответствует целочисленному делению на 10. В двоичной системе добавление (стирание) нуля справа эквивалентно умножению (делению) на 2. + +Арифметический сдвиг важен тем, что сохраняет это свойство для знаковых чисел, представленных в дополнительном коде. Логический сдвиг вправо изменяет и знак, и модуль числа, поэтому не может использоваться для деления знаковых чисел. + +Операции умножения и деления — это очень «дорогие» операции как с точки зрения элементов схемы (если эти операции реализуются аппаратно), так и с точки зрения времени их вычисления. Поэтому выполнение сдвигов в качестве замены умножения применяется повсеместно. Например, написав в коде языка C++ выражение `var * 8`, после компиляции вы наверняка получите операцию сдвига влево на 3. + +Ещё одно применение сдвигов: установка и очищение флагов управляющих регистров. Дело в том, что обычно процессоры не имеют доступа к отдельным битам многоразрядных регистров — их значения читаются записываются целиком. Вот как можно реализовать битовые операции с помощью сдвигов: + +```C++ +X = X | (1 << N); // Установка N-го бита +X = X & ~(1 << N); // Очистка N-го бита +Y = (X & (1 << N)) != 0; // Чтение N-го бита +``` ### Особенности реализации сдвига > [!IMPORTANT] -> Для **ВСЕХ** операций сдвига вы должны брать только 5 младших бит операнда B. +> Для **ВСЕХ** операций сдвига в данной лабораторной работе вы должны брать только 5 младших бит операнда B. > > Сами посмотрите: выполнять операцию сдвига более чем на 31 для 32-битных чисел не имеет смысла, число полностью заполнится нулями (единицами). Т.е. сдвигая на любое число, большее 31, вы получите один и тот же результат. Для того чтобы закодировать 31 требуется минимум 5 бит, отсюда и это требование. Оно обязательно, поскольку старшие биты в дальнейшем будут использоваться по другому назначению и, если вы упустите это, ваш будущий процессор станет работать неправильно. @@ -270,13 +300,13 @@ assign Result = $signed(A) / 10; В этом примере некоторому сигналу `Result` присваивают результат деления **знакового** числа `A` на `10`. -Так как используются не все возможные комбинации управляющего сигнала АЛУ, то **при описании через `case` не забывайте использовать `default`**. Если описать АЛУ как задумано, то получится что-то похожее на _рис. 4_. Но не обязательно, зависит от вашего описания. +Так как используются не все возможные комбинации управляющего сигнала АЛУ, то **при описании через `case` не забывайте использовать `default`**. Если описать АЛУ как задумано, то получится что-то похожее на _рис. 5_. Но не обязательно, зависит от вашего описания. ![../../.pic/Labs/lab_02_alu/fig_04.png](../../.pic/Labs/lab_02_alu/fig_04.png) -_Рисунок 3. Пример схемы, реализующей АЛУ._ +_Рисунок 5. Пример схемы, реализующей АЛУ._ -Обратите внимание на то, что сумматор на _рис. 3_ отличается от всех остальных блоков. Для того, чтобы спроектированный в ЛР№1 32-разрядный сумматор был создан не зазря, а также для закрепления навыков по созданию экземпляров модулей внутри других модулей, вам предлагается использовать его при реализации АЛУ. +Обратите внимание на то, что сумматор на _рис. 5_ отличается от всех остальных блоков. Для того, чтобы спроектированный в ЛР№1 32-разрядный сумматор был создан не зазря, а также для закрепления навыков по созданию экземпляров модулей внутри других модулей, вам предлагается использовать его при реализации АЛУ. Другие блоки распознаны Vivado на основе представленных в описании АЛУ арифметических или логических выражений и в процессе синтеза будут реализованы через те компоненты ПЛИС, которые позволят лучше всего удовлетворить временным и физическим ограничениям проекта (см. главу "Этапы реализации проекта в ПЛИС"). Сумматор же будет реализован так, как это описали мы, поскольку вместо использования абстрактной операции "+" в описании АЛУ было сказано разместить конкретный модуль, реализующий конкретную схему. Такая реализация сумматора не является эффективной ни в плане временных характеристик, ни в плане количества затраченных на реализацию ресурсов ПЛИС. Но как уже упоминалось в ЛР№1, цель этой реализации — воспроизвести простоту логики рассуждений о том, как спроектировать сумматор.