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; ----------------------------------------------------------------------