¿Cómo dividir un número de varios dígitos en dígitos separados en VHDL?

Encontré el método para el lenguaje c . Pero no sé cómo realizar esto en VHDL. Sea un número de punto fijo (de 12 a -19) como 3456,478396. Necesito dividir este número por completo en números separados 3456,478396 --> 3, 4, 5, 6, (punto), 4, 7, 8, 3, 9, 6. .. en 11 variables de tipo entero. ¿Cómo realizar esto en VHDL?

signal example : sfixed(4 downto -4);
--'example' contains 9.75 then it is storage as "01001.1100".
--simply example ="10011100".
--10011100 --> integer 156

¿Cómo recuperar el número 9.75 original de 156 para separarlo en un solo dígito?

SOLÍA,

library ieee;
library ieee_proposed;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee_proposed.float_pkg.ALL;
use ieee_proposed.fixed_pkg.ALL;
use ieee_proposed.fixed_float_types.ALL;
¿Cómo se representa el número original? ¿Cómo quieres que se represente una vez "roto"?
depende de cómo se mantenga el número. Si está en BCD, entonces es fácil. Si está en binario, primero debe convertir a decimal.
@Eugene Sh en la pregunta que mencioné que necesito dividir este número por completo en números separados 3456.478396 --> 3, 4, 5, 6, (punto), 4, 7, 8, 3, 9, 6... en 11 variables de tipo entero.
Consulte aquí: stackoverflow.com/questions/23871792/… Una vez que su entero binario se convierte a BCD, cada dígito está separado...
@Mishyoshi Eso no resuelve el lado derecho del problema. Los valores decimales.
@Harry Svensson, lo siento, acabo de recuperar esto, pensé que era una pregunta tonta.
Creo que es una buena pregunta, aunque no busqué ningún duplicado.

Respuestas (1)

Aquí hay algo de pseudocódigo.

Tomemos primero los que quedan del decimal, el número máximo es 15 10 => 2 dígitos decimales.

signal ex : sfixed(4 downto -4);

temp <= ex(4 downto 0);
L_0 <= temp mod 10;
temp <= temp/10;
L_1 <= temp mod 10;

Ejemplo:
ex= 12 10 = 1100 2

temp <= 12
L_0 <= 12 mod 10 = 2
temp <= 12/10    = 1
L_1 <= 1 mod 10  = 1

Y luego los de la derecha, el número más pequeño => 0.0625 => 4 dígitos decimales. Mismo método que antes, simplemente multiplicar por 625 10 antes de que empieces. Porque 0001 2 en binario se traduce a .0625 10 en decimal Entonces, el ancho de bit de la temperatura debe ser C mi i yo ( yo o gramo 2 ( 625 × 15 ) ) = 14 bits porque 15 10 es 1111 2 cual es su mayor valor.

signal ex : sfixed(4 downto -4);

temp <= ex(0 downto -4);
temp <= temp*625

R_3 <= temp mod 10;
temp <= temp/10;
R_2 <= temp mod 10;
temp <= temp/10;
R_1 <= temp mod 10;
temp <= temp/10;
R_0 <= temp mod 10;

Ejemplo:
ex= 0.1875 10 = 0011 2

temp <= 3 = 0011
temp <= 3*625 = 11101010011        = 1875

R_3 <= 1875 mod 10                 = 5
temp <= 1875/10                    = 187
R_2 <= 187 mod 10                  = 7
temp <= 187/10                     = 18
R_1 <= 18 mod 10                   = 8
temp <= 18/10                      = 1
R_0 <= 1 mod 10                    = 1

Y debería mostrarse así:

L 1 L 0 . R 0 R 1 R 2 R 3

Toda la división constante por 10 puede ser reemplazada por una multiplicación con 1 10 . Por lo tanto, no es demasiado ineficiente de implementar. Estoy bastante seguro de que el operador de módulo viene con la biblioteca estándar.

Si usa 6 bits para el lado derecho del punto decimal. Entonces el ancho de bit para la temperatura debe ser C mi i yo ( yo o gramo 2 ( 63 × 15625 ) ) = 20 bits . Probablemente esta no sea la forma más eficiente, es una forma que se me ocurrió ahora por mi cuenta. Debería funcionar sin mayores problemas.

Como esto se está haciendo en un FPGA, puede paralelizar la multiplicación, para R3, R2, R1 y R0, multiplique su temperatura por 1, 1 10 , 1 100 y 1 1000 para que obtenga los valores de inmediato, en lugar de en serie. Y luego usa el mod 10 en ellos.


EDITAR

Mishyoshi me dio una idea de cómo podría resolverse esto de otra manera. L 0 y L 1 se resuelven como antes, pero el R 0..3 se puede hacer de otra manera más eficiente.

signal ex : sfixed(4 downto -4);

signal temp : sfixed(4 downto -4); 
//We need 4 to the left of the decimal point because then we can capture
//all the single digits

temp <= "0000" & ex(0 downto -4);
temp <= temp*10;

