5 votos

Resultados inesperados cuando se multiplica en VHDL

Estoy tratando de hacer una sencilla BCD --> binario operación de conversión de trabajo en una ALU estoy de codificación. Todas las otras operaciones de trabajo perfectamente bien, sólo esta última operación no funciona por alguna razón.

He intentado numerosos enfoques y nada parece tener sentido.

Mis entradas son A y B que son de 8 bits en vectores. Las salidas son X y Y.

Así que la fórmula va Y:X = BCD2BIN(B:A).

En mi caso, en mi testbench he B = 0x40 y A = 0x46, por lo que el resultado que estoy esperando es 0xFCE, que es 4046.

Sólo para aquellos que son conscientes de la forma más sencilla de realizar esto es dividir cada byte en 2 nibbles, y se multiplica por una constante y la suma de los términos.

Así:

B:A = 0x4046 = (4 * 1000) + (0 * 100) + (4 * 10) * (6 * 1)

Señales de que estoy Usando

B = 0x40  --These are the inputs of the ALU, so it isn't actually coded this way.
A = 0x46  --However these are the values.

signal sig1000 : STD_LOGIC_VECTOR(15 downto 0) := x"03E8"; --1000
signal sig100 : STD_LOGIC_VECTOR(15 downto 0) := x"0064";  --100
signal sig10 : STD_LOGIC_VECTOR(15 downto 0) := x"000A";  --10

signal dig1 : STD_LOGIC_VECTOR(3 downto 0);
signal dig2 : STD_LOGIC_VECTOR(3 downto 0);
signal dig3 : STD_LOGIC_VECTOR(3 downto 0);
signal dig4 : STD_LOGIC_VECTOR(3 downto 0);

Después de COMENZAR el

dig1 <= B(7 downto 4);
dig2 <= B(3 downto 0);
dig3 <= A(7 downto 4);
dig4 <= A(3 downto 0);

De La Operación Real

opF <= STD_LOGIC_VECTOR((unsigned(dig1) * unsigned(sig1000)) + (unsigned(dig2) * unsigned(sig100)) + (unsigned(dig3) * unsigned(sig10)) + (unsigned(dig4)));

Y más tarde, el opF quede dividida en y y X.

Así que incluso la verificación de las señales en la simulación, son correctas, sin embargo, la salida no es.

El sig10001, sig100 y sig10 son los valores correctos y dig1 = 4, dig2 = 0, dig3 = 4 y dig4 = 6 con base decimal sin signo.

Sin embargo, el resultado es de 252

Incluso he intentado esta utilizando constantes, en lugar de vectores, con menos éxito.

Por ejemplo

