Adición firmada de dos vectores lógicos estándar al buscar desbordamiento y acarreo

Tengo lo que creo que es una implementación funcional para encontrar la suma de dos vectores firmados de 32 bits (std_logic_vector) en los que elegí expandir el resultado para tener siempre 33 bits para preservar el bit de signo y poder verificar el acarreo fuera con el bit expandido.

Mi método parece increíblemente sucio y me preguntaba si había una forma más limpia de lograr mi objetivo, para futuras referencias.

sum <= std_logic_vector(resize(signed(std_logic_vector(signed(a_alu32) + signed(b_alu32))), 33));
c_alu32 <= sum(31);
--overflow--
if ((a_alu32(31)='0' and b_alu32(31)='0' and sum(31)='1') or (a_alu32(31)='1' and b_alu32(31)='1' and sum(31)='0')) then 
  ov_alu32<='1'; --logic to check for overflow
else
  ov_alu32<='0';
end if;

--removing the extra bit through concatenation to achieve my 32 bit sum
o_alu32 <= sum(32) & sum(30 downto 0);

Respuestas (2)

Su implementación no es correcta:

  • Debe realizar la extensión del signo antes de la suma de a y b.
  • Una adición firmada no tiene indicador de acarreo, solo desbordamiento (se puede calcular pero no es válido); la adición sin signo produce una bandera de acarreo pero no tiene un desbordamiento válido.
  • El bit de signo es, por definición, siempre almacenado en el bit más alto

Esta podría ser una reescritura más o menos agradable, que es más genérica. Solo depende de la longitud de a, b y c. Entonces podrías reutilizar este código para 16 o 64 bits, o lo que sea.

