Domanda di intervista VHDL: rilevare se un numero può essere diviso per 5 senza resto


24

Ho visto una bella domanda di intervista per VHDL: costruire un sistema che riceve un numero e rileva se può essere diviso per 5 senza resto. Ho provato a risolverlo con una macchina a stati (suppongo che non vogliano che tu usi mod o rem ) e mentre ho avuto successo iniziale (numeri come 5, 10, 15 e numeri come 20, 40, 80 hanno funzionato ), altri numeri come 130, 75 e così via sono falliti per me.

Vorrei mostrare la mia macchina a stati ma è un disastro completo (non è un codice, è un disegno) e, come ho detto, non funziona nemmeno.

Fondamentalmente quello che ho provato a fare è scrivere in numeri binari che sono divisibili per 5 e costruire una macchina a stati che funzionerà per loro.

Sarei felice se tu potessi mostrarmi come risolvere questo problema e come pensare di fronte a qualcosa del genere.

Grazie!


Intendi un'implementazione hardware (sintetizzabile), non solo un codice per testare se un numero intero intero è divisibile per 5 (ad esempio per testbench).
smci,

@smci In realtà stavo chiedendo uno schema / disegno di una macchina a stati, ma un codice di quella macchina a stati non avrebbe fatto male. Tuttavia, Dave Tweed ha risposto perfettamente alla domanda.
Eran,

poi lo riproverei * "Domanda di intervista VHDL - cct per rilevare se ..."
smci

La risposta qui di egreg math.stackexchange.com/a/2569882/213607 potrebbe ispirare un approccio più parallelo.
matematico

Risposte:


37

Effettuare un'operazione rimanente in serie è in realtà abbastanza semplice. Il presupposto chiave è che i dati arrivano prima in MSB se sono seriali. Hai solo bisogno di N stati per calcolare un resto modulo N. Inizia nello stato "0" e se finisci nello stato "0" dopo l'ultimo bit (non importa quanti bit ci sono), il resto è zero.

schematico

simula questo circuito - Schema creato usando CircuitLab

Pensa a come faresti per una lunga divisione se l'unica cosa di cui hai bisogno per tenere traccia fosse il resto:

process (clk)
begin
  if rising_edge(clk) then
    if reset = 1 then
      state <= 0;
    else
      if (state & din) >= N then
        state <= (state & din) - N;
      else
        state <= state & din;
      end if;
    end if;
  end if;
end process;

6
Caspita, vedo che funziona ma potresti spiegare come hai inventato la macchina statale? Qual è stato il punto di partenza? Non l'ho mai visto prima, sono solo curioso di sapere quale sia la logica di come elaborarla?
zoder,

7
Il diagramma di stato è proprio quello che ottieni dal codice VHDL per il caso specifico di N = 5. In altre parole, se lo stato rappresenta il resto corrente, lo stato successivo è quello che si ottiene quando si sposta lo stato a sinistra di un bit, si aggiunge il bit di input e si sottrae 5 se necessario.
Dave Tweed

3
Questo, se bello, sarei davvero impressionato se qualcuno lo scoprisse da solo in un'intervista. E poi chiederei loro felicemente di commentare come i risultati della sintesi differirebbero dal solo utilizzo di un operatore rem per elaborare un vettore completo ad ogni ciclo di clock.
Casperrw,

8
@zoder Gli stati sono i residui mod 5; la freccia 0 indica 2n mod 5e la freccia 1 indica (2n + 1) mod 5.
Hobbs

2
Potrebbe aggiungere le dichiarazioni di state, dine Nal codice?
mkrieger1,

15

Puoi anche progettare una macchina a stati se i dati arrivano prima LSB:

Una rappresentazione grafica del DFA come descritto alla fine di questa risposta in appendice.

L'esistenza di un tale automa finito deterministico (DFA) segue direttamente dall'altra risposta , che descrive il DFA per MSB-first. Poiché le lingue accettate dai DFA sono regolari e si sa che le lingue regolari sono chiuse per inversione (ad es. Vedi qui ), deve esserci un DFA che accetta la seguente lingua:

.L={w{0,1}*| inverso(w)10 è divisibile per 5}

Costruzione

  1. Copia il primo DFA di MSB dalla risposta di Dave Tweed . Per questo ho usato lo strumento automa JFLAP .

  2. Applicare l'algoritmo di trasformazione esplicita per inversioni DFA, ad esempio come descritto in CS.SE: progettazione di un DFA e il suo inverso .
    Puoi vedere il risultato (non minimizzato) di questo passaggio nella vecchia revisione di questa risposta.

  3. Ridurre al minimo il DFA risultante. Sfortunatamente, questa funzione è un po 'buggy nell'ultima versione di JFLAP, quindi mi sono dimesso per minimizzarlo a mano.
    Ancora una volta, ci sono molti algoritmi e fonti per loro là fuori, ho usato quello descritto in "Minimizzazione DFA" su tutorialspoint.com .

    (In realtà, se i tuoi occhi sono abbastanza allenati nell'osservare i DFA, potresti vedere direttamente che e q 1 sono stati equivalenti nel DFA come ottenuto al punto 2. I miei non lo sono, grazie per aver notato che vai al commento del supercat !)q0q1

In effetti, l'automa risultante dà le risposte giuste:

Tabella con due colonne "Input" e "Result" che elencano se vari numeri risultano in "Accetta" o "Rifiuta".


UNrev5=(Q,Σ,δ,q0,F)Q={q0,q1,q2,q3,q4}Σ={0,1}F={q0}δ

δ(q0,0)=q0,δ(q0,1)=q1δ(q1,0)=q4,δ(q1,1)=q3δ(q2,0)=q1,δ(q2,1)=q2δ(q3,0)=q2,δ(q3,1)=q4δ(q4,0)=q3,δ(q4,1)=q0


Se hai difficoltà a invertire il DFA, puoi anche invertire l'equazione: invece di new_state = state * 2 + input, puoi usare (new_state - input) / 2 = state, quindi scambiare state e new_state. Il DFA per la nuova equazione dovrebbe risolvere il primo problema di LSB.
Eyal,

Perché q3 e q4 sono etichettati così e non viceversa? Scambia le etichette q3 e q4 e la macchina implementa l'algo "metà (mod 5) e aggiungi il bit di input".
Rosie F,

2
@RosieF: La frase "halve (mod 5)" potrebbe forse usare qualche spiegazione in più per coloro che non hanno familiarità con la matematica discreta. La divisione in questo contesto implica l'aggiunta di qualsiasi multiplo della base sarebbe necessario per dividere il numero in modo uniforme, quindi 3/2 (mod 5) sarebbe (3 + 5) / 2, cioè 4.
supercat

7

Un modo per inventare la macchina a stati (prima MSB) è il seguente:

  1. Il numero ricevuto finora è N. Supponiamo di conoscere il resto M = N mod 5.

  2. C'è un nuovo bit in arrivo e il nuovo valore è ora N' = N*2 + b.

  3. Il nuovo resto è quindi M' = (N*2 + b) mod 5 = (M*2 + b) mod 5.

Questo è abbastanza facile da tabulare a mano:

    M b | M'
------------------
    0 0 | 0
    1 0 | 2
    2 0 | 4
    3 0 | 1
    4 0 | 3
    0 1 | 1
    1 1 | 3
    2 1 | 0
    3 1 | 2
    4 1 | 4

Che corrisponde alla macchina dello stato nella risposta di Dave Tweed.


5

Si spera che la domanda dell'intervista riguardasse come risolvere il problema, piuttosto che i dettagli di VHDL o Verilog. I dettagli della lingua sono chiari una volta che hai un algoritmo.

S=0S(2S+d) mod 5 SS,dS=0,,4

S=0,K=0S(S+2Kd) mod 5,KK+1K24=1 mod 5S(S+2Kd) mod 5,K(K+1) mod 4S,K,d(S,K)S=0,,4K=0,,3


3

A seconda di cosa sta scrivendo il VHDL, potresti voler adottare un approccio che lo descriva come un calcolo combinato diretto. La ricezione di un numero può significare che l'intero numero sarà in un registro per un ciclo di clock.

Ad esempio, potresti annotare la mod 5 del valore rappresentato da ciascuno dei bit, aggiungerli insieme e quindi ripetere il processo fino a quando rimani con qualcosa di meno di 5. O implementalo in modo combinato per tutti i passaggi di riduzione, o riutilizzare la logica per un numero limitato di cicli.

Ma se usi l'operatore rem VHDL, questa potrebbe essere la risposta giusta. Supponendo che l'azienda disponga di strumenti di sintesi decenti, che ti darebbero un'implementazione abbastanza efficiente - forse un po 'più di area rispetto alle soluzioni di macchina a stati, ma piena produttività e quindi probabilmente una buona energia per calcolo. È l'opzione che costerebbe il minor tempo di attuazione e quindi probabilmente il minor denaro per il datore di lavoro!

Ad essere onesti, probabilmente non è la risposta che stanno cercando con una domanda del genere, ma è anche un'opportunità per mettere in mostra qualsiasi esperienza di design reale.


3

Se il numero è presentato in blocchi più grandi di un bit, può essere utile utilizzare alcuni calcoli paralleli per calcolare il residuo mod 15, a condizione che il calcolo possa produrre 15 è esattamente se il residuo è zero. Un modo semplice per calcolare il residuo mod-15 è quello di osservare che per qualsiasi valore di N> = 1, l'aggiunta dei bit 4N più a sinistra alla porzione di un numero oltre quello produrrà un valore congruente al mod 15 originale. Questo consente di suddividere il problema in molti modi diversi a seconda delle risorse disponibili.

Ad esempio, se si inizia con un valore a 32 bit, questo può essere trattato come otto valori a 4 bit. Questi possono essere aggiunti insieme in coppia per produrre quattro valori a 5 bit, che a loro volta possono essere combinati in due valori a 6 bit o in un valore a 7 bit. L'aggiunta dei tre bit superiori di quel valore a 7 bit ai 4 bit inferiori produrrà un valore a 5 bit che è al massimo 21. Si può quindi determinare se il valore originale è un multiplo di 5 osservando se il valore finale è uno di 0, 5, 10, 15 o 20.


... oppure puoi usare additivi a 4 bit in tutto, e assicurati solo che ogni carry-out diventi un carry-in per un sommatore più avanti nel circuito. Dopo tre livelli di aggiunta hai un singolo risultato a 4 bit e quattro carry ancora inutilizzati. Aggiungi tre dei carry insieme in parallelo con l'ultima aggiunta a 4 bit e aggiungi la loro somma al risultato con l'ultimo carry come carry-in. Questo produce al massimo 19, quindi non è necessario abbinare 20 in seguito.
Henning Makholm,

@HenningMakholm: ci sono molti modi per organizzare i componenti aggiuntivi per ottenere il risultato desiderato. Quale approccio sia migliore in una determinata situazione dipenderebbe probabilmente dal routing specifico del progetto o da problemi di utilizzo delle risorse. Un altro trucco sarebbe usare un add-carry carry-save, ma sfruttare il fatto che il bit superiore dell'output spostato può essere spostato verso il basso. Pertanto, uno strato potrebbe trasformare 8 ingressi in 6, quindi 6 in 4, quindi 4 in 3 e 3 in 2. Un'uscita di ogni strato sarebbe semplicemente porte AND e l'altra porte XOR, quindi il tempo di propagazione per scendere a un coppia di valori a 4 bit per ...
supercat

... una sola catena di trasporto sarebbe quella di quattro porte xor. Se è meglio ottenere un output inferiore a 19 o se è meglio controllare 20 come un possibile residuo, ciò dipende probabilmente dalla disponibilità e dall'utilizzo delle risorse. Dato un numero che non è più di 30, l'aggiunta dei nybbles superiori e inferiori produrrebbe un valore al massimo di 15 (o 16 + 14-> 1 + 14 o 0 + 15-> 0 + 15), ma aggiungendo esplicito i controlli per alcuni o tutti (20, 25, 30) potrebbero essere più economici.
supercat

2

Non ricordo il mio VHDL, ma ecco uno schizzo dell'idea che mi è venuta in mente per la prima volta:

Le ultime cifre (nella base 10) delle prime potenze di due sono 1, 2, 4, 8, 6, 2, ... e il ciclo si ripete. Quindi, i restanti mod 5 dei poteri di due sono 1, 2, 4, 3, ....

Usando quello, potremmo spostare in bit dall'LSB, e accumulare i rimanenti mod 5 corrispondenti alla posizione ogni volta che 1viene visto un bit. Esegui anche l'accumulazione mod 5 ed è sufficiente verificare se la somma è zero alla fine.


1

Possiamo usare l'idea dalla risposta qui , che nella base 4 possiamo derivare che un numero è divisibile per 5 solo se la somma delle cifre alternate lo è. Quindi

  1. raggruppare le cifre 2 per 2,
  2. sommare il dispari e sottrarre i blocchi pari di 2 bit.
  3. Se il risultato è nella regione dei due complementi di alcuni bit, ad esempio [-4,3] (facile da controllare supponendo che usiamo due complementi), allora abbiamo finito e possiamo dividere il numero originale per 5 solo se il risultato del la somma è 0 che è un'espressione logica molto semplice da controllare (in pratica solo un grande né su tutti i bit risultanti, no?)
  4. altrimenti ripetiamo il nuovo (numero molto più breve).

Proviamo sul numero 166 = (10) (10) (01) (10): 2,2,1,2

2-2 + 1-2 = -1

che è <= 3 in valore assoluto e non 0 perché possiamo concludere in una sola iterazione che 166 non è diviso equamente per 5.

Potrebbe essere che un piccolo ricordo potrebbe essere più economico / migliore in termini di velocità / numero di porte rispetto all'iterazione. Ovviamente si può precalcolare il peggio (il più grande risultato possibile dati gli input consentiti) e pianificare il progetto di conseguenza.


1

L'approccio MSB è decisamente più semplice, ma sono riuscito a fare il diagramma di stato LSB senza dover generare la soluzione MSB ... mi ci sono volute solo un paio d'ore. Risulta essere equivalente a quello mostrato da @ComFreek, appena annotato in modo diverso.

Tracciamo due numeri. Innanzitutto, seguiremo la somma corrente, modulo 5 ("SOMMA"). In secondo luogo, seguiremo il valore della prossima potenza di 2 da spostare, modulo 5 ("NEXT"). Rappresenterò ogni stato con possibili valori per "SOMMA" in alto e i corrispondenti valori "SUCCESSIVO" sotto di essi.

Inizieremo con il caso in cui "SUM" modulo 5 è 0:

Iniziale

Si noti che uno stato simile a:
3,2,4,1
1,4,3,2

è equivalente a:
1,3,4,2
2,1,3,4

Perché entrambi gli stati indicano che:
SUM = 1 e NEXT = 4 OR
SUM = 2 e NEXT = 3 OR
SUM = 3 e NEXT = 2 OR
SUM = 4 e NEXT = 1.

Va bene, quindi ora dobbiamo sviluppare stati extra, poiché la maggior parte degli intervistatori non sarà colpita da un diagramma di stato con un solo stato. Abbiamo finito quando ogni stato ha due transizioni.

Ogni volta che passi a un nuovo stato, ogni numero in "SUCCESSIVO" viene raddoppiato, quindi modulo 5. Per la "SOMMA" segui queste regole:

  • Se hai effettuato una transizione lungo uno 0, la riga superiore mantiene i suoi valori.
  • Se hai effettuato la transizione lungo un 1, ogni colonna è il modulo "SUM" + "NEXT" del vecchio stato.

Quindi, iniziamo compilando le transizioni quando il bit in entrata è 1.

Tutti 1

Bene, ora riempiamo gli zeri. C'è solo uno stato aggiunto, quindi andremo avanti e riempiremo anche le sue transizioni.

Completare

E voilà! Abbiamo una macchina a stati che accetta prima l'LSB, senza dover generare la soluzione MSB.


1

Tutto quanto sopra sembra così complicato! Esiste un modo matematico semplice per rilevare se un numero intero binario è divisibile per cinque. Per cominciare, ti ricordi come fare "scacciare nove" nell'aritmetica decimale ordinaria? Il modulo residuo 9 di un numero intero decimale è uguale al modulo residuo 9 della somma delle sue cifre. Questo funziona perché 9 è uno in meno della base numerica.

Esiste un processo simile, "scartare undici", in cui i segni di cifre alternate sono impostati in negativo. Questo funziona perché undici è uno maggiore della base numerica.

Quindi, se vogliamo "scacciare i cinque", potremmo rappresentare il nostro numero intero nella base numerica quattro. Quindi iniziamo con la coppia di cifre più bassa come somma iniziale e la sottraggiamo dalla coppia di cifre successiva per ottenere la somma successiva. Dopo aver esaminato il nostro numero intero candidato in questo modo, la somma finale sarà zero o divisibile per 5 se il nostro numero intero originale è divisibile per 5.

Esempio 70: 01 00 01 10 -> 01 00 -1 -> 01 01 -> 00, divisibile per 5 Esempio 49: 11 00 01 -> 11 -1 -> 1 00 -> 1, NOT divisibile per 5

Si noti che è necessario portare un bit in più per il segno della differenza accumulata e per i casi in cui è presente.

Un altro modo di procedere è semplicemente aggiungere le cifre esadecimali per ottenere il modulo residuo 15. Naturalmente è necessario un passaggio logico finale per identificare i tre risultati accettabili di zero, cinque e dieci.

Esempio 70: 4 6 -> A, quindi 70 è divisibile per 5 (ma non per 15) Esempio 49: 3 1 -> 4, quindi 70 NON è divisibile per 5.

Si noti che è possibile utilizzare basi numeriche diverse per costruire numerosi test di divisibilità, sebbene nella logica del computer siano più facili da implementare quelli con potenze di 2 +/- 1.

In aritmetica decimale, uno dei miei preferiti è il mio test per il residuo mod 7. Nota che 100 è due maggiore di un multiplo di 7, quindi raggruppa le cifre in coppie (lavora in base numerica 100) e aggiungi le centinaia DUE VOLTE dalle unità. Qui lavoriamo da sinistra a destra ...

Esempio: 98 76 -> 2 72 -> 76, quindi 9876 non è divisibile per 7. È 6 mod 7. Esempio: 03 45 67 -> 51 67 -> 1 69 -> 71 quindi è 1 mod 7.

Naturalmente, in binario, basta prendere la somma delle cifre ottali (gruppi di 3 bit).

Mi dispiace, vorrei essere un guru di Verilog, ma l'aritmetica è tutto ciò che posso offrire in questa fase della vita. Guarda "Dead Reckoning" di Ron Doerfler per molti trucchi come questo.


Mi chiedo se i nostri cugini canadesi potrebbero avere alcuni algoritmi speciali. Da quando hanno messo fuorilegge il penny canadese, tutti i prezzi sono arrotondati ai $ 0,05 più vicini.
richard1941,

1

Una domanda di intervista VHDL dovrebbe comportare un codice VHDL.

Ho avuto occasione di trovare un bug backend ghdl llvm con un'implementazione della tabella di transizione dello stato di Dave Tweed in cui l'autore di ghdl ha distillato l'implementazione in una funzione su 17 righe:

type remains is (r0, r1, r2, r3, r4); -- remainder values

    function mod5 (dividend: bit_vector) return boolean is
        type remain_array is array (NBITS downto 0) of remains;
        type branch is array (remains, bit) of remains;
        constant br_table:  branch := ( r0 => ('0' => r0, '1' => r1),
                                        r1 => ('0' => r2, '1' => r3),
                                        r2 => ('0' => r4, '1' => r0),
                                        r3 => ('0' => r1, '1' => r2),
                                        r4 => ('0' => r3, '1' => r4)
                                      );
        variable  remaind:    remains := r0;
        variable tbit:        bit_vector (NBITS - 1 downto 0) := dividend;
    begin
        for i in dividend'length - 1 downto 0 loop
            remaind := br_table(remaind,tbit(i));
        end loop;
        return remaind = r0;
end function;

Il caso di test associato è piuttosto piccolo e consente un debug più semplice e utilizza nomi di stato compatibili con VHDL nel tipo enumerato:

dave_tweed.png (creato con Dia)

L'idea qui è che la funzione (o anche un esempio di programma VHDL di 27 righe) è abbastanza breve da scrivere una risposta VHDL durante un'intervista. Non c'è bisogno di preoccuparsi di rovinare una domanda di intervista che richiede dimostrazione di conoscenze e abilità, un intervistato dovrebbe difendere un'implementazione quando viene interrogato.

(Il bug backend di llvm è stato corretto oggi in commit 1f5df6e .)

Una delle cose da notare è che la tabella di transizione di stato ci dice anche dove un bit di quoziente sarebbe un '1' mostrato da una transizione verso uno stato con un valore di resto inferiore (o entrambe le transizioni per r4) quando si sottraggono 5 dal dividendo. Questo può essere codificato in una tabella separata (o in una tabella di tipo record che sembra ingombrante). Lo facciamo storicamente nell'hardware grafico che si occupa di risoluzioni dello schermo orizzontali che si moltiplicano per 5 pixel.

In questo modo ci dà un div / mod5 producendo un quoziente e resto:

library ieee;
use ieee.std_logic_1164.all;

entity divmod5 is
    generic (
        NBITS:  natural := 13 
    );
    port (
        clk:        in  std_logic;
        dividend:   in  std_logic_vector (NBITS - 1 downto 0);
        load:       in  std_logic;
        quotient:   out std_logic_vector (NBITS - 3 downto 0);
        remainder:  out std_logic_vector (2 downto 0);
        remzero:    out std_logic
    );
end entity;

architecture foo of divmod5 is
    type remains is (r0, r1, r2, r3, r4); -- remainder values
    type remain_array is array (NBITS downto 0) of remains;
    signal remaindr:    remain_array := (others => r0);
    signal dividendreg: std_logic_vector (NBITS - 1 downto 0);
    signal quot:        std_logic_vector (NBITS - 3 downto 0);
begin

parallel:
    for i in NBITS - 1 downto 0 generate
        type branch is array (remains, bit) of remains;
        -- Dave Tweeds state transition table:
        constant br_table:  branch := ( r0 => ('0' => r0, '1' => r1),
                                        r1 => ('0' => r2, '1' => r3),
                                        r2 => ('0' => r4, '1' => r0),
                                        r3 => ('0' => r1, '1' => r2),
                                        r4 => ('0' => r3, '1' => r4)
                                      );

        type qt is array (remains, bit) of std_ulogic;
    -- Generate quotient bits from Dave Tweeds state machine using q_table.
    -- A '1' when a remainder goes to a lower remainder or for both branches
    -- of r4. A '0' for all other branches.

        constant q_table:   qt :=     ( r0 => (others => '0'),
                                        r1 => (others => '0'),
                                        r2 => ('0' => '0', '1' => '1'),
                                        r3 => (others => '1'),
                                        r4 => (others => '1')
                                      );
        signal tbit:    bit;
    begin
        tbit <= to_bit(dividendreg(i));
        remaindr(i) <= br_table(remaindr(i + 1),tbit);
do_quotient:
        if i < quot'length generate   
            quot(i) <= q_table(remaindr(i + 1),tbit);
        end generate;
    end generate;

dividend_reg:
    process (clk)
    begin
        if rising_edge(clk) then
            if load = '1' then
                dividendreg <= dividend;
            end if;
        end if;
    end process;

quotient_reg:
    process (clk)
    begin
        if rising_edge (clk) then
            quotient <=  quot;
        end if;
    end process;

remainders:
    process (clk)
    begin
        if rising_edge(clk) then 
            remzero <= '0';
            case remaindr(0) is
                when r0 =>
                    remainder <= "000";
                    remzero <= '1';
                when r1 =>
                    remainder <= "001";
                when r2 =>
                    remainder <= "010";
                when r3 =>
                    remainder <= "011";
                when r4 =>
                    remainder <= "100";
            end case;
        end if;
    end process;

end architecture;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity divmod5_tb is
end entity;

architecture foo of divmod5_tb is
    constant NBITS:    integer range 0 to 13 := 8;
    signal clk:        std_logic := '0';
    signal dividend:   std_logic_vector (NBITS - 1 downto 0);
    signal load:       std_logic := '0';

    signal quotient:   std_logic_vector (NBITS - 3 downto 0);
    signal remainder:  std_logic_vector (2 downto 0);
    signal remzero:    std_logic;
    signal psample:    std_ulogic;
    signal sample:     std_ulogic;
    signal done:       boolean;
begin
DUT:
    entity work.divmod5
        generic map  (NBITS)
        port map (
            clk => clk,
            dividend => dividend,
            load => load,
            quotient => quotient,
            remainder => remainder,
            remzero => remzero
        );
CLOCK:
    process
    begin
        wait for 5 ns;
        clk <= not clk;
        if done'delayed(30 ns) then
            wait;
        end if;
    end process;
STIMULI:
    process
    begin
        for i in 0 to 2 ** NBITS - 1 loop
            wait for 10 ns;
            dividend <= std_logic_vector(to_unsigned(i,NBITS));
            wait for 10 ns;
            load <= '1';
            wait for 10 ns;
            load <= '0';
        end loop;
        wait for 15 ns;
        done <= true;
        wait;
    end process;

SAMPLER:
    process (clk)
    begin
        if rising_edge(clk) then
            psample <= load;
            sample <= psample after 4 ns;
        end if;
    end process;

MONITOR:
    process (sample)
        variable i:     integer;
        variable div5:  integer;
        variable rem5:  integer;
    begin
        if rising_edge (sample) then
            i := to_integer(unsigned(dividend));
            div5 := i / 5;
            assert div5 = unsigned(quotient)
                report LF & HT &
                    "i = " & integer'image(i) &
                    " div 5 expected " & integer'image(div5) & 
                    " got " & integer'image(to_integer(unsigned(quotient)))
                SEVERITY ERROR;
            rem5 := i mod 5;
            assert rem5 = unsigned(remainder)
                report LF & HT &
                    "i = " & integer'image(i) &
                    " rem 5 expected " & integer'image(rem5) & 
                    " got " & integer'image(to_integer(unsigned(remainder)))
                SEVERITY ERROR;
        end if;
    end process;

end architecture;

Implementato qui con un'istruzione generate, un'istruzione generate interna che produce bit di quoziente. L'array remaindr fornisce una traccia di transizione di stato:

divmod5_tb.png

Tutto senza un'operazione aritmetica.

È anche possibile implementare in una procedura senza che tutti i registri sfruttino i parametri con mode out. Si avvicinerebbe a un numero minimo di righe per un'intervista.

Un'implementazione sequenziale con clock richiederebbe un contatore di bit e un controllo del flusso (un flip flop JK e un paio di gate).

C'è un compromesso tempo / complessità a seconda della dimensione del dividendo che probabilmente ti verrà richiesto di difendere in un'intervista.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.