Altifigence Academy

51 / 63 · Теория

АЛУ и флаги zero, negative, carry, overflow

Постройте ADD/SUB на общем сумматоре, разделите carry и знаковое переполнение и выведите условия сравнения.

Предварительные знания: дополнительный кодДополнительный код представляет знаковые целые битовой последовательностью фиксированной ширины. Для n бит диапазон составляет от −2^(n−1) до 2^(n−1)−1. Подробнее, сумматоры, комбинационный MUXМультиплексор — комбинационная схема, соединяющая один из нескольких входов с выходом по сигналу выбора. Соответствие битов выбора и номеров входов должно быть задано явно. Подробнее и расширение разрядности.

АЛУ формирует результат и флаги состояния

АЛУ выбирает результат одной из схем операций и выдаёт биты состояния для его интерпретации. Входы A,BA,B и результат RR имеют ширину WW; поддерживаются ADD, SUB, AND, OR, XOR. Арифметический результат всегда усекается до младших WW битов. Одни биты можно прочитать как unsignedБеззнаковая интерпретация (unsigned) рассматривает битовую последовательность как неотрицательное целое. Диапазон n бит — от 0 до 2^n−1; знаковая интерпретация тех же битов может дать другое число. Подробнее или signed в дополнительном коде, поэтому carry и overflow выдаются отдельно. Два сумматора для разных знаковых интерпретаций не нужны.

Флаги: Z=(R=0)Z=(R=0), N=RW−1N=R_{W-1}. Z — свёртка NOR всего выбранного результата, N — старший бит. N=1 означает отрицательную signed-интерпретацию сохранённых битов. При переполнении этот знак может отличаться от знака точной суммы неограниченной разрядности.

Разделение carry и overflow

При сложении C — старший бит расширенной суммы 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 равен 1, когда знаки входов одинаковы, а знак результата другой. Для старших битов a,b,ra,b,r:

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

В 8 битах 255+1255+1 даёт R=0, C=1, V=0. В знаковой интерпретации это −1+1=0-1+1=0, без выхода за диапазон. Напротив, 127+1127+1 даёт R=0x80, C=0, V=1: unsigned 128 помещается, но превышен signed-максимум 127. Объединение C и V потеряет это различие.

Для вычитания инвертируетсяИнверсия — операция NOT, меняющая 0 на 1 и 1 на 0. Черта над формулой означает применение NOT ко всему выражению под ней. Подробнее только W-битный B, затем он расширяется нулём: T={0,A}+{0,¬B}+1T=\{0,A\}+\{0,\neg B\}+1. Инверсия всех W+1 битов изменила бы смысл старшего carry. Здесь C=1 определён как отсутствие займа. Поэтому unsigned A<BA<B означает ¬C\neg C.

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

Знаковое переполнение при вычитании возможно только для разных знаков. Команда сравнения может использовать флаги SUB, не сохраняя R. Signed A<BA<B равно N⊕VN\oplus V, signed A≤BA\le B — Z∨(N⊕V)Z\lor(N\oplus V). Например, −128−1-128-1 сохраняется как +127, но V=1 исправляет ошибку проверки одного N.

Пример 8-битного ADD: unsigned-результат представим, signed-результат выходит за диапазон. Убедитесь, что для одной суммы одновременно возможны C=0 и V=1.

Различайте C и V на примере 127 + 1
  1. A=7F · B=01: со знаком: 127 + 1
  2. 9-битная сумма T: 0_10000000
  3. 8-битный результат R: 80 → со знаком −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. Это контракт данного АЛУ, а не имитация набора команд конкретного процессора.

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 и начальный перенос выражают ADD/SUB одной суммирующей структурой. Сначала каждая ветвь задаёт y, затем вычисляются Z,N, что даёт согласованные флаги и логическим операциям. Присваивания по умолчанию определяют все пути и предотвращают защёлкиЗащёлка — элемент хранения, который следует за входом, пока управляющий сигнал активен, и удерживает значение, когда он неактивен. Этим она отличается от триггера, записывающего данные только на фронте. Подробнее. РегистровРегистр хранит многобитное состояние. Синхронные регистры в этом курсе записывают определённый вход на фронте тактового сигнала. Подробнее здесь нет, поэтому нет задержки в тактовых циклах, но физическая задержка распространения существует. Результат должен пройти и MUX операции, и детектор нуля до срока setup следующего регистра.

Для проверки сочетайте 0, максимум unsigned, максимум и минимум signed, а также соседние граничные значения. R сравнивайте с эталоном по модулю 2W2^W, C — с расширенной unsigned-суммой, V — с выходом за signed-диапазон. Даже при правильном R определения флагов могут быть ошибочны.

Практический пример разделения знака, нуля, unsigned carry и signed overflow приведён в описании условных флагов Arm.

Попробуйте сами

Для 8-битного АЛУ найдите R,Z,N,C,V: (1) 0x7F+0x01, (2) 0xFF+0x01, (3) 0x00−0x01, (4) 0x80−0x01. Почему при знаковом сравнении входов (4) одного 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-заём, поэтому C=0; signed −1 представимо. В (4) unsigned 128−1=127 не требует займа, C=1. Но signed −128−1=−129 вне диапазона, V=1, и N=0 сохранённого R не отражает знак точной разности. Условие signed A<B даёт N xor V=1, то есть верный результат сравнения.

Выбор действует в этом браузере. Его можно изменить внизу страницы.