Altifigence Academy

51 / 63 · Conceito

ALU e flags zero, negative, carry e overflow

Implemente ADD/SUB com um somador compartilhado e derive comparações distinguindo carry de overflow signed.

Pré-requisitos: complemento de doisComplemento de dois Representação de inteiros com sinal por sequências de bits de largura fixa. O intervalo de n bits vai de −2^(n−1) a 2^(n−1)−1. Saiba mais, somadores, MUXMultiplexador Circuito combinacional que conecta uma dentre várias entradas à saída conforme um sinal de seleção. É preciso especificar a correspondência entre os bits de seleção e os números das entradas. Saiba mais combinacionais e extensão de largura.

Uma ALU produz resultado e estado

A ALU seleciona resultados de operações e emite flags para interpretá-los. Neste projeto, A,B,RA,B,R têm WW bits e são suportados ADD, SUB, AND, OR e XOR. Os resultados aritméticos mantêm apenas os WW bits baixos. Os mesmos bits podem ser interpretados como unsignedunsigned Interpretação de uma sequência de bits como inteiro não negativo. Com n bits, o intervalo é de 0 a 2^n−1; pode diferir da interpretação signed dos mesmos bits. Saiba mais ou signed em complemento de dois; por isso, carry e overflow são separados. Não são necessários somadores distintos para as interpretações unsigned e signed.

Definem-se Z=(R=0)Z=(R=0) e N=RW−1N=R_{W-1}. Z é uma redução NOR de todo o resultado selecionado; N é o bit superior. N=1 indica que a interpretação signed armazenada é negativa; havendo overflow, pode não coincidir com o sinal da soma exata.

Separe carry e overflow

Na soma, C é o bit superior da soma estendida 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 se ambos os operandos têm o mesmo sinal e o resultado tem outro. Se a,b,ra,b,r são os bits superiores:

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

Em oito bits, 255+1255+1 dá R=0, C=1, V=0: signed é −1+1=0-1+1=0, dentro do intervalo. Já 127+1127+1 dá R=0x80, C=0, V=1: unsigned 128 cabe, mas excede o máximo signed 127. Unir C e V impediria distinguir os casos.

Para subtrair, invertaNegação Operação NOT que troca 0 por 1 e 1 por 0. Uma barra sobre uma expressão aplica NOT a toda a expressão coberta. Saiba mais apenas os W bits de B e depois estenda com 0: T={0,A}+{0,¬B}+1T=\{0,A\}+\{0,\neg B\}+1. Inverter os W+1 bits alteraria o significado do carry superior. Aqui C=1 significa sem borrow; portanto, A<BA<B unsigned equivale a ¬C\neg C.

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

Somente subtrair sinais diferentes pode produzir overflow signed. Uma comparação pode usar as flags de SUB sem armazenar R. A<BA<B signed é N⊕VN\oplus V e A≤BA\le B é Z∨(N⊕V)Z\lor(N\oplus V). Por exemplo, −128−1-128-1 armazena +127, mas V=1 corrige o erro de olhar apenas N.

O ADD abaixo cabe em unsigned, mas não em signed. Observe que C=0 e V=1 podem coexistir.

Distinga C e V em 127 + 1
  1. A=7F · B=01: signed 127 + 1
  2. Soma T de nove bits: 0_10000000
  3. Resultado R de oito bits: 80 → signed −128
  4. Flags de estado: Z=0 · N=1 · C=0 · V=1

Somador compartilhado e regras explícitas de saída

O RTL pressupõe W≥2. Os códigos 0–4 são ADD, SUB, AND, OR e XOR. Para operações lógicas, C=V=0. Um código não usado produz R=0, Z=1 e as demais flags em 0. É o contrato desta ALU, não uma imitação de uma ISA específica.

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

A inversão condicional de B e o carry inicial expressam ADD/SUB com a mesma estrutura. Calcular primeiro y em cada ramo e depois Z,N fornece flags coerentes também para a lógica. Atribuições padrão cobrem todas as saídas e evitam latchesLatch Elemento de armazenamento que acompanha a entrada enquanto o controle está ativo e mantém o valor quando está inativo. É diferente do flip-flop, que captura apenas em uma borda. Saiba mais. Sem registradoresRegistrador Circuito que armazena vários bits de estado. Os registradores síncronos deste curso capturam a entrada especificada na borda de clock. Saiba mais, não há latência em ciclos, mas há atraso físico. O MUX de operação e o detector de zero também devem chegar antes do setup do próximo registrador.

Para verificar, combine 0, máximo unsigned, extremos signed e valores dos dois lados de cada limite. Compare R com referência módulo 2W2^W, C com a soma unsigned estendida e V com excesso do intervalo signed, independentemente. R correto não garante flags corretas.

Um exemplo real dessa separação entre sinal, zero, carry unsigned e overflow signed está na explicação de flags de condição da Arm.

Experimente

Numa ALU de 8 bits, calcule R,Z,N,C,V para (1) 0x7F+0x01, (2) 0xFF+0x01, (3) 0x00−0x01 e (4) 0x80−0x01. Explique por que comparar os operandos signed do caso 4 usando apenas N falha.

Ler a explicação

Na ordem (R,Z,N,C,V): (1) (0x80,0,1,0,1), (2) (0x00,1,0,1,0), (3) (0xFF,0,1,0,0), (4) (0x7F,0,0,1,1). Em (3), há borrow unsigned, C=0, e −1 signed é representável. Em (4), unsigned 128−1=127 não exige borrow, C=1; signed −128−1=−129 excede o intervalo e V=1. O N=0 armazenado não reflete o sinal da diferença exata. N xor V=1 dá corretamente A<B signed.

Sua escolha vale neste navegador. Altere-a a qualquer momento no rodapé.