¿Cómo convertir de binario a hexadecimal en verilog?

1

La pregunta necesita una explicación:

Supongamos que tengo un valor de 8 bits, digamos 8'b00000001 (1)

Supongamos que tengo el módulo de la siguiente manera:

module hex_decoder(hex_digit, segments);
    input [3:0] hex_digit;
    output reg [6:0] segments;

    always @(*)
        case (hex_digit)
            4'h0: segments = 7'b100_0000;
            4'h1: segments = 7'b111_1001;
            4'h2: segments = 7'b010_0100;
            4'h3: segments = 7'b011_0000;
            4'h4: segments = 7'b001_1001;
            4'h5: segments = 7'b001_0010;
            4'h6: segments = 7'b000_0010;
            4'h7: segments = 7'b111_1000;
            4'h8: segments = 7'b000_0000;
            4'h9: segments = 7'b001_1000;
            4'hA: segments = 7'b000_1000;
            4'hB: segments = 7'b000_0011;
            4'hC: segments = 7'b100_0110;
            4'hD: segments = 7'b010_0001;
            4'hE: segments = 7'b000_0110;
            4'hF: segments = 7'b000_1110;   
            default: segments = 7'h7f;
        endcase
endmodule

para generar en HEX0 y HEX1, puedo hacer algo como esto:

hex_decoder h0(.hex_digit(value[3:0]), HEX0);
hex_decoder h1(.hex_digit(value[7:4]), HEX1);

y esto mostrará 01 en HEX1, HEX0.

El único problema es que después de 9 , los valores se convertirán en letras hexadecimales. Lo quiero para que si paso el binario 10, ( 8'b00001010 ), HEX1 HEX0 debería ser 1 0, no 0 A (como funciona el hex)

¿Cómo puedo convertirlo así?

    
pregunta K Split X

3 respuestas

2

El problema que tiene es bastante común: cómo convertir un número binario en algo llamado "decimal codificado en binario" (BCD). En BCD, cada dígito es de 4 bits, pero esos 4 bits solo se usan para representar los números 0-9 (de ahí el bit decimal). Este es un formato ideal para mostrar en pantallas de 7 segmentos, pantallas, de hecho, cualquier cosa que necesite un número decimal para mostrarse.

La forma más sencilla de convertir de binario a BCD es mediante un algoritmo llamado "Mayúsculas-Add-3" o "Double-Dabble" (ambos nombres para la misma cosa). Esencialmente, el enfoque es escanear a través de la representación binaria, luego, cada vez que vea un número que es 5 o más alto en cada grupo de 4 bits, le agrega 3. Básicamente, este enfoque es una forma de desbordar cualquier valor mayor o igual a 10 en un dígito en el siguiente sin demasiado hardware.

Aquí hay un ejemplo, robado de esta Página de Wikipedia :

  

Double Dabble Conversion of 243 Hund Tens Unit Shift In 0000 0000 0000 11110011 Initialization 0000 0000 0001 11100110 Shift 0000 0000 0011 11001100 Shift 0000 0000 0111 10011000 Shift 0000 0000 1010 10011000 Add 3 to ONES, since it was 7 0000 0001 0101 00110000 Shift 0000 0001 1000 00110000 Add 3 to ONES, since it was 5 0000 0011 0000 01100000 Shift 0000 0110 0000 11000000 Shift 0000 1001 0000 11000000 Add 3 to TENS, since it was 6 0001 0010 0001 10000000 Shift 0010 0100 0011 00000000 Shift 2 4 3 BCD

Construir este proceso en Verilog es relativamente sencillo. Te lo dejo como ejercicio.

    
respondido por el Tom Carpenter
0

El problema con Double-Dabble es que fue escrito para programas de software, por lo que la solución es inherentemente serial. Los FPGA y los ASIC son paralelos en la naturaleza: necesitamos usar sus fortalezas para nuestro beneficio.

Mientras funciona Double-Dabble, el ejemplo dado aquí utiliza 11 ciclos de reloj después de la inicialización para obtener un resultado de 3 dígitos de una entrada de 8 bits. Para obtener un resultado de 8 dígitos de una entrada de 27 bits, Double-Dabble requiere 35 ciclos de reloj. Un objetivo alcanzable para un resultado de N dígitos es N-1 ciclos de reloj. ¿Cómo? Haciendo división larga en paralelo.

Para obtener un resultado de ocho dígitos de una entrada de 27 bits, comience haciendo 9 restas en paralelo, input1 menos: 9000_0000, 8000_0000, 7000_0000, ..., 2000_0000, 1000_0000 e implícito 0. Tome el resto del factor más grande donde el resultado no es negativo (pruebe el bit superior del resultado), registre el factor como el dígito superior y use el resto como entrada para la siguiente etapa, que es nuevamente 9 restas en paralelo. Input2 menos 900_0000, 800_0000, 700_0000, ..., 200_0000, 100_0000 e implícito 0. Repita este procedimiento hasta la entrada 7 menos 90, 80, 70, ..., 20 y 10. El resto de la última resta es el dígito de la persona .

El uso de este método requiere siete ciclos de reloj después de la inicialización para obtener un resultado de ocho dígitos. Dependiendo del FPGA, esto podría implementarse con nueve DSP y 63 constantes. Sin los DSP, el número de bits de sustracción se reduce en tres o cuatro bits en cada ciclo, por lo que no toma toda la estructura que se podría esperar, y solo se requieren siete ciclos de reloj para completar.

    
respondido por el Daniel Wisehart
0

Una tabla de rom podría funcionar si te gusta usar puertas FPGA ... Digamos que tienes una placa de desarrollo FPGA típica con cuatro pantallas de 7 segmentos, y quieres mostrar valores sin firma. Eso es 10000 caracteres totales, 7 bits cada uno, redondear a 16K por 32 bits es una rom de 64 Kbyte. (El 7 seg a mi lado también tiene un LED decimal, por lo que 8 bits por carácter ..)

Algo así como un "generador de caracteres" de la edad de piedra de los terminales ascii.

También puedes usar hasta 7 seg y pasar de 9999 a -999.

El relleno de la tabla de rom puede realizarse mediante C o Python, etc., utilizando uno de los anteriores y convirtiendo la salida al formato de archivo de rom de FPGA.

A velocidades FPGA esto es ligeramente (!!)  Más que un poco más rápido de lo necesario y, por lo tanto, un desperdicio de puertas, pero si tiene espacio, ¿por qué no?

Definitivamente lo suficientemente rápido para los juegos Persistence of Vision ..

Sin embargo, por lo general, si ya tiene un pequeño microprocesador incorporado, use una de las rutinas secuenciales anteriores y deje que el micro lo maneje como una de sus tareas.

    
respondido por el Gord Wait

Lea otras preguntas en las etiquetas