opF <= STD_LOGIC_VECTOR((unsigned(dig1) * 10#1000#) + (unsigned(dig2) * 10#100#) + (unsigned(dig3) * 10#10#) + (unsigned(dig4)));

Archivo completo, como algunos lo han solicitado.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity ALU is
Port ( A : in  STD_LOGIC_VECTOR (7 downto 0);
       B : in  STD_LOGIC_VECTOR (7 downto 0);
       Cin : in  STD_LOGIC;
       OPCODE : in  STD_LOGIC_VECTOR (3 downto 0);
       Y : out  STD_LOGIC_VECTOR (7 downto 0);
       X : out  STD_LOGIC_VECTOR (7 downto 0);
       Z : out  STD_LOGIC;
       Cout : out  STD_LOGIC;
       V : out  STD_LOGIC;
       F_active : out  STD_LOGIC;
       X_bin_pal : out  STD_LOGIC;
       X_prime : out  STD_LOGIC;
       N : out  STD_LOGIC);
end ALU;

architecture Behavioral of ALU is

    signal resultSignal : STD_LOGIC_VECTOR(15 downto 0);

    signal cin_vector : STD_LOGIC_VECTOR(0 downto 0);

    signal op0 : STD_LOGIC_VECTOR(15 downto 0);
    signal op1 : STD_LOGIC_VECTOR(15 downto 0);
    signal op2 : STD_LOGIC_VECTOR(15 downto 0);
    signal op3 : STD_LOGIC_VECTOR(15 downto 0);
    signal op4 : STD_LOGIC_VECTOR(15 downto 0);
    signal op5 : STD_LOGIC_VECTOR(15 downto 0);
    signal op6 : STD_LOGIC_VECTOR(15 downto 0);
    signal op7 : STD_LOGIC_VECTOR(15 downto 0);
    signal op8 : STD_LOGIC_VECTOR(15 downto 0);
    signal op9 : STD_LOGIC_VECTOR(15 downto 0);
    signal opA : STD_LOGIC_VECTOR(15 downto 0);
    signal opB : STD_LOGIC_VECTOR(15 downto 0);
    signal opC : STD_LOGIC_VECTOR(15 downto 0);
    signal opD : STD_LOGIC_VECTOR(15 downto 0);
    signal opE : STD_LOGIC_VECTOR(15 downto 0);
    signal opF : STD_LOGIC_VECTOR(15 downto 0);

    signal dig1 : STD_LOGIC_VECTOR(3 downto 0);
    signal dig2 : STD_LOGIC_VECTOR(3 downto 0);
    signal dig3 : STD_LOGIC_VECTOR(3 downto 0);
    signal dig4 : STD_LOGIC_VECTOR(3 downto 0);

    signal Xsig : STD_LOGIC_VECTOR(7 downto 0) := x"00";
    signal Xsig_reverse : STD_LOGIC_VECTOR(7 downto 0) := x"00";

    signal Ysig : STD_LOGIC_VECTOR(7 downto 0) := x"00";

    signal Zsig : STD_LOGIC := '0';
    signal Coutsig : STD_LOGIC := '0';
    signal Vsig : STD_LOGIC := '0';
    signal Nsig : STD_LOGIC := '0';

    signal sig1000 : STD_LOGIC_VECTOR(15 downto 0) := x"03E8";
    signal sig100 : STD_LOGIC_VECTOR(15 downto 0) := x"0064";
    signal sig10 : STD_LOGIC_VECTOR(15 downto 0) := x"000A";



begin

cin_vector(0) <= Cin;

dig1 <= B(7 downto 4);
dig2 <= B(3 downto 0);
dig3 <= A(7 downto 4);
dig4 <= A(3 downto 0);

op0 <= x"00" & (A AND B);
op1 <= x"00" & (A OR B);
op2 <= x"00" & (A XOR B);
op3 <= x"00" & (A XNOR B);
op4 <= STD_LOGIC_VECTOR(unsigned(x"00" & A) + unsigned(x"00" & B));
op5 <= x"00" & STD_LOGIC_VECTOR(signed(A) + signed(B));
op6 <= STD_LOGIC_VECTOR(unsigned(x"00" & A) + unsigned(x"00" & B) + unsigned(x"000" & "000" & cin_vector));
op7 <= STD_LOGIC_VECTOR(signed(A) * signed(B));
op8 <= STD_LOGIC_VECTOR(unsigned(A) * unsigned(B));
op9 <= STD_LOGIC_VECTOR(unsigned(x"00" & A) - unsigned(x"00" & B));
opA <= STD_LOGIC_VECTOR(ROTATE_LEFT(unsigned(A & x"00"), 1));
opB <= STD_LOGIC_VECTOR(ROTATE_LEFT(unsigned(Cin & A & "0000000"), 1));
opC <= STD_LOGIC_VECTOR(SHIFT_RIGHT(unsigned(A & x"00"), 1));
opD <= STD_LOGIC_VECTOR(SHIFT_RIGHT(signed(A & x"00"), 1));
opE <= STD_LOGIC_VECTOR(SHIFT_LEFT(unsigned(A & x"00"), 1));
opF <= STD_LOGIC_VECTOR((unsigned(dig1) * unsigned(sig1000)) + (unsigned(dig2) * unsigned(sig100)) + (unsigned(dig3) * unsigned(sig10)) + (unsigned(dig4)));

with OPCODE select resultSignal <=
     op0 when x"0",
     op1 when x"1",
     op2 when x"2",
     op3 when x"3",
     op4 when x"4",
     op5 when x"5",
     op6 when x"6",
     op7 when x"7",
     op8 when x"8",
     op9 when x"9",
     opA when x"A",
     opB when x"B",
     opC when x"C",
     opD when x"D",
     opE when x"E",
     opF when x"F";


Ysig <= resultSignal(15 downto 8) when OPCODE = "0111" or OPCODE = "1000" or OPCODE = "1111" else
        x"00";

Y <= Ysig;

Xsig <=     resultSignal(15 downto 8) when OPCODE = "1100" or OPCODE = "1101" or OPCODE = "1110" else
            resultSignal(15 downto 9) & resultSignal(0) when OPCODE = "1010" else
            resultSignal(14 downto 8) & resultSignal(0) when OPCODE = "1011" else
            resultSignal(7 downto 0);

Xsig_reverse <= Xsig(0) & Xsig(1) & Xsig(2) & Xsig(3) & Xsig(4) & Xsig(5) & Xsig(6) & Xsig(7);

X <= Xsig;

Zsig <=     '1' when resultSignal = x"0000" else
        '0';

Z <= Zsig;

Coutsig <=  resultSignal(8) when OPCODE = "0100" or OPCODE = "0110" or OPCODE = "1001"  or OPCODE = "1110" else
            resultSignal(15) when OPCODE = "1011" else
            resultSignal(7) when OPCODE = "1100" or OPCODE  = "1101" else
            '1' when OPCODE = "1111" and  Ysig /= x"00" else
            '0';

Cout <= Coutsig;


Vsig <=     '1' when OPCODE = "0101" and resultSignal(7) = '0' and A(7) = '1' and B(7) = '1' else
            '1' when OPCODE = "0101" and resultSignal(7) = '1' and A(7) = '0' and B(7) = '0' else
            '1' when OPCODE = "1110" and resultSignal(15) /= A(7) else
            '0';

V <= Vsig;

F_active <= Zsig OR Coutsig OR Vsig;

X_bin_pal <=    '1' when Xsig = Xsig_reverse else
                    '0';

X_prime <=  '1' when Xsig = x"02" or Xsig = x"03" or Xsig = x"05" or Xsig = x"07" or Xsig = x"0B" or Xsig = x"0D" or Xsig = x"11" or Xsig = x"13" else
                '1' when Xsig = x"17" or Xsig = x"1D" or Xsig = x"1F" or Xsig = x"25" or Xsig = x"29" or Xsig = x"2B" or Xsig = x"2F" or Xsig = x"35" else
                '1' when Xsig = x"3B" or Xsig = x"3D" or Xsig = x"43" or Xsig = x"47" or Xsig = x"49" or Xsig = x"4F" or Xsig = x"53" or Xsig = x"59" else
                '1' when Xsig = x"61" or Xsig = x"65" or Xsig = x"67" or Xsig = x"6B" or Xsig = x"6D" or Xsig = x"71" or Xsig = x"7F" or (Xsig = x"83" and Nsig = '0') else
                '1' when (Xsig = x"89" or Xsig = x"8B" or Xsig = x"95" or Xsig = x"97" or Xsig = x"9D" or Xsig = x"A3" or Xsig = x"A7" or Xsig = x"AD") and Nsig = '0' else
                '1' when (Xsig = x"B3" or Xsig = x"B5" or Xsig = x"BF" or Xsig = x"C1" or Xsig = x"C5" or Xsig = x"C7" or Xsig = x"D3" or Xsig = x"DF") and Nsig = '0' else
                '1' when (Xsig = x"E3" or Xsig = x"E5" or Xsig = x"E9" or Xsig = x"EF" or Xsig = x"F1" or Xsig = x"FB") and Nsig = '0' else
                '0';

Nsig <= '1' when OPCODE = "0101" and Xsig(7) = '1' else
        '1' when OPCODE = "0111" and Ysig(7) = '1' else
        '1' when OPCODE = "1101" and Xsig(7) = '1' else
        '1' when OPCODE = "1110" and Xsig(7) = '1' else
        '0';

N <= Nsig;



end Behavioral;

10voto

Darren Hicks Puntos 1021

16 bits multiplicado por 4 bits puede llegar a ser, como máximo, un 20 bits de número, al parecer, esto es el tamaño que se crea implícitamente por VHDL para almacenar el resultado intermedio de la multiplicación. Cuando esta implícito 20 bits número es asignado a un número de 16 bits de la matriz, los últimos 4 bits se pierden. Y es por eso que Brian Drummonds del simulador de VHDL se quejó obligado matriz de error.

Debido a que su resultado final realmente encaja en un 16 bits número, la mejor solución es reducir el número de bits de sig1000, sig100, sig10 a un 12 bits de la matriz.

7voto

Brian Drummond Puntos 27798

La primera cosa a hacer, como siempre, es para escribir un testbench. He aquí un mínimo de un (a continuación). Nota: he utilizado un VHDL-2008 "to_string" llamada a la simplificación.

Ahora, analizar, elaborar y simular...

ghdl -a --std=08 alu.vhd
ghdl -a --std=08 alu_tb.vhd
ghdl -e --std=08 ALU_TB
./alu_tb
./alu_tb:error: bound check failure at alu.vhd:89
./alu_tb:error: simulation failed

Así que el problema es una matriz obligado violación en la línea 89 ... que es, por supuesto, opF <= ...

Que el simulador no se puede diagnosticar una simple violación de los límites? Zanja y obtener una mejor. O averiguar cómo activar la envolvente de cheques. (Si es Xilinx ISIM, hay una opción que nunca debería haber estado fuera en el primer lugar).

Pero ahora que usted sabe que es una simple matriz de obligado error debe ser muy fácil de encontrar y corregir. Comience por ejecutar sólo un dígito a la vez a través de ese grande de cálculo.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity ALU_TB is
end ALU_TB;

architecture TB of ALU_TB is

constant A : STD_LOGIC_VECTOR (7 downto 0) := X"46";
constant B : STD_LOGIC_VECTOR (7 downto 0) := X"40";
constant Cin : STD_LOGIC := '0';
constant OPCODE : STD_LOGIC_VECTOR (3 downto 0) := X"F";
signal Y : STD_LOGIC_VECTOR (7 downto 0);
signal X : STD_LOGIC_VECTOR (7 downto 0);

begin

DUT : entity Work.ALU
Port Map( 
       A         => A,
       B         => B,
       Cin       => Cin,
       OPCODE    => OPCODE,
       Y         => Y,
       X         => X,
       Z         => open,
       Cout      => open,
       V         => open,
       F_active  => open,
       X_bin_pal => open,
       X_prime   => open,
       N         => open);

check : process is
begin
   wait for 1 us;
   report "X = " & to_string(X) severity NOTE;
   report "Y = " & to_string(Y) severity NOTE;
end process check;

end TB;

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X