R_0 <= temp(3 downto 0); //Copy the 4 MSB bits 
temp <= "0000" & temp(-1 downto -4); //Delete the 4 MSB bits
temp <= temp*10;
R_1 <= temp(3 downto 0);
temp <= "0000" & temp(-1 downto -4);
temp <= temp*10;
R_2 <= temp(3 downto 0);
temp <= "0000" & temp(-1 downto -4);
temp <= temp*10;
R_3 <= temp(3 downto 0);

Ejemplo:
ex= 0.1875 10 = 0011 2

signal temp : sfixed(4 downto -4);

temp <= "0000" & "0011"                     = 0000.0011 = 3
temp <= 3*10                           = 30 = 0001.1110 
R_0 <= "0001.1110"(3 downto 0)              = 0001 = 1
temp <= "0000" & temp(-1 downto -4)         = 0000.1110
temp <= 14*10                         = 140 = 1000.1100
R_1 <= "1000.1100"(3 downto 0)              = 1000 = 8
temp <= "0000" & "1100"                     = 0000.1100
temp <= 12*10                         = 120 = 0111.1000
R_2 <= "0111.1000"(3 downto 0)              = 0111 = 7
temp <= "0000" & "1000"                     = 0000.1000
temp <= 8*10                           = 80 = 0101.0000
R_3 <= "0101.0000"(3 downto 0)              = 0101 = 5

Como puede ver, se trata de llevar los bits al lugar de los "unos", los 4 bits a la izquierda del punto decimal.

Eso es mucho menos bits necesarios para esto. En esta otra solución puedes, como dijo Mishyoshi, ponerlos en una tubería.

No entiendo qué es y cómo se obtuvo el número más pequeño => 0.0625 => 4 dígitos decimales . el numero 625
si pone 1/16 en la calculadora, mostrará 0.0625, si solo mira los números distintos de cero, dice 625. Eso significa que 0000.0001 en binario es 0.0625 en decimal. Entonces el "peso" del 1 es 1/16. Pero como estamos en el "lado derecho", podemos simplemente ignorar el punto decimal y tratarlo como 0625. En otras palabras, simplemente multiplicar por 625. Debido a que solo estamos convirtiendo a BCD, no estamos haciendo nada. elegante.
Si fueran 6 bits, entonces multiplicarías por 15625 porque 0000.000001 en binario es 0.015625 en decimal. Elimina el decimal y obtienes 000001 es 015625. Así que multiplica el 1 por 015625 y luego comienza a cortar los dígitos.
Podría estar equivocado, pero para un valor fraccionario de punto fijo de 4 bits, puede realizar una multiplicación binaria de 10000 porque tiene un valor de 0.0625 (4 dígitos => 10 ^ 4). Luego convierta eso a BCD usando el enlace que proporcioné. El valor será 10000 veces demasiado grande, así que considere la posición del punto decimal 4 a la izquierda. Solo habría una sola multiplicación con un multiplicador fácilmente disponible y un montón de sumadores que podrían canalizarse.
Hmm, estás en algo @Mishyoshi. Necesitas hacer algo más que simplemente multiplicar por 10 4 aunque.
@Harry Svensson en el cálculo anterior , la temperatura es un vector, ¿no es necesario convertirlo a un número entero antes de ir a los pasos mod 10 y **/10**? Estoy usando el paquete de punto fijo de David Bishop .
@Oppo Dije que es pseudocódigo , lo que significa que ignoro el 90% de toda la semántica y solo escribo código como un algoritmo. La razón de esto es porque no quiero profundizar en el lenguaje VHDL porque A , no tengo tiempo para verificar el código, B , no tengo Quartus instalado, C , ese algoritmo debería ser suficiente para ponerte en la dirección correcta.
@Harry Svensson Seguí el método exacto anterior para un número fijo (de 19 a -19) pero obtengo 3 74334.738277 para el valor 2 74334.738295 la parte fraccionaria está bien, el valor izquierdo ha cambiado .
No sé qué decirte, sin ningún código ni conocimiento de cómo lo hiciste, no hay nada que pueda decirte. Todo lo que sé es que debería funcionar, si hay algún problema con el último bit, entonces hiciste algo bien para cada número, excepto para el último. sfixed significa número fijo firmado , ¿verdad? Tal vez haya algún error sucediendo en el último bit porque es un bit de señal.
@Harry Svensson, sí, el último bit es 1 si es un número negativo y 0 si es un número positivo para sfixed (lib de David Bishop) -9.75 = "10110010" y 9.75 = "01001110"
Bueno, ahí está la respuesta de por qué no funciona.
@Harry Svensson No entiendo, ¿qué se debe hacer?
@oppo ¿Cómo espera hacer el número 374334 con 18 bits? -- Tú no . el bit 19 es el bit de signo. Entonces, sea cual sea el empujón de silencio que estés haciendo, imagina que eres 1 bit menos y cuida especialmente el bit 19. Como... si es un 1, entonces genera un "-", si es un 0, no genera un "-".