Altifigence Academy

41 / 52 · Concepto

ALU and Zero, Negative, Carry, and Overflow Flags

Build a shared ADD/SUB datapath and derive status flags and signed versus unsigned comparison conditions.

La traducción aún no está disponible. Se muestra la lección original. (한국어)

선수 지식: 2의 보수, 가산기, 조합논리 MUX, 비트폭 확장을 이해해야 합니다.

결과와 상태를 함께 만드는 ALU

ALU는 연산별 회로의 결과를 선택하고, 그 결과를 해석하는 데 필요한 상태 비트를 출력합니다. 이번 설계의 입력 A,BA,B와 결과 RRWW비트이며 ADD, SUB, AND, OR, XOR를 지원합니다. 산술 결과는 항상 하위 WW비트로 잘립니다. 같은 비트열을 unsigned 또는 2의 보수 signed로 읽을 수 있으므로, carry와 overflow를 별도로 내보냅니다. 부호 해석에 따라 가산기를 두 개 만들 필요는 없습니다.

플래그는 Z=(R=0)Z=(R=0), N=RW1N=R_{W-1}입니다. Z는 선택된 결과 전체의 reduction NOR이고 N은 최상위 비트입니다. N이 1이라는 것은 저장된 비트열의 signed 해석이 음수라는 뜻입니다. overflow가 발생했다면, 무한 정밀도로 계산한 실제 합의 부호와는 다를 수 있습니다.

carry와 overflow를 분리하기

덧셈에서는 확장된 합 TT의 최상위 비트가 C입니다.

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

V는 입력 두 개의 부호가 같고 결과 부호가 달라졌을 때 1입니다. a,b,ra,b,r을 각각 최상위 비트라고 하면 다음과 같습니다.

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

8비트에서 255+1255+1은 R=0, C=1, V=0입니다. signed로는 1+1=0-1+1=0이어서 표현 범위를 넘지 않습니다. 반대로 127+1127+1은 R=0x80, C=0, V=1입니다. unsigned 합 128은 들어가지만 signed 최댓값 127을 넘습니다. C와 V를 하나로 묶으면 이 두 경우를 구분할 수 없습니다.

뺄셈은 W비트 B만 반전하고, 그 뒤 0을 붙여 확장합니다. 즉 T={0,A}+{0,¬B}+1T=\{0,A\}+\{0,\neg B\}+1입니다. W+1비트 전체를 반전하면 상위 carry의 뜻이 달라집니다. 이 강의는 C=1을 borrow 없음으로 정의합니다. 따라서 unsigned 비교에서 A<BA<B¬C\neg C입니다.

Vsub=(ab)(ar)V_{\mathrm{sub}}=(a\oplus b)\land(a\oplus r)

서로 다른 부호를 뺄 때만 signed overflow가 가능합니다. 비교 명령은 SUB의 R을 저장하지 않고 플래그만 쓰면 됩니다. signed A<BA<BNVN\oplus V, signed ABA\le BZ(NV)Z\lor(N\oplus V)입니다. 예를 들어 1281-128-1의 저장 결과는 +127이지만 V=1이므로 N만 볼 때의 오류를 보정합니다.

8비트 ADD의 한 예입니다. unsigned 결과는 표현 가능하지만 signed 결과는 범위를 넘습니다. 같은 합에서 C=0과 V=1이 동시에 가능하다는 점을 확인하세요.

127 + 1에서 C와 V를 구분하기
  1. A=7F · B=01: signed 127 + 1
  2. 9비트 합 T: 0_10000000
  3. 8비트 결과 R: 80 → signed −128
  4. 상태 플래그: Z=0 · N=1 · C=0 · V=1

공유 가산기와 명시적인 출력 규칙

아래 RTL은 W≥2를 전제로 합니다. opcode 0~4는 ADD, SUB, AND, OR, XOR입니다. 논리 연산은 C,V를 0으로 정합니다. 사용하지 않는 opcode는 R=0이므로 Z=1이며 다른 플래그는 0입니다. 이 규칙은 특정 CPU 명령어 집합을 흉내 낸 것이 아니라 이 ALU의 인터페이스 계약입니다.

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

조건부 B 반전과 초기 carry가 ADD/SUB를 하나의 가산 구조로 표현합니다. 각 분기에서 y를 먼저 정한 뒤 Z,N을 계산하므로 논리 연산에도 일관된 상태가 붙습니다. 기본 대입은 모든 출력 경로를 정의하며 래치를 막습니다. 여기에는 레지스터가 없어 클록 단위의 계산 지연은 없지만, 실제 신호 전파 지연은 있습니다. 연산 선택 MUX와 zero 검출 회로까지 다음 레지스터의 setup 시간 안에 도착해야 합니다.

검증에서는 0, 최대 unsigned, 최대·최소 signed와 경계 양옆을 짝지으십시오. R은 modulo 2W2^W의 기준값, C는 unsigned 확장 합, V는 signed 범위 초과로 각각 비교해야 합니다. R이 맞아도 플래그 정의가 틀릴 수 있습니다. 새 RTL은 설명용으로 작성했으며 여기서 시뮬레이터 실행 결과를 제시하지는 않습니다.

플래그를 결과의 부호·영·unsigned carry·signed overflow로 구분하는 실제 사례는 Arm의 조건 플래그 설명에서 확인할 수 있습니다.

Inténtalo tú

8비트 ALU에서 (1) 0x7F+0x01, (2) 0xFF+0x01, (3) 0x00−0x01, (4) 0x80−0x01의 R,Z,N,C,V를 구하세요. (4)의 입력을 signed로 비교할 때 N만 쓰면 왜 틀리는지도 설명하세요.

Leer la explicación

순서를 (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)입니다. (3)은 unsigned borrow가 발생해 C=0이고 signed −1은 표현 가능합니다. (4)는 unsigned 128−1=127이므로 borrow가 없어 C=1입니다. signed로는 −128−1=−129가 범위를 벗어나 V=1이고, 저장된 R의 N=0은 실제 차의 부호를 반영하지 못합니다. signed A<B는 N xor V=1이므로 올바르게 참을 얻습니다.

Tu elección se aplica a este navegador. Puedes cambiarla en el pie de página.