Skip to content

Commit

Permalink
Laborator 6 - ALU (#33)
Browse files Browse the repository at this point in the history
* Added white background to images for dark mode visibility

* Explained ALU implementation

* Missed a word

* Shrink operands to 5 bits to make space for carry/oe switches

* Update chapters/microprogramable_cpu/arithmetic-logic-unit/drills/README.md

Co-authored-by: Teodor-Alexandru Dicu <[email protected]>

* Centered images

* Ups

---------

Co-authored-by: Teodor-Alexandru Dicu <[email protected]>
  • Loading branch information
VictorCaproiu and DTeodor-Alexaandru authored Nov 7, 2024
1 parent f891d6d commit ea6734e
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Practică: Implementare modul UAL

Conținutul laboratorului este present la următorul [link](https://github.com/cs-pub-ro/computer-architecture/tree/main/chapters/microprogramable_cpu/arithmetic-logic-unit/drills/alu/support).
Conținutul laboratorului este prezent la următorul [link](https://github.com/cs-pub-ro/computer-architecture/tree/main/chapters/microprogramable_cpu/arithmetic-logic-unit/drills/alu/support).

Vom completa conținutul **modulului alu**, folosind intrările și ieșirile prezentate mai jos.

Expand All @@ -19,7 +19,7 @@ module alu #(
);
```

Codurile de identificare ale operațiilor (cei 4 biți S) sunt definite în modulul ```alu.v``` din scheletul de laborator și in codul de mai jos.
Codurile de identificare ale operațiilor (cei 4 biți S) sunt definite în modulul ```alu.v``` din scheletul de laborator și în codul de mai jos.

```verilog
localparam ADC = 4'd0;
Expand All @@ -34,7 +34,50 @@ localparam SHR = 4'd8;
localparam SAR = 4'd9;
```

TODO: exaplain the remaining code
## Operațiile

Partea combinațională a modulului descrie comportamentul fiecărei operații în funcție de codul operațional ``` i_w_opcode ``` prin intermediul unei structuri `case`.

### Adunarea cu carry (ADC)

Se execută adunarea celor 2 operanzi și carry, iar în cazul în care rezultatul depășește ca mărime parametrul `p_data_width`, bitul în plus activează flag-ul _carry_.

Flag-ul de _overflow_ este activat cu 2 condiții:

1. **MSB**-ul operanzilor este egal. Acest bit indică dacă operandul este un număr pozitiv sau negativ, iar suma dintre două numere de semn opus nu poate depăși intervalul lor.
2. **MSB**-ul rezultatului diferă de cel al operanzilor, indicând că a avut loc overflow-ul

```verilog
ADC: begin
{l_r_carry, l_r_result} = i_w_op1 + i_w_op2 + i_w_carry;
l_r_overflow = (i_w_op1[p_data_width-1] == i_w_op2[p_data_width-1]) &&
(i_w_op1[p_data_width-1] != l_r_result[p_data_width-1]);
end
```

### Scăderile (SBB1/SBB2)

Condițiile pentru activarea semnalelor de _carry_ și _overflow_ sunt asemănătoare cu cele din cazul adunării, cu excepția primei condiții de _overflow_, care e inversată.

```verilog
i_w_op2[p_data_width-1] != i_w_op1[p_data_width-1]
```

### Operațiile logice (AND/OR/XOR/NOT) și de shift (SHL/SHR/SAR)

Se observă că operațiile logice nu activează semnalele _carry_ și _overflow_, iar în cazul operațiilor cu un singur operand (NOT/SHL/SHR/SAR), datorită operatorului `|`, acesta se poate afla pe oricare din intrări `i_w_op1` sau `i_w_op2` cu condiția ca cealaltă să aibă valoarea **0**.

De asemenea operația `SAL` lipsește întrucât e identică cu `SHL`.

### Zero (Z), Sign (S), Parity (P)

Aceste semnale au aceleași condiții de activare indiferent de operația efectuată. De asemenea paritatea este verificată prin operatorul de reducere _XNOR_.

```verilog
l_r_zero = l_r_result == 0;
l_r_sign = l_r_result[p_data_width-1];
l_r_parity = ~^l_r_result;
```

## Extra operations

Expand All @@ -44,4 +87,4 @@ TODO: exaplain the remaining code

### DIV

### MOD
### MOD
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module alu #(
parameter p_data_width = 6, // 6 for FPGA testing, 16 for Simulation and inside the CPU
parameter p_data_width = 5, // 5 for FPGA testing, 16 for Simulation and inside the CPU
parameter p_flags_width = 5
)(
output wire [(p_data_width-1):0] o_w_out,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { i_w_op
set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { i_w_op1[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { i_w_op1[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3]
set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 } [get_ports { i_w_op1[4] }]; #IO_L12N_T1_MRCC_14 Sch=sw[4]
set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { i_w_op1[5] }]; #IO_L7N_T1_D10_14 Sch=sw[5]
set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { i_w_op2[0] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6]
set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { i_w_op2[1] }]; #IO_L5N_T0_D07_14 Sch=sw[7]
set_property -dict { PACKAGE_PIN T8 IOSTANDARD LVCMOS18 } [get_ports { i_w_op2[2] }]; #IO_L24N_T3_34 Sch=sw[8]
set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS18 } [get_ports { i_w_op2[3] }]; #IO_25_34 Sch=sw[9]
set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { i_w_op2[4] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=sw[10]
set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { i_w_op2[5] }]; #IO_L23P_T3_A03_D19_14 Sch=sw[11]
set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { i_w_op2[0] }]; #IO_L7N_T1_D10_14 Sch=sw[5]
set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { i_w_op2[1] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6]
set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 } [get_ports { i_w_op2[2] }]; #IO_L5N_T0_D07_14 Sch=sw[7]
set_property -dict { PACKAGE_PIN T8 IOSTANDARD LVCMOS18 } [get_ports { i_w_op2[3] }]; #IO_L24N_T3_34 Sch=sw[8]
set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS18 } [get_ports { i_w_op2[4] }]; #IO_25_34 Sch=sw[9]
set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 } [get_ports { i_w_oe }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=sw[10]
set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { i_w_carry }]; #IO_L23P_T3_A03_D19_14 Sch=sw[11]
set_property -dict { PACKAGE_PIN H6 IOSTANDARD LVCMOS33 } [get_ports { i_w_opcode[0] }]; #IO_L24P_T3_35 Sch=sw[12]
set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 } [get_ports { i_w_opcode[1] }]; #IO_L20P_T3_A08_D24_14 Sch=sw[13]
set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 } [get_ports { i_w_opcode[2] }]; #IO_L19N_T3_A09_D25_VREF_14 Sch=sw[14]
Expand All @@ -33,16 +33,16 @@ set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { o_w_ou
set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { o_w_out[3] }]; #IO_L8P_T1_D11_14 Sch=led[3]
set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { o_w_out[4] }]; #IO_L7P_T1_D09_14 Sch=led[4]
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { o_w_out[5] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5]
set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[0] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6]
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[1] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7]
set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[2] }]; #IO_L16N_T2_A15_D31_14 Sch=led[8]
set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[3] }]; #IO_L14N_T2_SRCC_14 Sch=led[9]
set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[4] }]; #IO_L22P_T3_A05_D21_14 Sch=led[10]
#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { LED[11] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=led[11]
#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { LED[12] }]; #IO_L16P_T2_CSI_B_14 Sch=led[12]
#set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { LED[13] }]; #IO_L22N_T3_A04_D20_14 Sch=led[13]
#set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { LED[14] }]; #IO_L20N_T3_A07_D23_14 Sch=led[14]
#set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { LED[15] }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=led[15]
#set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[0] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6]
#set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[1] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7]
#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[2] }]; #IO_L16N_T2_A15_D31_14 Sch=led[8]
#set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[3] }]; #IO_L14N_T2_SRCC_14 Sch=led[9]
#set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[4] }]; #IO_L22P_T3_A05_D21_14 Sch=led[10]
set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[0] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 Sch=led[11]
set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[1] }]; #IO_L16P_T2_CSI_B_14 Sch=led[12]
set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[2] }]; #IO_L22N_T3_A04_D20_14 Sch=led[13]
set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[3] }]; #IO_L20N_T3_A07_D23_14 Sch=led[14]
set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 } [get_ports { o_w_flags[4] }]; #IO_L21N_T3_DQS_A06_D22_14 Sch=led[15]

## RGB LEDs
#set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { LED16_B }]; #IO_L5P_T0_D06_14 Sch=led16_b
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@

Unitatea aritmetică-logică este responsabilă de efectuarea operațiilor aritmetice și logice în timpul execuției instrucțiunilor. Operațiile primesc unul sau doi operanzi, iar UAL-ul în afară de producerea rezultatului setează și o serie de indicatori de condiții (eng. *flags*) rezultați în urma operațiilor. Operațiile disponibile în UAL derivă din instrucțiunile prezente în setul de instrucțiuni al procesorului didactic, însă nu au neapărat o corespondență 1-la-1 cu acestea. Unele operații sunt folosite în mai multe instrucțiuni, iar unele instrucțiuni folosesc mai multe operații. UAL-ul trebuie însă proiectat în așa fel astfel încât să cuprindă toate operațiile necesare în execuția instrucțiunilor disponibile în procesorul didactic.

<div align="center">

![Unitatea aritmetică-logică](../media/fig_ual.png)



_Figure: Unitatea aritmetică-logică_

</div>

Operanzii pe 16 biți sunt *op1* și *op2*, iar cei 4 biți *S* selectează operația ce va fi efectuată. Rezultatul este pus pe magistrală prin activarea semnalului *Enable*. Acesta este dezactivat de instrucțiunile care nu au nevoie de fapt de rezultatul operației, ci doar de indicatori (ex: *cmp*, *test*). Operațiile de adunare și scădere folosesc și un bit de carry/borrow reprezentat prin semnalul *Carry*. Acesta este activat selectiv de instrucțiunile ADD/ADC (*add with carry*) și SUB/SBB (*subtract with borrow*), precum și alte instrucțiuni, pentru a obține rezultatul dictat de semantica instrucțiunii.

## Descrierea generală a registrului care conține indicatorii de condiții (IND)
Expand Down Expand Up @@ -89,6 +95,8 @@ O shiftare logică nu ține cont de semnul operandului. În cazul shiftării log

În imaginile de mai jos se poate observa modul de execuție a shiftărilor logice.

<div align="center">

![Shiftare logică la stânga](../media/shl.png?200)

_Figure: Shiftare logică la stânga_
Expand All @@ -97,8 +105,12 @@ _Figure: Shiftare logică la stânga_

_Figure: Shiftare logică la dreapta_

</div>

Iar în figurile de mai jos găsiți un exemplu practic de efectuare a shiftărilor logice spre stânga (*SHL*) și spre dreapta (*SHR*).

<div align="center">

![Exemplu de shiftare logică la stânga](../media/shl_sal_example.png?200)

_Figure: Exemplu de shiftare logică la stânga_
Expand All @@ -107,12 +119,16 @@ _Figure: Exemplu de shiftare logică la stânga_

_Figure: Exemplu de shiftare logică la dreapta_

</div>

În Verilog, operatorii de shiftare logică sunt `<<` și `>>`.

### Shiftare aritmetică

Spre deosebire de shiftarea logică spre dreapta (*SHR*), shiftarea aritmetică spre dreapta (*SAR*) nu umple spațiile rămase libere cu zerouri. În cazul *SAR*, spațiile rămase libere se umplu cu valoarea bitului cel mai semnificativ, care se replică de câte ori este nevoie (vezi imaginea de mai jos).

<div align="center">

![Exemplu de shiftare aritmetică la dreapta](../media/sar.png?200)

_Figure: Exemplu de shiftare aritmetică la dreapta_
Expand All @@ -121,9 +137,11 @@ _Figure: Exemplu de shiftare aritmetică la dreapta_

_Figure: Exemplu de shiftare aritmetică la dreapta_

</div>

În Verilog, operatorii de shiftare aritmetică sunt `<<<` și `>>>`.

:!: Aceștia au efectul scontat doar dacă variabila a fost declarată `signed` (ex: `reg signed [15:0] a;`).
Aceștia au efectul scontat doar dacă variabila a fost declarată `signed` (ex: `reg signed [15:0] a;`).

> **Important**: Shiftarea logică spre stânga (*SHL*) și shiftarea aritmetică spre stânga (*SAL*) se efectuează în același mod. Se păstrează, însă, ambele mnemonici (*SHL* / *SAL*) pentru a se putea păstra contextul folosirii acestora, logic sau aritmetic.
Expand Down

0 comments on commit ea6734e

Please sign in to comment.