Aquí hay un 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 que están a la derecha, el número más pequeño = > 0.0625 = > 4 dígitos decimales. El mismo método que antes, solo multiplica por \ $ 625_ {10} \ $ antes de comenzar. Porque \ $ 0001_ {2} \ $ en binario se traduce a \ $. 0625_ {10} \ $ en decimal. Por lo tanto, el ancho de bits de temp debe ser \ $ ceil (log_2 (625 × 15)) = \ $ 14 bits porque \ $ 15_ {10} \ $ es \ $ 1111 _ {2} \ $, que es tu valor más alto.
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 se puede reemplazar por una multiplicación con \ $ \ frac {1} {10} \ $. Así que no es demasiado ineficiente para 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. Luego, el ancho de bits para temp debe ser \ $ ceil (log2 (63 × 15625)) \ $ = 20 bits . Probablemente esta no sea la forma más eficiente, es una forma que se me ocurrió ahora mismo por mi cuenta. Debería funcionar sin mayores problemas.
Ya que esto se está haciendo en un FPGA, puedes paralelizar la multiplicación, para R3, R2, R1 y R0, multiplica su temp con 1, \ $ \ frac {1} {10} \ $, \ $ \ frac {1} {100} \ $ y \ $ \ frac {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 esto podría resolverse de otra manera. \ $ L_0 \ $ y \ $ L_1 \ $ se resuelven como antes, pero \ $ 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 "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.