-- create locale signals with suffix '_s' for signed
-- both signals have one more bit than the original
signal a_alu32_s   : SIGNED(a_alu32'length downto 0);
signal b_alu32_s   : SIGNED(b_alu32'length downto 0);
signal sum_alu32_s : SIGNED(a_alu32'length downto 0);
signal temp        : std_logic_vector(2 downto 0);

-- convert type and perform a sign-extension
a_alu32_s <= resize(signed(a_alu32), a_alu32_s'length);
b_alu32_s <= resize(signed(b_alu32), b_alu32_s'length);

-- addition of two 33 bit values
sum_alu32_s <= a_alu32_s + b_alu32_s;

-- resize to require size and type conversion
o_alu32 <= std_logic_vector(resize(sum_alu32_s, o_alu32'length));

-- flag calculations
--c_alu32  <= sum_32_s(sum_alu32_s'high);

-- concat the three relevant sign-bits from a,b and sum to one vector
temp     <= a_alu32_s(a_alu32_s'high) & b_alu32_s(b_alu32_s'high) & sum_alu32_s(sum_alu32_s'high);
ov_alu32 <= (temp = "001") or (temp = "110");
La bombilla se encendió para todo hasta el método que usaste para encontrar el desbordamiento. Tengo curiosidad por saber cómo simplificó mi proceso en el suyo, ya que parece una habilidad valiosa (¿involucra KMAPS)? Gracias por la ayuda.
Mire la asignación a "temp". Entonces la prueba se vuelve clara: dos números positivos suman un negativo (o viceversa)...
¿Qué es KMAPS? Google no lo sabe. -- el cálculo para ov es el mismo que el suyo, pero no usé una declaración if-then-else. Convertí tu a_alu32(31)='0' and b_alu32(31)='0' ...a not a_alu32(31) and not b_alu32(31) .... Entonces pensé que es una línea muy larga y que el bit de acceso a a_alu32 y Co se necesita dos veces. Así que recopilé todos los bits necesarios en temp. Ahora es posible hacer una prueba de caso simple para 001 y 110. Esto significa 'pos+pos=neg -> error' o 'neg+neg=pos -> error'. La detección de desbordamiento original sería calculada por ov := C norte xor C norte 1 .
Lo siento, finalmente encontré K-maps. En Alemania esto se conoce como 'Karnaugh-Veitch-Diagram' o KV-diagram :)

Esta respuesta considera primero la respuesta de Paebbels y luego brinda otro enfoque (correcto).

El OP tiene dos números de 32 bits que quiere agregar. Solicitar un número de 33 bits para tener la capacidad de detectar un desbordamiento. Dado que se usa 1 bit para indicar "se ha desbordado - pregunta sí/no", el resultado es nuevamente un número de 32 bits. En otras palabras: número de 32 bits + indicador de desbordamiento de 1 bit = 33 bits. Lo cual es conceptualmente diferente a un número de 33 bits (que sería un diseño extraño). También tenga en cuenta que sum(32) & sum(30 downto 0)son de 32 bits (el resultado final).

Ahora considerando la respuesta de Paebbels: Supongamos que a_alu32 y b_alu32 son 2 bits con signo, un bit para la cantidad (número absoluto), 1 bit para el signo. Luego cambie su tamaño a 3 bits (1 bit de signo, 2 bits de cantidad) para a_alu32_s y b_alu32_s. Ejemplo:

  • números de entrada: 01y 01(ambos 1 en decimal)
  • extensión a 3 bits: 001y001
  • suma:001 + 001 = 010
  • tomar los bits más altos de a, b y sumar:000
  • es 000igual a 001o 110? no.. así no se ha desbordado (según la lógica de Paebbels)
  • Sin embargo, ¿qué hace Paebbels para que el resultado final vuelva a ser de 32 bits (y, en este ejemplo, de 2 bits)? o_alu32 <= std_logic_vector(resize(sum_alu32_s, o_alu32'length));. ¿ Cómo 010se vuelve a redimensionar a dos bits? Tome el bit de signo 0, tome el resto 10, corte el msb del resto 10 -> 0, pegue el bit de signo + resto-con-1-bit-menos -> 00. 00está 0en firmado. Entonces 1 + 1 = 0y no se produjo desbordamiento. Extraño... extraño.

La solución que propone esta respuesta es mirar los 2 bits más altos de la suma. Haciéndolo un AND de 2 vías en lugar de un AND de 3 vías (también guardando lógica). Cuando se ha "activado" el bit más alto de la parte de cantidad, se ha producido un desbordamiento (es decir, el número absoluto ha aumentado un bit adicional). "activo" puede ser 0o 1dependiendo del bit de signo. Ejemplo: 010es un número positivo con la parte de cantidad el bit más alto es "activo" ( 1), 101es un número negativo con el bit de cantidad más alto "activo" ( 0) ( 101(-3) es más pequeño que 110(-2) y más pequeño que 111(-1) en dos complementos).

Aquí hay una tabla donde:

  • in1 e in2 son los números de entrada
  • resized1 y resized2 y las versiones redimensionadas temporales
  • sum es la suma de las versiones redimensionadas
  • ov1 es si se ha producido un desbordamiento con el método de Paebbels
  • ov2 es si se ha producido un desbordamiento al observar los dos bits msb de la suma (bit de signo + msn de cantidad-parte) que deberían ser 01o10

mesa:

╔═════╦═════╦══════════╦══════════╦════════════╦═════╦═════╗
║ in1 ║ in2 ║ resized1 ║ resized2 ║    sum     ║ ov1 ║ ov2 ║
╠═════╬═════╬══════════╬══════════╬════════════╬═════╬═════╣0000000000000        ║ no  ║ no  ║0001000001001        ║ no  ║ no  ║0010000110110        ║ no  ║ no  ║0011000111111        ║ no  ║ no  ║0100001000001        ║ no  ║ no  ║0101001001010        ║ no  ║ yes ║0110001110111        ║ no  ║ no  ║0111001111110        ║ no  ║ no  ║1000110000110        ║ no  ║ no  ║1001110001111        ║ no  ║ no  ║10101101101100 (100) ║ no  ║ yes ║10111101111101 (101) ║ no  ║ yes ║1100111000111        ║ no  ║ no  ║11011110011000 (000) ║ no  ║ no  ║11101111101101 (101) ║ no  ║ yes ║11111111111110 (110) ║ no  ║ yes ║
╚═════╩═════╩══════════╩══════════╩════════════╩═════╩═════╝

Tenga en cuenta que la suma puede desbordarse, pero esto está bien porque solo nos importa el desbordamiento de los dos números originales que nos gustaría sumar. Este código provoca el desbordamiento de la suma sum_alu32_s <= a_alu32_s + b_alu32_s;. En este ejemplo, agregar 2 números de 3 bits produce otro número de 3 bits y se pierde el msb, puede ver este efecto en la columna de suma.

Conclusión: tal vez soy yo y no entendí la solución de Paebbels. ¡Pero cuando ejecuto los números, obtengo un resultado en el que el método de Paebbels no detecta un desbordamiento en absoluto!