UNIVERSITÀ DEGLI STUDI DI UDINE
Facoltà di Ingegneria
Corso di Laurea Specialistica in Ingegneria Gestionale dell’Informazione
Dipartimento di Ingegneria Elettrica, Gestionale e Meccanica
Calcolatori Elettronici
RELAZIONE DISPOSITIVO NFACTOR
Prof. Mirko Loghi
Giovanni Bernardis
Anno Accademico 2010/2011
OGGETTO:
Progettare un dispositivo che, preso come ingresso un numero naturale senza segno, restituisce in
uscita il numero di fattori primi distinti in cui può essere scomposto.
Per la risoluzione del problema saranno presentati quattro algoritmi per i quali è stato sviluppato il
progetto completo (diagramma ASM, schema del datapath, codice VHDL) e con opportuni commenti
si cercherà di spiegare al lettore le scelte fatte.
SPECIFICHE:
Il dispositivo, denominato NFACTOR, deve avere un ingresso dati A da 32 bit e un’uscita dati Q.
All’attivarsi del segnale di ingresso START, il dispositivo riceve su A un numero intero senza segno,
che chiameremo per semplicità N, da 32 bit. Il dispositivo deve determinare e fornire in uscita, sulla
linea dati Q, il numero di fattori primi distinti (e diversi da 1) in cui può essere scomposto il numero N.
Infine, il dispositivo deve segnalare che l’uscita è valida e che si può procedere con una nuova
elaborazione, alzando il segnale di uscita READY. Ovviamente il dispositivo in questione deve avere gli
ingressi per il clock e il reset.
Le condizioni N=0 e N=1 devono essere gestite restituendo come risultato il valore 0.
Inoltre, si ha a disposizione un dispositivo DIVIDER, che usa l’uscita DONE per segnalare di essere
pronto e di avere un risultato valido; il quale legge i numeri ai suoi ingressi OP1 e OP2 da 32 bit e
all’attivarsi del segnale GO, esegue la divisione intera e fornisce il risultato sull’uscita DIV e il resto su
REMAIN. Anche questo dispositivo è dotato dei segnali per il clock e il reset.
Sono richiesti il diagramma ASM (Algorithmic State Machine), lo schema a blocchi del datapath e il
codice VHDL della control-unit, datapath e del top-level.
ALGORITMI:
Prima di procedere con i dettagli risolutivi, si vuole presentare l’idea di base utilizzata per la soluzione.
Com’è solito farsi, per scomporre un numero nei suoi fattori, lo si cerca di dividere prima per 2 fino a
quando si ottiene un resto diverso da 0, poi si prova con il 3, e poi in modo iterativo con i successivi
numeri primi fino a quando il dividendo è uguale a 1 e a quel punto l’algoritmo termina. Ad esempio se
vogliamo scomporre il 40, procederemo con: 40/2 = 20  20/2 = 10  10/2 = 5  5/2= 2 con
resto di 1, quindi proviamo con il 3, 5/3 = 1 con resto di 2, proviamo ancora con il 5, 5/5 = 1, a questo
punto abbiamo finito e troviamo che i due fattori sono 2 e 5, quindi abbiamo 2 fattori distinti come
risultato.
Dopo questa premessa, analizziamo ora i diversi algoritmi utilizzati che si differenziano tra loro solo per
come viene calcolato il nuovo divisore necessario per la divisione.
• ALGORITMO 1:
La prima implementazione consiste nell’utilizzare come divisore tutti i numeri dal 2 in poi: si partirà
dividendo per 2, poi per 3, poi 4, poi 5, ecc., si noti che gli incrementi tra un divisore e quello
successivo sono di un’unità.
Questo metodo è quello di più facile realizzazione, richiede che non appena la divisione ha resto
diverso da zero, il divisore venga incrementato di 1. In questo modo però si compiranno molte
divisioni in cui il risultato sicuramente ha resto non nullo e che quindi si possono evitare; ad esempio se
troviamo il 2 come fattore, tutti i numeri pari, maggiori di 2 saranno già stati presi in considerazione
(poiché sono multipli di 2).
• ALGORITMO 2:
Una seconda strategia è di partire sempre dal 2, il più piccolo numero primo, poi il 3 e poi avanzare con
incrementi di 2, in modo da utilizzare i numeri dispari come fattori, quindi 5, 7, ecc.
Questo algoritmo è sicuramente migliore del primo in quanto consente di risparmiare circa il 50% dei
tentativi (i numeri pari) che sicuramente sarebbero “andati a vuoto”.
• ALGORITMO 3:
Il terzo metodo prevede di utilizzare come divisori la sequenza: 2, 3, 5, 7, 11, 13, 17, 19, ecc. Per passare
al fattore successivo si utilizza la seguente sequenza di operazioni: +1, +2, +2, +4, +2, +4, +2, +4, ecc.
Si noti che dopo i primi due passi la sequenza è periodica, questo tornerà utile in fase di
implementazione.
• ALGORITMO 4:
L’ultimo algoritmo è quello maggiormente ottimizzato ma anche il più complesso; la sequenza di
incrementi è la seguente: +1, +2, +2, +4, +2, +4, +2, +4, +6, +2, +6, +4, +2, +4, +2, +4, +6, +2, +6,
ecc. Anche qui, dopo le prime 3 operazioni si può notare una periodicità di 8 elementi.
Per tutti i casi sopraesposti, si può ridurre notevolmente il tempo di elaborazione considerando che se il
divisore in esame è maggiore di
, il dividendo corrente è primo e quindi è inutile proseguire con la
ricerca.
Questo si può dimostrare considerando un generico numero il quale può essere espresso come:
dove
e
sono due fattori distinti; ipotizzando inoltre che
, intuitivamente ne consegue che
. Ad esempio, se prendiamo
, si ottiene:
√
Com’è noto, il 15 si scompone nei fattori 3 e 5, corrispondenti ai nostri generici
e . Applicando
uno dei precedenti algoritmi, tenteremo di dividere prima per 2, poi per 3 (ottenendo così il primo
fattore e 5 come dividendo); a questo punto il divisore successivo sarebbe il 4, ed essendo maggiore di
3,873 possiamo terminare l’elaborazione sapendo che il dividendo in esame è primo, come infatti risulta
esserlo.
Quindi, quando siamo alla ricerca dei vari fattori, in linea generale, possiamo terminare la ricerca
quando il divisore è maggiore di
Nel nostro specifico caso, operando con numeri da 32 bit, il massimo valore rappresentabile è
,
ne segue che
(√
)
; il valore soglia risulterà essere
e quindi
questo accorgimento ci aiuterà a risparmiare tempo nel caso dovessimo scomporre numeri primi molto
grandi.
È comune a tutti gli algoritmi l’accorgimento che si utilizza per attivare il dispositivo DIVIDER,
necessario ad effettuare il calcolo della divisione intera.
Nel diagramma ASM, in un primo stato si abilita il segnale GO, per far avviare la divisione; in un
secondo stato, invece, solamente si attende che la divisione sia terminata e all’alzarsi del segnale DONE
si procede con le successive elaborazioni.
Attivare il segnale GO e valutare la condizione DONE in un unico stato è un classico errore che si
commette in queste situazioni; analizzando le forme d’onda capiremo meglio questa problematica.
Si osservi che quando ci troviamo nello stato CALC, il segnale GO viene subito attivato ma che anche
il segnale DONE continua a rimanere alto, quindi se lo valutassimo in quell’istante ci troveremmo nella
condizione di poter proseguire con le elaborazioni successive ma staremmo commettendo un errore in
quanto in realtà la divisione è ancora in corso e i risultati forniti alle uscite non sono validi.
Infine si vuol far notare che il registro Q è di soli 4 bit: questo è sufficiente a rappresentare il massimo
numero di fattori distinti possibili avendo in ingresso numeri da 32 bit.
Il massimo numero rappresentabile con 32 bit è:
Ora moltiplicando tra loro i 10 più piccoli numeri primi distinti si ottiene:
Si nota quindi che usando i più piccoli numeri primi distinti disponibili, già con 10 fattori si è ben oltre
il numero massimo rappresentabile con 32 bit. Per rappresentare il 10 in binario sono sufficienti 4 bit e
da questo ne deriva la dimensione del registro Q.
PROGETTO 1:
• ASM:
Nello stato INIT vengono inizializzati i registri ed è lo stato in cui ci si trova quando si è pronti per una
nuova elaborazione e si ha un risultato pronto. All’attivarsi del segnale START ha inizio l’elaborazione
vera e propria e si entra in un ciclo while che viene terminato quando il divisore è maggiore di
o
quando il dividendo è minore o uguale a 1. All’interno del ciclo viene attivato il segnale GO per avviare
la divisione, al termine della quale viene valutato il resto e in base a quest’ultimo si decide se ripetere la
divisione con lo stesso divisore o se incrementare il divisore; inoltre c’è un contatore che viene
incrementato ogni volta che viene individuato un nuovo fattore primo.
• DATAPATH:
Tutti i registri sono abilitati dal segnale LOAD, in X si trova il dividendo corrente, che all’inizio è
uguale al numero in ingresso e poi diventa il quoziente delle divisioni quando queste sono prive di
resto; in OLD c’è l’ultimo fattore valido trovato, che confrontato con il divisore corrente, ci dà la
possibilità di individuare i fattori distinti; Q è il contatore del numero di fattori primi distinti ed è
direttamente collegato all’uscita del dispositivo.
Ad ogni registro è associato un multiplexer, necessario per le varie inizializzazioni.
Troviamo diversi comparatori che ci forniscono i segnali di ingresso alla control unit.
Inoltre è presente un sommatore il cui compito è di incrementare il divisore di 1, in modo da provare
tutti i fattori dal 2 in poi.
• VHDL:
La control unit presenta un processo che regola la macchina a stati derivante dallo schema ASM e la
descrizione comportamentale dei segnali di uscita diretti al datapath, tra i quali si trovano i vari selettori
per i multiplexer.
Il codice completo di toplevel, ctrlunit e datapath si trova nell’APPENDICE 1.
PROGETTO 2:
• ASM:
In questo secondo caso il diagramma ASM è molto simile al primo, in quanto l’algoritmo è quasi lo
stesso; l’unica differenza è dovuta all’introduzione di una variabile chiamata SOM, che assumendo i
valori 1 o 2 consente l’utilizzo di tutti i fattori dispari dopo il 2 come divisore.
• DATAPATH:
Come appena accennato, rispetto a prima, si tratta di trovare un sistema per sommare al divisore prima
1 e poi sempre 2. Questo è stato fatto adottando un registro chiamato SOM, collegato al sommatore del
divisore; tramite un multiplexer comandato da opportuni segnali della control unit, il registro SOM
assume prima il valore numerico 1 e poi sempre 2 fino ad una nuova elaborazione.
• VHDL:
La FSM della control unit è identica, sono solamente stati aggiunti i segnali di LOAD e di selezione per
il registro SOM.
Anche il datapath sostanzialmente è lo stesso.
Il codice è disponibile nell’APPENDICE 2.
PROGETTO 3:
• ASM:
Questo algoritmo prevede una sequenza di incrementi che dopo i primi 2 passi diventa periodica con
periodo 2. Per la gestione della parte periodica da quella non periodica, è stata introdotta una decision
box la cui condizione dipende da un contatore, chiamato FLAG, che non fa altro che segnalare se si è
nel primo, secondo o seguenti passi. I vari incrementi vengono generati dalla cascata di 2 multiplexer
pilotati rispettivamente dai segnali FLAG e CNT, quindi il segnale OUT_MUX = FLAG, CNT .
Il resto dell’algoritmo è lo stesso e quindi non ci sono sostanziali differenze per quanto riguarda l’ASM,
a parte alcune inizializzazioni aggiunte allo stato INIT dovute all’introduzione di nuove variabili
precedentemente inesistenti.
• DATAPATH:
Viene modificata la parte che riguarda gli incrementi del divisore, ora al sommatore è collegato il
segnale OUT_MUX, frutto della cascata di 2 multiplexer: MUX_1 e MUX_2; il primo è controllato dal
segnale di selezione SEL_1, il quale è direttamente collegato al registro FLAG e quindi gestisce la parte
periodica da quella non periodica, il secondo multiplexer interviene solo per la parte periodica degli
incrementi e il segnale di controllo è collegato ad un registro a 1 bit (il periodo è 2) chiamato CNT.
Gli incrementi del registro FLAG, in un primo momento erano gestiti da un sommatore e da un
multiplexer usato per l’inizializzazione; poi è stato eliminato il sommatore e tutto viene gestito tramite il
multiplexer. Anche gli incrementi del contatore CNT, inizialmente utilizzavano un sommatore, ma
essendo un registro a 1 bit, è sufficiente una porta NOT.
• VHDL:
L’aggiunta della decision box e dei registri FLAG e CNT porta ad un incremento dei segnali di
controllo da e verso la control unit: ci sono sia i LOAD per i registri e i segnali SEL per i multiplexer a
loro collegati, sia un bus a 2 bit con lo stato del FLAG, utile per la decision box che è stata appena
introdotta.
I dettagli del codice sono disponibili nell’APPENDICE 3.
PROGETTO 4:
• ASM:
L’ultimo algoritmo, per com’è strutturato, è abbastanza simile al precedente e quindi anche nell’ASM
non ci sono grosse differenze; c’è sempre una sequenza di incrementi che dopo 3 passi diventa
periodica e questo è stato gestito in maniera analoga a prima, con l’uso delle variabili FLAG e CNT.
Anche qui si utilizza il segnale OUT_MUX, che in funzione di FLAG e CNT fornisce in uscite la
sequenza di incrementi che andrà a sommarsi al divisore.
• DATAPATH:
Come anticipato, gli incrementi del divisore vengono gestiti da 2 multiplexer in cascata e anche il FLAG
è sempre gestito dal solo multiplexer, consentendoci quindi di risparmiare un sommatore.
Il contatore CNT questa volta è di 3 bit (
, come il periodo) e quindi abbiamo dovuto usare un
sommatore: partendo dal valore binario “000”, una volta raggiunto il valore binario “111”, un’ulteriore
somma porterebbe a “1000” come risultato ma a causa dell’overflow, nel registro viene scritto il valore
“000”; da qui nasce la ciclicità che permette di avere una periodicità con periodo 8.
• VHDL:
E’ stato modificato il MUX_2, avendo ora 8 ingressi a 32 bit e un bus a 3 bit per la selezione, sempre
collegato al CNT.
Tutto il codice si trova nell’APPENDICE 4.
SIMULAZIONI E RISULTATI:
Una volta completati ctrlunit e datapath, si passa alla descrizione strutturale del top level dove i blocchi
componenti vengono collegati tra loro. Successivamente è necessario compilare i file e correggere
eventuali errori.
Una volta terminata questa fase, utilizzando un apposito testbench, che non è altro che un dispositivo
dotato di generatore di reset, generatore di clock e generatore di ingressi, si simula ed analizza il
comportamento del DUT (device under test) che nel caso specifico è il top level per i vari algoritmi.
Nel nostro caso il testbench ha un clock con semiperiodo al livello logico 0 pari a 6ns e semiperiodo a
livello alto pari a 5ns; il reset invece è un impulso dalla durata di 29ns che viene attivato 1ns dopo
l’avvio della simulazione mentre i dati in ingresso corrispondono alla seguente sequenza di numeri:
15, 0, 25, 1, 40, 99, 24, 1764, 2147483647 e 2147483244
La simulazione termina quando tutti i numeri vengono elaborati e quindi una metrica per confrontare
gli algoritmi è la valutazione del tempo totale impiegato.
Vengono ora riportati i risultati delle simulazioni:
Algoritmo1: 51923146 ns
Algoritmo2: 25968118 ns
Algoritmo3: 17317498 ns
Algoritmo4: 13858042 ns
Osservando i dati si nota un trend monotono decrescente a significare l’efficacia progressiva degli
algoritmi.
Il secondo algoritmo impiega approssimativamente metà tempo rispetto al primo e questo è dovuto al
fatto che vengono utilizzati circa la metà dei tentativi, i numeri dispari invece della prova di tutti i
numeri come divisore.
Nel terzo algoritmo, preso un intervallo di incrementi pari a +6, vengono effettuati solo 2 tentativi (visti
gli incrementi +2 e +4) contro i 6 del primo metodo, infatti anche i dati sperimentali confermano che
impiega circa un terzo del tempo.
Con un ragionamento analogo, si scopre che il quarto algoritmo dovrebbe impiegare circa il ⁄
̅ di tempo rispetto al primo tentativo; 8 deriva dalla periodicità con periodo di 8 elementi mentre il
30 deriva dalla somma degli incrementi
. Utilizzando i dati
sperimentali otteniamo
⁄
; quindi con buona approssimazione
possiamo affermare che ancora una volta i dati confermano l’analisi.
APPENDICE 1:
• NFACTOR1.VHDL
library ieee;
use ieee.std_logic_1164.all;
package nfactor_pkg is
component nfactor is
port (
CLK, RESET : in std_logic;
-- data inputs
A : in std_logic_vector(31 downto 0);
-- data outputs
Q : out std_logic_vector(3 downto 0);
-- control signals
START : in std_logic;
-- status signals
READY : out std_logic
);
end component;
end nfactor_pkg;
---------------------------------------------------------------------library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.divider_behav_pkg.all;
entity nfactor is
port (
CLK, RESET : in std_logic;
-- data inputs
A : in std_logic_vector(31 downto 0);
-- data outputs
Q : out std_logic_vector(3 downto 0);
-- control signals
START : in std_logic;
-- status signals
READY : out std_logic
);
end nfactor;
architecture struct of nfactor is
component nfactor1_ctrlunit is
port (start, CLK, RST: in std_logic;
ready: out std_logic;
load_x, load_d, load_o, load_q: out std_logic;
sel_x, sel_d, sel_o, sel_q: out std_logic;
div_go: out std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: in std_logic);
end component;
component nfactor1_datapath is
port (CLK, RST, load_x, load_d, load_o, load_q: in std_logic;
sel_x, sel_d, sel_o, sel_q, div_go: in std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: out std_logic;
A: in std_logic_vector (31 downto 0);
Q: out std_logic_vector (3 downto 0));
end component;
signal load_x, load_d, load_o, load_q, sel_x, sel_d, sel_o, sel_q: std_logic;
signal Xmin1, DmagMAX, DeqO, restozero, div_go, div_done: std_logic;
begin
CU: nfactor1_ctrlunit
port map (START, CLK, RESET, READY, load_x, load_d, load_o, load_q,
sel_x, sel_d, sel_o, sel_q, div_go, Xmin1, DmagMAX, DeqO, restozero, div_done);
DP: nfactor1_datapath
port map (CLK, RESET, load_x, load_d, load_o, load_q, sel_x, sel_d, sel_o, sel_q, div_go,
Xmin1, DmagMAX, DeqO, restozero, div_done, A, Q);
end struct;
----------------------------------------------------------------------
• NFACTOR1_CTRLUNIT.VHDL
library ieee;
use ieee.std_logic_1164.all;
entity nfactor1_ctrlunit is
port (start, CLK, RST: in std_logic;
ready: out std_logic;
load_x, load_d, load_o, load_q: out std_logic;
sel_x, sel_d, sel_o, sel_q: out std_logic;
div_go: out std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: in std_logic);
end nfactor1_ctrlunit;
architecture arch of nfactor1_ctrlunit is
type state is (INIT, WAIT_DIV, CALC, FIN);
signal NextState, PresState: state;
begin
update_state: process(CLK, RST)
begin
if RST = '1' then
PresState<=INIT;
elsif CLK'event AND CLK='1' then
PresState<=NextState;
end if;
end process;
FSM: process (presstate, start, Xmin1, DmagMAX, DeqO, restozero, div_done)
begin
case presstate is
when INIT =>
if start = '0' then nextstate <= INIT;
else nextstate <= FIN;
end if;
when FIN =>
if DmagMAX = '1' then nextstate <= INIT;
elsif Xmin1 = '1' then nextstate <= INIT;
else nextstate <= CALC;
end if;
when CALC =>
nextstate <= WAIT_DIV;
when WAIT_DIV =>
if div_done = '0' then nextstate <= WAIT_DIV;
else nextstate <= FIN;
end if;
end case;
end process;
ready <= '1' when presstate=INIT else '0';
load_x <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='1') else '0';
sel_x <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='1';
load_d <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='0') else '0';
sel_d <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='0';
load_o <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='1' and DeqO='0') else
'0';
sel_o <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='1' and DeqO='0';
load_q <= '1' when (presstate=INIT and start='1') or (presstate=FIN and DmagMAX='1') or (presstate=WAIT_DIV
and div_done='1' and restozero='1' and DeqO='0') else '0';
sel_q <= '0' when (presstate=INIT and start='1') else
'1' when (presstate=FIN and DmagMAX='1') or (presstate=WAIT_DIV and div_done='1' and restozero='1' and
DeqO='0');
div_go <= '1' when presstate=CALC else '0';
end arch;
• NFACTOR1_DATAPATH.VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.divider_behav_pkg.all;
entity nfactor1_datapath is
port (CLK, RST, load_x, load_d, load_o, load_q: in std_logic;
sel_x, sel_d, sel_o, sel_q, div_go: in std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: out std_logic;
A: in std_logic_vector (31 downto 0);
Q: out std_logic_vector (3 downto 0));
end nfactor1_datapath;
architecture arch of nfactor1_datapath is
signal x, d, o, mux_x, mux_d, mux_o, out_div, out_rem: std_logic_vector (31 downto 0);
signal q_reg, mux_q: std_logic_vector (3 downto 0);
begin
DIV : divider
port map (
CLK => CLK, RESET => RST,
OP1 => X, OP2 => D,
DIV => out_div, REMAIN => out_rem,
START => div_go,
READY => div_done
);
x <= (others=>'0') when RST='1' else
mux_x when CLK'event and CLK='1' and load_x='1';
d <= (others=>'0') when RST='1' else
mux_d when CLK'event and CLK='1' and load_d='1';
o <= (others=>'0') when RST='1' else
mux_o when CLK'event and CLK='1' and load_o='1';
q_reg <= (others=>'0') when RST='1' else
mux_q when CLK'event and CLK='1' and load_q='1';
q <= q_reg;
mux_x <= A when sel_x='0' else out_div;
mux_d <= std_logic_vector(to_unsigned(2,32)) when sel_d='0' else std_logic_vector(unsigned(d)+1);
mux_o <= (others=>'0') when sel_o='0' else d;
mux_q <= (others=>'0') when sel_q='0' else std_logic_vector(unsigned(q_reg)+1);
Xmin1 <= '1' when unsigned(x) <= 1 else '0';
DmagMAX <= '1' when unsigned(d) > 2**16 else '0';
DeqO <= '1' when unsigned(d) = unsigned(o) else '0';
restozero <= '1' when unsigned(out_rem) = 0 else '0';
end arch;
APPENDICE 2:
• NFACTOR2.VHDL
library ieee;
use ieee.std_logic_1164.all;
package nfactor_pkg is
component nfactor is
port (
CLK, RESET : in std_logic;
-- data inputs
A : in std_logic_vector(31 downto 0);
-- data outputs
Q : out std_logic_vector(3 downto 0);
-- control signals
START : in std_logic;
-- status signals
READY : out std_logic
);
end component;
end nfactor_pkg;
---------------------------------------------------------------------library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.divider_behav_pkg.all;
entity nfactor is
port (
CLK, RESET : in std_logic;
-- data inputs
A : in std_logic_vector(31 downto 0);
-- data outputs
Q : out std_logic_vector(3 downto 0);
-- control signals
START : in std_logic;
-- status signals
READY : out std_logic
);
end nfactor;
architecture struct of nfactor is
component nfactor2_ctrlunit is
port (start, CLK, RST: in std_logic;
ready: out std_logic;
load_x, load_d, load_o, load_q, load_som: out std_logic;
sel_x, sel_d, sel_o, sel_q, sel_som: out std_logic;
div_go: out std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: in std_logic);
end component;
component nfactor2_datapath is
port (CLK, RST, load_x, load_d, load_o, load_q, load_som: in std_logic;
sel_x, sel_d, sel_o, sel_q, sel_som, div_go: in std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: out std_logic;
A: in std_logic_vector (31 downto 0);
Q: out std_logic_vector (3 downto 0));
end component;
signal load_x, load_d, load_o, load_q, load_som, sel_x, sel_d, sel_o, sel_q, sel_som: std_logic;
signal Xmin1, DmagMAX, DeqO, restozero, div_go, div_done: std_logic;
begin
CU: nfactor2_ctrlunit
port map (START, CLK, RESET, READY, load_x, load_d, load_o, load_q, load_som,
sel_x, sel_d, sel_o, sel_q, sel_som, div_go, Xmin1, DmagMAX, DeqO, restozero, div_done);
DP: nfactor2_datapath
port map (CLK, RESET, load_x, load_d, load_o, load_q, load_som, sel_x, sel_d, sel_o, sel_q, sel_som, div_go,
Xmin1, DmagMAX, DeqO, restozero, div_done, A, Q);
end struct;
----------------------------------------------------------------------
• NFACTOR2_CTRLUNIT.VHDL
library ieee;
use ieee.std_logic_1164.all;
entity nfactor2_ctrlunit is
port (start, CLK, RST: in std_logic;
ready: out std_logic;
load_x, load_d, load_o, load_q, load_som: out std_logic;
sel_x, sel_d, sel_o, sel_q, sel_som: out std_logic;
div_go: out std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: in std_logic);
end nfactor2_ctrlunit;
architecture arch of nfactor2_ctrlunit is
type state is (INIT, WAIT_DIV, CALC, FIN);
signal NextState, PresState: state;
begin
update_state: process(CLK, RST)
begin
if RST = '1' then
PresState<=INIT;
elsif CLK'event AND CLK='1' then
PresState<=NextState;
end if;
end process;
FSM: process (presstate, start, Xmin1, DmagMAX, DeqO, restozero, div_done)
begin
case presstate is
when INIT =>
if start = '0' then nextstate <= INIT;
else nextstate <= FIN;
end if;
when FIN =>
if DmagMAX = '1' then nextstate <= INIT;
elsif Xmin1 = '1' then nextstate <= INIT;
else nextstate <= CALC;
end if;
when CALC =>
nextstate <= WAIT_DIV;
when WAIT_DIV =>
if div_done = '0' then nextstate <= WAIT_DIV;
else nextstate <= FIN;
end if;
end case;
end process;
ready <= '1' when presstate=INIT else '0';
load_x <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='1') else '0';
sel_x <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='1';
load_d <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='0') else '0';
sel_d <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='0';
load_o <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='1' and DeqO='0') else
'0';
sel_o <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='1' and DeqO='0';
load_q <= '1' when (presstate=INIT and start='1') or (presstate=FIN and DmagMAX='1') or (presstate=WAIT_DIV
and div_done='1' and restozero='1' and DeqO='0') else '0';
sel_q <= '0' when (presstate=INIT and start='1') else
'1' when (presstate=FIN and DmagMAX='1') or (presstate=WAIT_DIV and div_done='1' and restozero='1' and
DeqO='0');
load_som <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='0') else '0';
sel_som <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='0';
div_go <= '1' when presstate=CALC else '0';
end arch;
• NFACTOR2_DATAPATH.VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.divider_behav_pkg.all;
entity nfactor2_datapath is
port (CLK, RST, load_x, load_d, load_o, load_q, load_som: in std_logic;
sel_x, sel_d, sel_o, sel_q, sel_som, div_go: in std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: out std_logic;
A: in std_logic_vector (31 downto 0);
Q: out std_logic_vector (3 downto 0));
end nfactor2_datapath;
architecture arch of nfactor2_datapath is
signal x, d, o, som, mux_x, mux_d, mux_o, mux_som, out_div, out_rem: std_logic_vector (31 downto 0);
signal q_reg, mux_q: std_logic_vector (3 downto 0);
begin
DIV : divider
port map (
CLK => CLK, RESET => RST,
OP1 => X, OP2 => D,
DIV => out_div, REMAIN => out_rem,
START => div_go,
READY => div_done
);
x <= (others=>'0') when RST='1' else
mux_x when CLK'event and CLK='1' and load_x='1';
d <= (others=>'0') when RST='1' else
mux_d when CLK'event and CLK='1' and load_d='1';
o <= (others=>'0') when RST='1' else
mux_o when CLK'event and CLK='1' and load_o='1';
som <= (others=>'0') when RST='1' else
mux_som when CLK'event and CLK='1' and load_som='1';
q_reg <= (others=>'0') when RST='1' else
mux_q when CLK'event and CLK='1' and load_q='1';
q <= q_reg;
mux_x <= A when sel_x='0' else out_div;
mux_d <= std_logic_vector(to_unsigned(2,32)) when sel_d='0' else std_logic_vector(unsigned(d)+unsigned(som));
mux_o <= (others=>'0') when sel_o='0' else d;
mux_q <= (others=>'0') when sel_q='0' else std_logic_vector(unsigned(q_reg)+1);
mux_som <= std_logic_vector(to_unsigned(1,32)) when sel_som='0' else std_logic_vector(to_unsigned(2,32));
Xmin1 <= '1' when unsigned(x) <= 1 else '0';
DmagMAX <= '1' when unsigned(d) > 2**16 else '0';
DeqO <= '1' when unsigned(d) = unsigned(o) else '0';
restozero <= '1' when unsigned(out_rem) = 0 else '0';
end arch;
APPENDICE 3:
• NFACTOR3.VHDL
library ieee;
use ieee.std_logic_1164.all;
package nfactor_pkg is
component nfactor is
port (
CLK, RESET : in std_logic;
-- data inputs
A : in std_logic_vector(31 downto 0);
-- data outputs
Q : out std_logic_vector(3 downto 0);
-- control signals
START : in std_logic;
-- status signals
READY : out std_logic
);
end component;
end nfactor_pkg;
---------------------------------------------------------------------library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.divider_behav_pkg.all;
entity nfactor is
port (
CLK, RESET : in std_logic;
-- data inputs
A : in std_logic_vector(31 downto 0);
-- data outputs
Q : out std_logic_vector(3 downto 0);
-- control signals
START : in std_logic;
-- status signals
READY : out std_logic
);
end nfactor;
architecture struct of nfactor is
component nfactor3_ctrlunit is
port (start, CLK, RST: in std_logic;
ready: out std_logic;
load_x, load_d, load_o, load_q, load_flag, load_cnt: out std_logic;
sel_x, sel_d, sel_o, sel_q, sel_cnt: out std_logic;
flag: in std_logic_vector (1 downto 0);
sel_flag: out std_logic_vector (1 downto 0);
div_go: out std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: in std_logic);
end component;
component nfactor3_datapath is
port (CLK, RST, load_x, load_d, load_o, load_q, load_flag, load_cnt: in std_logic;
sel_x, sel_d, sel_o, sel_q, sel_cnt, div_go: in std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: out std_logic;
sel_flag: in std_logic_vector (1 downto 0);
flag: out std_logic_vector (1 downto 0);
A: in std_logic_vector (31 downto 0);
Q: out std_logic_vector (3 downto 0));
end component;
signal load_x, load_d, load_o, load_q, load_flag, load_cnt: std_logic;
signal sel_x, sel_d, sel_o, sel_q, sel_cnt: std_logic;
signal flag, sel_flag: std_logic_vector (1 downto 0);
signal Xmin1, DmagMAX, DeqO, restozero, div_go, div_done: std_logic;
begin
CU: nfactor3_ctrlunit
port map (START, CLK, RESET, READY, load_x, load_d, load_o, load_q, load_flag, load_cnt,
sel_x, sel_d, sel_o, sel_q, sel_cnt, flag, sel_flag,
div_go, Xmin1, DmagMAX, DeqO, restozero, div_done);
DP: nfactor3_datapath
port map (CLK, RESET, load_x, load_d, load_o, load_q, load_flag, load_cnt,
sel_x, sel_d, sel_o, sel_q, sel_cnt, div_go,
Xmin1, DmagMAX, DeqO, restozero, div_done, sel_flag, flag, A, Q);
end struct;
----------------------------------------------------------------------
• NFACTOR3_CTRLUNIT.VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity nfactor3_ctrlunit is
port (start, CLK, RST: in std_logic;
ready: out std_logic;
load_x, load_d, load_o, load_q, load_flag, load_cnt: out std_logic;
sel_x, sel_d, sel_o, sel_q, sel_cnt: out std_logic;
flag: in std_logic_vector (1 downto 0);
sel_flag: out std_logic_vector (1 downto 0);
div_go: out std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: in std_logic);
end nfactor3_ctrlunit;
architecture arch of nfactor3_ctrlunit is
type state is (INIT, WAIT_DIV, CALC, FIN);
signal NextState, PresState: state;
begin
update_state: process(CLK, RST)
begin
if RST = '1' then
PresState<=INIT;
elsif CLK'event AND CLK='1' then
PresState<=NextState;
end if;
end process;
FSM: process (presstate, start, Xmin1, DmagMAX, DeqO, restozero, div_done)
begin
case presstate is
when INIT =>
if start = '0' then nextstate <= INIT;
else nextstate <= FIN;
end if;
when FIN =>
if DmagMAX = '1' then nextstate <= INIT;
elsif Xmin1 = '1' then nextstate <= INIT;
else nextstate <= CALC;
end if;
when CALC =>
nextstate <= WAIT_DIV;
when WAIT_DIV =>
if div_done = '0' then nextstate <= WAIT_DIV;
else nextstate <= FIN;
end if;
end case;
end process;
ready <= '1' when presstate=INIT else '0';
load_x <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='1') else '0';
sel_x <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='1';
load_d <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='0') else '0';
sel_d <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='0';
load_o <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='1' and DeqO='0') else
'0';
sel_o <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='1' and DeqO='0';
load_q <= '1' when (presstate=INIT and start='1') or (presstate=FIN and DmagMAX='1') or (presstate=WAIT_DIV
and div_done='1' and restozero='1' and DeqO='0') else '0';
sel_q <= '0' when (presstate=INIT and start='1') else
'1' when (presstate=FIN and DmagMAX='1') or (presstate=WAIT_DIV and div_done='1' and restozero='1' and
DeqO='0');
load_flag <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='0' and
unsigned(flag)<=1) else '0';
sel_flag <= "00" when presstate=INIT else
"01" when presstate=WAIT_DIV and div_done='1' and restozero='0' and flag="00" else
"10" when presstate=WAIT_DIV and div_done='1' and restozero='0' and flag="01";
load_cnt <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='0' and flag="10") else
'0';
sel_cnt <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='0' and flag="10";
div_go <= '1' when presstate=CALC else '0';
end arch;
• NFACTOR3_DATAPATH.VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.divider_behav_pkg.all;
entity nfactor3_datapath is
port (CLK, RST, load_x, load_d, load_o, load_q, load_flag, load_cnt: in std_logic;
sel_x, sel_d, sel_o, sel_q, sel_cnt, div_go: in std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: out std_logic;
sel_flag: in std_logic_vector (1 downto 0);
flag: out std_logic_vector (1 downto 0);
A: in std_logic_vector (31 downto 0);
Q: out std_logic_vector (3 downto 0));
end nfactor3_datapath;
architecture arch of nfactor3_datapath is
signal x, d, o, mux_x, mux_d, mux_o, out_div, out_rem, mux_1, mux_2: std_logic_vector (31 downto 0);
signal q_reg, mux_q: std_logic_vector (3 downto 0);
signal flag_reg, sel_1, mux_flag: std_logic_vector (1 downto 0);
signal cnt, mux_cnt, sel_2: std_logic;
begin
DIV : divider
port map (
CLK => CLK, RESET => RST,
OP1 => X, OP2 => D,
DIV => out_div, REMAIN => out_rem,
START => div_go,
READY => div_done
);
x <= (others=>'0') when RST='1' else
mux_x when CLK'event and CLK='1' and load_x='1';
d <= (others=>'0') when RST='1' else
mux_d when CLK'event and CLK='1' and load_d='1';
o <= (others=>'0') when RST='1' else
mux_o when CLK'event and CLK='1' and load_o='1';
flag_reg <= (others=>'0') when RST='1' else
mux_flag when CLK'event and CLK='1' and load_flag='1';
flag <= flag_reg;
sel_1 <= flag_reg;
cnt <= '0' when RST='1' else
mux_cnt when CLK'event and CLK='1' and load_cnt='1';
sel_2 <= cnt;
q_reg <= (others=>'0') when RST='1' else
mux_q when CLK'event and CLK='1' and load_q='1';
q <= q_reg;
mux_x <= A when sel_x='0' else out_div;
mux_d <= std_logic_vector(to_unsigned(2,32)) when sel_d='0' else std_logic_vector(unsigned(d)+unsigned(mux_1));
mux_o <= (others=>'0') when sel_o='0' else d;
mux_q <= (others=>'0') when sel_q='0' else std_logic_vector(unsigned(q_reg)+1);
mux_1 <= std_logic_vector(to_unsigned(1,32)) when sel_1="00" else
std_logic_vector(to_unsigned(2,32)) when sel_1="01" else mux_2;
mux_2 <= std_logic_vector(to_unsigned(2,32)) when sel_2='0' else
std_logic_vector(to_unsigned(4,32));
mux_flag <= "00" when sel_flag="00" else
"01" when sel_flag="01" else
"10" when sel_flag="10";
mux_cnt <= '0' when sel_cnt='0' else not cnt;
Xmin1 <= '1' when unsigned(x) <= 1 else '0';
DmagMAX <= '1' when unsigned(d) > 2**16 else '0';
DeqO <= '1' when unsigned(d) = unsigned(o) else '0';
restozero <= '1' when unsigned(out_rem) = 0 else '0';
end arch;
APPENDICE 4:
• NFACTOR4.VHDL
library ieee;
use ieee.std_logic_1164.all;
package nfactor_pkg is
component nfactor is
port (
CLK, RESET : in std_logic;
-- data inputs
A : in std_logic_vector(31 downto 0);
-- data outputs
Q : out std_logic_vector(3 downto 0);
-- control signals
START : in std_logic;
-- status signals
READY : out std_logic
);
end component;
end nfactor_pkg;
---------------------------------------------------------------------library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.divider_behav_pkg.all;
entity nfactor is
port (
CLK, RESET : in std_logic;
-- data inputs
A : in std_logic_vector(31 downto 0);
-- data outputs
Q : out std_logic_vector(3 downto 0);
-- control signals
START : in std_logic;
-- status signals
READY : out std_logic
);
end nfactor;
architecture struct of nfactor is
component nfactor4_ctrlunit is
port (start, CLK, RST: in std_logic;
ready: out std_logic;
load_x, load_d, load_o, load_q, load_flag, load_cnt: out std_logic;
sel_x, sel_d, sel_o, sel_q, sel_cnt: out std_logic;
flag: in std_logic_vector (1 downto 0);
sel_flag: out std_logic_vector (1 downto 0);
div_go: out std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: in std_logic);
end component;
component nfactor4_datapath is
port (CLK, RST, load_x, load_d, load_o, load_q, load_flag, load_cnt: in std_logic;
sel_x, sel_d, sel_o, sel_q, sel_cnt, div_go: in std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: out std_logic;
sel_flag: in std_logic_vector (1 downto 0);
flag: out std_logic_vector (1 downto 0);
A: in std_logic_vector (31 downto 0);
Q: out std_logic_vector (3 downto 0));
end component;
signal load_x, load_d, load_o, load_q, load_flag, load_cnt: std_logic;
signal sel_x, sel_d, sel_o, sel_q, sel_cnt: std_logic;
signal flag, sel_flag: std_logic_vector (1 downto 0);
signal Xmin1, DmagMAX, DeqO, restozero, div_go, div_done: std_logic;
begin
CU: nfactor4_ctrlunit
port map (START, CLK, RESET, READY, load_x, load_d, load_o, load_q, load_flag, load_cnt,
sel_x, sel_d, sel_o, sel_q, sel_cnt, flag, sel_flag,
div_go, Xmin1, DmagMAX, DeqO, restozero, div_done);
DP: nfactor4_datapath
port map (CLK, RESET, load_x, load_d, load_o, load_q, load_flag, load_cnt,
sel_x, sel_d, sel_o, sel_q, sel_cnt, div_go,
Xmin1, DmagMAX, DeqO, restozero, div_done, sel_flag, flag, A, Q);
end struct;
----------------------------------------------------------------------
• NFACTOR4_CTRLUNIT.VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity nfactor4_ctrlunit is
port (start, CLK, RST: in std_logic;
ready: out std_logic;
load_x, load_d, load_o, load_q, load_flag, load_cnt: out std_logic;
sel_x, sel_d, sel_o, sel_q, sel_cnt: out std_logic;
flag: in std_logic_vector (1 downto 0);
sel_flag: out std_logic_vector (1 downto 0);
div_go: out std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: in std_logic);
end nfactor4_ctrlunit;
architecture arch of nfactor4_ctrlunit is
type state is (INIT, WAIT_DIV, CALC, FIN);
signal NextState, PresState: state;
begin
update_state: process(CLK, RST)
begin
if RST = '1' then
PresState<=INIT;
elsif CLK'event AND CLK='1' then
PresState<=NextState;
end if;
end process;
FSM: process (presstate, start, Xmin1, DmagMAX, DeqO, restozero, div_done)
begin
case presstate is
when INIT =>
if start = '0' then nextstate <= INIT;
else nextstate <= FIN;
end if;
when FIN =>
if DmagMAX = '1' then nextstate <= INIT;
elsif Xmin1 = '1' then nextstate <= INIT;
else nextstate <= CALC;
end if;
when CALC =>
nextstate <= WAIT_DIV;
when WAIT_DIV =>
if div_done = '0' then nextstate <= WAIT_DIV;
else nextstate <= FIN;
end if;
end case;
end process;
ready <= '1' when presstate=INIT else '0';
load_x <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='1') else '0';
sel_x <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='1';
load_d <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='0') else '0';
sel_d <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='0';
load_o <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='1' and DeqO='0') else
'0';
sel_o <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='1' and DeqO='0';
load_q <= '1' when (presstate=INIT and start='1') or (presstate=FIN and DmagMAX='1') or (presstate=WAIT_DIV
and div_done='1' and restozero='1' and DeqO='0') else '0';
sel_q <= '0' when (presstate=INIT and start='1') else
'1' when (presstate=FIN and DmagMAX='1') or (presstate=WAIT_DIV and div_done='1' and restozero='1' and
DeqO='0');
load_flag <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='0' and
unsigned(flag)<=2) else '0';
sel_flag <= "00" when presstate=INIT else
"01" when presstate=WAIT_DIV and div_done='1' and restozero='0' and flag="00" else
"10" when presstate=WAIT_DIV and div_done='1' and restozero='0' and flag="01" else
"11" when presstate=WAIT_DIV and div_done='1' and restozero='0' and flag="10";
load_cnt <= '1' when presstate=INIT or (presstate=WAIT_DIV and div_done='1' and restozero='0' and flag="11") else
'0';
sel_cnt <= '0' when presstate=INIT else
'1' when presstate=WAIT_DIV and div_done='1' and restozero='0' and flag="11";
div_go <= '1' when presstate=CALC else '0';
end arch;
• NFACTOR4_DATAPATH.VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.divider_behav_pkg.all;
entity nfactor4_datapath is
port (CLK, RST, load_x, load_d, load_o, load_q, load_flag, load_cnt: in std_logic;
sel_x, sel_d, sel_o, sel_q, sel_cnt, div_go: in std_logic;
Xmin1, DmagMAX, DeqO, restozero, div_done: out std_logic;
sel_flag: in std_logic_vector (1 downto 0);
flag: out std_logic_vector (1 downto 0);
A: in std_logic_vector (31 downto 0);
Q: out std_logic_vector (3 downto 0));
end nfactor4_datapath;
architecture arch of nfactor4_datapath is
signal x, d, o, mux_x, mux_d, mux_o, out_div, out_rem, mux_1, mux_2: std_logic_vector (31 downto 0);
signal q_reg, mux_q: std_logic_vector (3 downto 0);
signal flag_reg, sel_1, mux_flag: std_logic_vector (1 downto 0);
signal cnt, mux_cnt, sel_2: std_logic_vector (2 downto 0);
begin
DIV : divider
port map (
CLK => CLK, RESET => RST,
OP1 => X, OP2 => D,
DIV => out_div, REMAIN => out_rem,
START => div_go,
READY => div_done
);
x <= (others=>'0') when RST='1' else
mux_x when CLK'event and CLK='1' and load_x='1';
d <= (others=>'0') when RST='1' else
mux_d when CLK'event and CLK='1' and load_d='1';
o <= (others=>'0') when RST='1' else
mux_o when CLK'event and CLK='1' and load_o='1';
flag_reg <= (others=>'0') when RST='1' else
mux_flag when CLK'event and CLK='1' and load_flag='1';
flag <= flag_reg;
sel_1 <= flag_reg;
cnt <= (others=>'0') when RST='1' else
mux_cnt when CLK'event and CLK='1' and load_cnt='1';
sel_2 <= cnt;
q_reg <= (others=>'0') when RST='1' else
mux_q when CLK'event and CLK='1' and load_q='1';
q <= q_reg;
mux_x <= A when sel_x='0' else out_div;
mux_d <= std_logic_vector(to_unsigned(2,32)) when sel_d='0' else std_logic_vector(unsigned(d)+unsigned(mux_1));
mux_o <= (others=>'0') when sel_o='0' else d;
mux_q <= (others=>'0') when sel_q='0' else std_logic_vector(unsigned(q_reg)+1);
mux_1 <= std_logic_vector(to_unsigned(1,32)) when sel_1="00" else
std_logic_vector(to_unsigned(2,32)) when sel_1="01" else
std_logic_vector(to_unsigned(2,32)) when sel_1="10" else mux_2;
mux_2 <= std_logic_vector(to_unsigned(4,32)) when sel_2="000" else
std_logic_vector(to_unsigned(2,32)) when sel_2="001" else
std_logic_vector(to_unsigned(4,32)) when sel_2="010" else
std_logic_vector(to_unsigned(2,32)) when sel_2="011" else
std_logic_vector(to_unsigned(4,32)) when sel_2="100" else
std_logic_vector(to_unsigned(6,32)) when sel_2="101" else
std_logic_vector(to_unsigned(2,32)) when sel_2="110" else
std_logic_vector(to_unsigned(6,32));
mux_flag <= "00" when sel_flag="00" else
"01" when sel_flag="01" else
"10" when sel_flag="10" else "11";
mux_cnt <= (others=>'0') when sel_cnt='0' else std_logic_vector(unsigned(cnt)+1);
Xmin1 <= '1' when unsigned(x) <= 1 else '0';
DmagMAX <= '1' when unsigned(d) > 2**16 else '0';
DeqO <= '1' when unsigned(d) = unsigned(o) else '0';
restozero <= '1' when unsigned(out_rem) = 0 else '0';
end arch;
APPENDICE 5:
• TB.VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use STD.textio.all;
use WORK.nfactor_pkg.all;
-- interface
entity TB is
end TB;
architecture struct of TB is
constant CLK_SEMIPERIOD0
constant CLK_SEMIPERIOD1
constant WAITS
: time := 6 ns;
: time := 5 ns;
: integer := 5;
signal CLK, RESET
: std_logic;
type seq_array is array (natural range <>) of integer;
constant sequence
: seq_array := (
15, 0, 25, 1, 40, 99, 24, 1764
, 2147483647, 2147483244 -- 12*178956937
);
constant sequence_results : seq_array := (
2, 0, 1, 0, 2, 2, 2, 3
,
1,
3
);
signal seq_idx
: integer := 0;
signal old_seq_idx
: integer := 0;
signal nw
: integer := 0;
type statetype is (
INIT,
W1, DONE1,
FINISH, FINISH2
);
signal state
: statetype := INIT;
signal A
signal Q
signal START
signal READY
signal end_simul
: std_logic_vector(31 downto 0);
: std_logic_vector(3 downto 0);
: std_logic;
: std_logic;
: std_logic;
begin
-----------------------------------------------------------clk_process: process
begin
CLK <= '1', '0' after CLK_SEMIPERIOD1;
wait for (CLK_SEMIPERIOD1 + CLK_SEMIPERIOD0);
end process clk_process;
start_process: process
begin
RESET <= '0';
wait for 1 ns;
RESET <= '1';
wait for 29 ns;
RESET <= '0';
wait;
end process start_process;
end_process: process(end_simul)
begin
if end_simul='1' then
assert false report "NONE. End of simulation." severity failure;
end if;
end process end_process;
----------------------------------------------------------------------------------------------------------------------DUT : nfactor
port map (
CLK => CLK, RESET => RESET,
A => A,
Q => Q,
START => START,
READY => READY
);
----------------------------------------------------------------------------------------------------------------------nextstate : process(CLK, RESET)
variable outputline
: LINE;
begin
if RESET = '1' then
state <= INIT;
elsif rising_edge(CLK) then
case state is
when INIT =>
if READY = '1' then
state <= W1;
end if;
seq_idx <= 0;
nw
<= 0;
when W1 =>
seq_idx <= seq_idx + 1;
old_seq_idx <= seq_idx;
state <= DONE1;
when DONE1 =>
if READY = '1' then
if sequence_results(old_seq_idx) /= to_integer(unsigned(Q)) then
write(outputline, string'("WRONG result: A="));
write(outputline, sequence(old_seq_idx));
write(outputline, string'(" Q="));
write(outputline, to_integer(unsigned(Q)));
write(outputline, string'(" (should be "));
write(outputline, sequence_results(old_seq_idx));
write(outputline, string'(")"));
writeline(output, outputline);
end if;
if seq_idx >= sequence'length then
state <= FINISH;
else
state <= W1;
end if;
end if;
when FINISH =>
nw <= nw + 1;
if nw+1 = WAITS then
state <= FINISH2;
end if;
when FINISH2 =>
end case;
end if;
end process nextstate;
outputs : process(state, seq_idx)
begin
A <= (others => '-');
START <= '0';
end_simul <= '0';
case state is
when INIT =>
when W1 =>
A <= std_logic_vector( to_unsigned( sequence(seq_idx), A'length) );
START <= '1';
when DONE1 =>
when FINISH2 =>
end_simul <= '1';
when others =>
end case;
end process outputs;
-----------------------------------------------------------end struct;
APPENDICE 6:
• DIVIDER.BEHAV.VHDL
---------------------------------------------------------------------library ieee;
use ieee.std_logic_1164.all;
package divider_behav_pkg is
component divider is
port (
CLK, RESET : in std_logic;
-- data inputs
OP1
: in std_logic_vector(31 downto 0);
OP2
: in std_logic_vector(31 downto 0);
-- data outputs
DIV
: out std_logic_vector(31 downto 0);
REMAIN
: out std_logic_vector(31 downto 0);
-- control signals
START
: in std_logic;
-- status signals
READY
: out std_logic
);
end component;
end divider_behav_pkg;
------------------------------------------------------------------------------------------------------------------------------------------library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity divider is
port (
CLK, RESET : in std_logic;
-- data inputs
OP1
: in std_logic_vector(31 downto 0);
OP2
: in std_logic_vector(31 downto 0);
-- data outputs
DIV
: out std_logic_vector(31 downto 0);
REMAIN
: out std_logic_vector(31 downto 0);
-- control signals
START
: in std_logic;
-- status signals
READY
: out std_logic
);
end divider;
architecture behav of divider is
signal waitcount
: integer := 0;
type statetype is (
INIT, WORK1, DONE
);
signal state
: statetype := INIT;
signal ratio
: std_logic_vector(DIV'range);
signal remainder
: std_logic_vector(REMAIN'range);
begin
nextstate : process(CLK, RESET)
begin
if RESET = '1' then
state <= INIT;
elsif rising_edge(CLK) then
case state is
when INIT =>
waitcount <= 0;
if START = '1' then
state <= WORK1;
ratio <= std_logic_vector( unsigned(OP1) / unsigned(OP2) );
remainder <= std_logic_vector( unsigned(OP1) mod unsigned(OP2) );
else
state <= INIT;
end if;
when WORK1 =>
waitcount <= waitcount+1;
if waitcount=34 -3 then
state <= DONE;
else
state <= WORK1;
end if;
when DONE => state <= INIT;
end case;
end if;
end process;
outputs : process(state)
begin
READY <= '0';
DIV <= (others => '-');
REMAIN <= (others => '-');
case state is
when INIT =>
READY <= '1';
DIV <= ratio;
REMAIN <= remainder;
when others =>
end case;
end process;
end behav;
----------------------------------------------------------------------
Scarica

nfactor - diegm - Università degli Studi di Udine