PDA

View Full Version : [VHDL o algoritmo] Normalizzazione di un numero binario


giovafrankie
24-11-2015, 17:20
Sto realizzando una Floating Point Unit a precisione variabile e avrei bisogno di un modulo che faccia la normalizzazione.

L'idea è scorrere il mio vettore di bit e, non appena trovo il primo 1 (da sinistra), scrivere dentro una variabile (out_shift_esp_int) di quanto è lo shift (poi un altro modulo lo effettua, sfruttando quel numero).

Ho già realizzato un codice che lo fa in maniera "fissa":

--SI OCCUPA DI NORMALIZZARE IL NUMERO POST OPERAZIONE, CIOÈ SHIFTA IL RISULTATO A SINISTRA PER PORTARE IL PRIMO 1 NELLA POSIZIONE CORRETTA
encoder_priority: process(out_mux_normalizzatore, out_mux_esp)

variable out_shift_esp_appoggio: std_logic_vector(6 downto 0);
begin

--IMPLEMENTO UNA ENCODER PRIORITY, TROVANDO DIRETTAMENTE LO SHIFT
if out_mux_normalizzatore(23)='1'then out_shift_esp_int<="1111111"; -- lo shift è -1 111111
elsif out_mux_normalizzatore(22)='1' then out_shift_esp_int<="0000000"; -- lo shift è 0
elsif out_mux_normalizzatore(21)='1' then out_shift_esp_int<="0000001"; -- lo shift è 1 verso sx
elsif out_mux_normalizzatore(20)='1' then out_shift_esp_int<="0000010"; -- lo shift è 2 verso sx
elsif out_mux_normalizzatore(19)='1' then out_shift_esp_int<="0000011"; -- lo shift è 3 verso sx
elsif out_mux_normalizzatore(18)='1' then out_shift_esp_int<="0000100"; -- lo shift è 4 verso sx
elsif out_mux_normalizzatore(17)='1' then out_shift_esp_int<="0000101"; -- lo shift è 5 verso sx
elsif out_mux_normalizzatore(16)='1' then out_shift_esp_int<="0000110"; -- lo shift è 6 verso sx
elsif out_mux_normalizzatore(15)='1' then out_shift_esp_int<="0000111"; -- lo shift è 7 verso sx
elsif out_mux_normalizzatore(14)='1' then out_shift_esp_int<="0001000"; -- lo shift è 8 verso sx
elsif out_mux_normalizzatore(13)='1' then out_shift_esp_int<="0001001"; -- lo shift è 9 verso sx
elsif out_mux_normalizzatore(12)='1' then out_shift_esp_int<="0001010"; -- lo shift è 10 verso sx
elsif out_mux_normalizzatore(11)='1' then out_shift_esp_int<="0001011"; -- lo shift è 11 verso sx
elsif out_mux_normalizzatore(10)='1' then out_shift_esp_int<="0001100"; -- lo shift è 12 verso sx
elsif out_mux_normalizzatore(9)='1' then out_shift_esp_int<="0001101"; -- lo shift è 13 verso sx
elsif out_mux_normalizzatore(8)='1' then out_shift_esp_int<="0001110"; -- lo shift è 14 verso sx
elsif out_mux_normalizzatore(7)='1' then out_shift_esp_int<="0001111"; -- lo shift è 15 verso sx
elsif out_mux_normalizzatore(6)='1' then out_shift_esp_int<="0010000"; -- lo shift è 16 verso sx
elsif out_mux_normalizzatore(5)='1' then out_shift_esp_int<="0010001"; -- lo shift è 17 verso sx
elsif out_mux_normalizzatore(4)='1' then out_shift_esp_int<="0010010"; -- lo shift è 18 verso sx
elsif out_mux_normalizzatore(3)='1' then out_shift_esp_int<="0010011"; -- lo shift è 19 verso sx
elsif out_mux_normalizzatore(2)='1' then out_shift_esp_int<="0010100"; -- lo shift è 20 verso sx
elsif out_mux_normalizzatore(1)='1' then out_shift_esp_int<="0010101"; -- lo shift è 21 verso sx
elsif out_mux_normalizzatore(0)='1' then out_shift_esp_int<="0010110"; -- lo shift è 22 verso sx
else out_shift_esp_int <= out_mux_esp; -- NON CI SONO 0 QUINDI DAL MUX ARRIVA TUTTI 000...00 QUINDI L'USCITA È 0
end if;
end process encoder_priority;



