Altifigence Academy

51 / 63 · Concetto

ALU e flag zero, negative, carry e overflow

Realizzare ADD/SUB con un sommatore condiviso e derivare confronti separando carry e overflow.

Prerequisiti: complemento a dueComplemento a due Rappresentazione di interi con segno a larghezza fissa. Con n bit il campo è da −2^(n−1) a 2^(n−1)−1. Approfondisci, sommatori, MUXMultiplexer Circuito combinatorio che collega un ingresso all’uscita secondo la selezione. Va specificata la corrispondenza fra bit di selezione e ingressi. Approfondisci combinatori ed estensione della larghezza.

Un’ALU produce risultato e stato

L’ALU seleziona i risultati delle operazioni e produce bit di stato per interpretarli. Ingressi A,BA,B e risultato RR hanno WW bit; sono supportati ADD, SUB, AND, OR, XOR. L'aritmetica conserva sempre i WW bit bassi. Poiché gli stessi bit si leggono unsignedUnsigned Interpretazione dei bit come intero non negativo. Il campo a n bit è 0–2^n−1 e può differire dalla lettura signed degli stessi bit. Approfondisci o signed in complemento a due, carry e overflow sono separati. Non occorrono due sommatori per le due interpretazioni.

I flag sono Z=(R=0)Z=(R=0) e N=RW−1N=R_{W-1}. Z è il NOR di riduzione dell'intero risultato scelto; N è il bit più significativo. N=1 indica che il valore memorizzato interpretato signed è negativo. Con overflow, può differire dal segno del risultato matematico a precisione infinita.

Separare carry e overflow

Nell'addizione, C è il bit superiore della somma estesa TT.

T={0,A}+{0,B},R=T[W−1:0],C=T[W]T=\{0,A\}+\{0,B\},\qquad R=T[W-1:0],\quad C=T[W]

V vale 1 quando gli ingressi hanno lo stesso segno e il risultato uno diverso. Per i bit più alti a,b,ra,b,r:

Vadd=¬(a⊕b)∧(a⊕r)V_{\mathrm{add}}=\neg(a\oplus b)\land(a\oplus r)

A otto bit, 255+1255+1 dà R=0, C=1, V=0: signed è −1+1=0-1+1=0, rappresentabile. Invece 127+1127+1 dà R=0x80, C=0, V=1: 128 è rappresentabile come unsigned ma supera il massimo signed 127. Un unico flag C/V non distingue i casi.

Per sottrarre si invertonoInversione NOT scambia 0 e 1. Una barra superiore applica NOT all’intera espressione sottostante. Approfondisci solo i W bit di B, poi si estende con 0: T={0,A}+{0,¬B}+1T=\{0,A\}+\{0,\neg B\}+1. Invertire tutti i W+1 bit cambia il significato del carry. Qui C=1 significa nessun prestito; quindi unsigned A<BA<B equivale a ¬C\neg C.

Vsub=(a⊕b)∧(a⊕r)V_{\mathrm{sub}}=(a\oplus b)\land(a\oplus r)

Nella sottrazione l'overflow signed è possibile solo con segni diversi. Un confronto può usare i flag SUB senza memorizzare R. Signed A<BA<B è N⊕VN\oplus V e A≤BA\le B è Z∨(N⊕V)Z\lor(N\oplus V). Per esempio −128−1-128-1 memorizza +127, ma V=1 corregge l'errore che deriverebbe dal solo N.

L'esempio ADD a otto bit seguente è rappresentabile unsigned ma non signed. Nella stessa somma possono quindi coesistere C=0 e V=1.

Distinguere C e V in 127 + 1
  1. A=7F · B=01: signed 127 + 1
  2. Somma T a 9 bit: 0_10000000
  3. Risultato R a 8 bit: 80 → signed −128
  4. Flag di stato: Z=0 · N=1 · C=0 · V=1

Sommatore condiviso e regole d'uscita esplicite

L'RTL assume W≥2. Gli opcode 0–4 sono ADD, SUB, AND, OR, XOR. Le operazioni logiche pongono C, V a 0. Gli opcode inutilizzati danno R=0, Z=1 e gli altri flag a 0. È il contratto di questa ALU, non l'imitazione di una particolare ISA.

SystemVerilog
module alu #(parameter int W = 8) (
  input  logic [W-1:0] a, b,
  input  logic [2:0] op,
  output logic [W-1:0] y,
  output logic z, n, c, v
);
  logic sub;
  logic [W-1:0] bx;
  logic [W:0] sum;
  always_comb begin
    sub = (op == 3'd1);
    bx = b ^ {W{sub}};
    sum = {1'b0, a} + {1'b0, bx}
        + {{W{1'b0}}, sub};
    y = '0;
    c = 1'b0;
    v = 1'b0;
    case (op)
      3'd0, 3'd1: begin
        y = sum[W-1:0];
        c = sum[W];
        if (sub)
          v = (a[W-1] ^ b[W-1]) & (a[W-1] ^ y[W-1]);
        else
          v = ~(a[W-1] ^ b[W-1]) & (a[W-1] ^ y[W-1]);
      end
      3'd2: y = a & b;
      3'd3: y = a | b;
      3'd4: y = a ^ b;
      default: y = '0;
    endcase
    z = ~(|y);
    n = y[W-1];
  end
endmodule

Inversione condizionata di B e carry iniziale condividono la struttura ADD/SUB. y viene definito prima di Z, N, rendendo coerenti i flag anche nelle operazioni logiche. I default coprono tutti i percorsi e impediscono latchLatch Elemento che segue l’ingresso quando il controllo è attivo e mantiene il valore quando inattivo. Differisce dal flip-flop che acquisisce solo ai fronti. Approfondisci. Non essendoci registriRegistro Memorizza uno stato di più bit. I registri sincroni del corso acquisiscono gli ingressi specificati al fronte di clock. Approfondisci, non c'è latenza in cicli, ma esiste ritardo fisico. Anche il MUX che seleziona l’operazione e la rilevazione dello zero devono rispettare il setup del registro seguente.

Provate coppie di 0, massimo unsigned, minimo/massimo signed e valori adiacenti ai confini. Confrontate separatamente R con modulo 2W2^W, C con somma unsigned estesa e V con superamento del campo signed. R corretto non garantisce flag corretti.

Un esempio reale di separazione fra segno, zero, carry unsigned e overflow signed è nella spiegazione Arm dei flag condizionali.

Prova tu

Calcolate (R, Z, N, C, V) a otto bit per (1) 0x7F+0x01, (2) 0xFF+0x01, (3) 0x00−0x01, (4) 0x80−0x01. Perché nel confronto signed di (4) il solo N è errato?

Leggi la spiegazione

(1) (0x80,0,1,0,1), (2) (0x00,1,0,1,0), (3) (0xFF,0,1,0,0), (4) (0x7F,0,0,1,1). In (3) c’è prestito unsigned, C=0, mentre −1 signed è rappresentabile. In (4), unsigned 128−1=127 non richiede prestito: C=1. Signed −128−1=−129 è fuori campo: V=1 e N=0 memorizzato non riflette il segno reale. N xor V=1 dà correttamente A<B signed.

La scelta vale per questo browser. Puoi modificarla in qualsiasi momento dal piè di pagina.