Ho successivamente realizzato una versione parametrica. Però non sembra funzionare (l'uscita non è quella che dovrebbe essere). :muro:

--SI OCCUPA DI NORMALIZZARE IL NUMERO POST OPERAZIONE, CIOÈ SHIFTA IL RISULTATO A SINISTRA PER PORTARE IL PRIMO 1 NELLA POSIZIONE CORRETTA
encoder_priority: process(out_mux_normalizzatore, out_mux_esp)

variable counter: integer := ((2*(n_mant+2))-1);
variable i: integer;

begin

--IMPLEMENTO UNA ENCODER PRIORITY, TROVANDO DIRETTAMENTE LO SHIFT
if out_mux_normalizzatore(counter)='1' then out_shift_esp_int <= (others=>'1'); -- lo shift è -1 111111

else

normalizer: for i in (counter-1) to 0
LOOP
if out_mux_normalizzatore(i)='1' then
out_shift_esp_int <= conv_std_logic_vector(integer(counter-i-1),n_esp+2);
exit;
end if;
END LOOP normalizer;

if (i=0) then out_shift_esp_int <= out_mux_esp;
end if;

end if;

end process encoder_priority;


Volevo chiedervi se avete altre idee per poter risolvere questo problema. Quello che non posso realizzare è la prima soluzione parametrica, perchè è impossibile realizzare degli IF annidiati dentro ad un LOOP.

Non è necessaria la conoscenza del linguaggio VHDL, sarebbe utile anche un consiglio sull'algoritmo da utilizzare, poi ci penso io ad implementarlo, se possibile.

Vi ringrazio in anticipo. :help:


P.S.: Non essendoci la possibilità di lasciare indentato il codice, ho provveduto a colorarlo, il maniera da renderlo più leggibile.

ingframin
26-11-2015, 13:41
Sto realizzando una Floating Point Unit a precisione variabile e avrei bisogno di un modulo che faccia la normalizzazione.

L'idea è scorrere il mio vettore di bit e, non appena trovo il primo 1 (da sinistra), scrivere dentro una variabile (out_shift_esp_int) di quanto è lo shift (poi un altro modulo lo effettua, sfruttando quel numero).

Ho già realizzato un codice che lo fa in maniera "fissa":



Ho successivamente realizzato una versione parametrica. Però non sembra funzionare (l'uscita non è quella che dovrebbe essere). :muro:


Volevo chiedervi se avete altre idee per poter risolvere questo problema. Quello che non posso realizzare è la prima soluzione parametrica, perchè è impossibile realizzare degli IF annidiati dentro ad un LOOP.

Non è necessaria la conoscenza del linguaggio VHDL, sarebbe utile anche un consiglio sull'algoritmo da utilizzare, poi ci penso io ad implementarlo, se possibile.

Vi ringrazio in anticipo. :help:


P.S.: Non essendoci la possibilità di lasciare indentato il codice, ho provveduto a colorarlo, il maniera da renderlo più leggibile.

Se puoi aspettare domenica ti rispondo io.
Nel frattempo, hai provato a vedere su opencores?
Tipo questo:

--
-- VHDL Architecture HAVOC.FPnormalize.FPnormalize
--
-- Created:
-- by - Guillermo
-- at - ITESM, 10:51:00 07/16/03
--
-- Generated by Mentor Graphics' HDL Designer(TM) 2002.1b (Build 7)
--
-- hds interface_start
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;


ENTITY FPnormalize IS
GENERIC(
SIG_width : integer := 28
);
PORT(
SIG_in : IN std_logic_vector (SIG_width-1 DOWNTO 0);
EXP_in : IN std_logic_vector (7 DOWNTO 0);
SIG_out : OUT std_logic_vector (SIG_width-1 DOWNTO 0);
EXP_out : OUT std_logic_vector (7 DOWNTO 0)
);

-- Declarations

END FPnormalize ;


-- hds interface_end
ARCHITECTURE FPnormalize OF FPnormalize IS
BEGIN

PROCESS(SIG_in, EXP_in)
BEGIN
IF (SIG_in( SIG_width-1 )='1') THEN
SIG_out <= '0' & SIG_in(SIG_width-1 DOWNTO 2) & (SIG_in(1) AND SIG_in(0));
EXP_out <= EXP_in + 1;
ELSE
SIG_out <= SIG_in;
EXP_out <= EXP_in;
END IF;
END PROCESS;

END FPnormalize;




Trovato qui:
http://opencores.org/project,fpuvhdl

cdimauro
28-11-2015, 20:38
Ma è normale che un moltiplicatore richieda meno risorse di un sommatore? :mbe:

ingframin
29-11-2015, 10:45
Ma è normale che un moltiplicatore richieda meno risorse di un sommatore? :mbe:

Su un FPGA si, perché il moltiplicatore è già implementato nell'hardware dell'FPGA mentre per il sommatore bisgna usare le LUT e le catene dedicate di propagazione del riporto.
Su un ASIC no, un sommatore è più piccolo.

cdimauro
29-11-2015, 16:30
Ma gli FPGA non hanno generalmente moltiplicatori limitati? Tipo massimo 18x18 bit? In questo caso per una moltiplicazione a 32 bit servirebbero 3 moltiplicazioni 18x18 (16 x 16 sarebbero sufficienti) e 3 somme, con conseguente maggior consumo di risorse rispetto a una normale somma.

ingframin
03-12-2015, 15:33
Ma gli FPGA non hanno generalmente moltiplicatori limitati? Tipo massimo 18x18 bit? In questo caso per una moltiplicazione a 32 bit servirebbero 3 moltiplicazioni 18x18 (16 x 16 sarebbero sufficienti) e 3 somme, con conseguente maggior consumo di risorse rispetto a una normale somma.

Non usi altrettante CLB, li sta l'inghippo.
In ogni caso dipende anche dall'FPGA che usi e dal sintetizzatore.
Se provi con Quartus a sintetizzare per diversi modelli vedi risultati diversi.
Già se provi differenti versioni delle cyclone o se confronti cyclone con Stratix mi sa che esce diverso.