J'ai vu une belle question d'entrevue pour VHDL - construire un système qui reçoit un nombre et détecte s'il peut être divisé par 5 sans reste. J'ai essayé de résoudre cela avec une machine d'état (je suppose qu'ils ne veulent pas que vous utilisiez mod ou rem ) et même si j'ai eu un succès initial (des nombres comme 5, 10, 15 et des nombres tels que 20, 40, 80 ont fonctionné ), d'autres numéros comme 130, 75 et ainsi de suite ont échoué pour moi.
Je montrerais ma machine d'état mais c'est un gâchis complet (ce n'est pas un code, c'est un dessin), et comme je l'ai dit, ne fonctionne même pas.
Fondamentalement, ce que j'ai essayé de faire est d'écrire des nombres binaires divisibles par 5 et de créer une machine d'état qui fonctionnera pour eux.
Je serais heureux si vous pouviez me montrer comment résoudre ce problème et comment penser face à quelque chose comme ça.
Merci!
la source
Réponses:
Faire une opération de reste en mode série est en fait assez facile. L'hypothèse clé est que les données sont fournies en premier par MSB si elles sont en série. Vous n'avez besoin que de N états pour calculer un reste modulo N. Commencez à l'état "0" et si vous vous retrouvez à l'état "0" après le dernier bit (peu importe le nombre de bits), le reste est zéro.
simuler ce circuit - Schéma créé à l'aide de CircuitLab
Pensez à la façon dont vous feriez une longue division si la seule chose dont vous aviez besoin pour suivre était le reste:
la source
2n mod 5
et la flèche 1 pointe vers(2n + 1) mod 5
.state
,din
etN
à votre code?Vous pouvez également concevoir une machine d'état si les données viennent en premier LSB:
L'existence d'un tel automate fini déterministe (DFA) découle directement de l'autre réponse , qui décrit le DFA pour MSB-first. Étant donné que les langues acceptées par les DFA sont régulières et que les langues normales sont réputées fermées par inversion (par exemple, voir ici ), il doit y avoir un DFA qui accepte la langue suivante:
.L = { w ∈ { 0 , 1 }∗| marche arrière(w ) dix est divisible par 5 }
Construction
Copiez le premier DFA MSB de la réponse de Dave Tweed . J'ai utilisé l'outil automate JFLAP pour cela.
Appliquez l'algorithme de transformation explicite pour les inversions DFA, par exemple comme décrit sur CS.SE: Conception d'un DFA et son inverse .
Vous pouvez voir le résultat (non réduit) de cette étape dans l' ancienne révision de cette réponse.
Réduisez le DFA résultant. Malheureusement, cette fonctionnalité est un peu boguée dans la dernière version de JFLAP, donc je me suis résignée à la minimiser à la main.
q0 q1
Encore une fois, il existe de nombreux algorithmes et sources pour eux, j'ai utilisé celui décrit dans «DFA Minimization» sur tutorialspoint.com .
(En fait, si vos yeux sont suffisamment entraînés à regarder les DFA, vous pouvez directement voir que et q 1 sont des états équivalents dans le DFA comme obtenus au point 2. Les miens ne le sont pas, merci de l'avoir remarqué, allez au commentaire de supercat !)
En effet, l'automate résultant donne les bonnes réponses:
la source
Une façon de créer la machine d'état (MSB en premier) est la suivante:
Le numéro reçu jusqu'à présent est
N
. Supposons que vous connaissez le resteM = N mod 5
.Il y a un nouveau bit à venir et une nouvelle valeur est maintenant
N' = N*2 + b
.Un nouveau reste est alors
M' = (N*2 + b) mod 5 = (M*2 + b) mod 5
.C'est assez facile de tabuler à la main:
Ce qui correspond à la machine d'état dans la réponse de Dave Tweed.
la source
On espère que la question de l'entretien portait sur la manière de résoudre le problème, plutôt que sur les tenants et aboutissants de VHDL ou Verilog. Les détails de la langue sont simples une fois que vous avez un algorithme.
la source
Selon l'objet de l'écriture de la VHDL, vous souhaiterez peut-être adopter une approche qui la décrit comme un calcul combinatoire direct. La réception d'un numéro peut signifier que le numéro entier sera dans un registre pour un cycle d'horloge.
Vous pouvez, par exemple, noter le mod 5 de la valeur que chacun des bits représente, les additionner ensemble, puis répéter le processus jusqu'à ce qu'il vous reste quelque chose de moins de 5. Soit implémentez ceci de manière combinée pour toutes les étapes de réduction, ou réutiliser la logique pour un petit nombre de cycles.
Mais si vous utilisez l'opérateur rem VHDL, cela peut être la bonne réponse. En supposant que la société possède des outils de synthèse décents, cela vous donnerait une mise en œuvre assez efficace - un peu plus de surface que les solutions de machines d'état, mais un débit complet et donc probablement une bonne énergie par calcul. C'est l'option qui coûterait le moins de temps à mettre en œuvre et donc probablement le moins d'argent pour l'employeur!
Pour être honnête, ce n'est probablement pas la réponse qu'ils recherchent avec une telle question - mais c'est aussi l'occasion de montrer une véritable expérience de conception.
la source
Si le nombre est présenté en morceaux supérieurs à un bit, il peut être utile d'utiliser des calculs parallèles pour calculer le résidu mod 15, à condition que le calcul puisse donner 15 est exactement si le résidu est nul. Un moyen simple de calculer le résidu mod-15 consiste à observer que pour toute valeur de N> = 1, l'ajout des 4N bits les plus à gauche à la partie d'un nombre au-delà qui produira une valeur qui est congruente avec le mod 15. d'origine. permet au problème d'être subdivisé de différentes manières en fonction des ressources disponibles.
Par exemple, si l'on commence par une valeur 32 bits, cela peut être traité comme huit valeurs 4 bits. Celles-ci peuvent être ajoutées ensemble par paire pour produire quatre valeurs de 5 bits, qui peuvent à leur tour être combinées en deux valeurs de 6 bits ou une valeur de 7 bits. L'ajout des trois bits supérieurs de cette valeur de 7 bits aux 4 bits inférieurs donnera une valeur de 5 bits qui est au maximum de 21. On peut ainsi déterminer si la valeur d'origine est un multiple de 5 en observant si la valeur finale est l'un parmi 0, 5, 10, 15 ou 20.
la source
Je ne me souviens pas de mon VHDL, mais voici un croquis de l'idée qui m'est venue à l'esprit:
Les derniers chiffres (en base 10) des premières puissances de deux sont 1, 2, 4, 8, 6, 2, ... et le cycle se répète. Par conséquent, les restes mod 5 de puissances de deux sont 1, 2, 4, 3, ....
En utilisant cela, nous pourrions décaler les bits du LSB et accumuler les restes mod 5 correspondant à la position chaque fois qu'un
1
bit est vu. Faites également le mod d'accumulation 5, et il suffit de vérifier si la somme est nulle à la fin.la source
Nous pouvons utiliser l'idée de la réponse ici , que dans la base 4, nous pouvons déduire qu'un nombre n'est divisible par 5 que si la somme des chiffres alternés l'est. Nous avons donc
Essayons le nombre 166 = (10) (10) (01) (10): 2,2,1,2
2-2 + 1-2 = -1
ce qui est <= 3 en valeur absolue et non 0 pourquoi nous pouvons conclure en une seule itération que 166 n'est pas divisé également par 5.
Il se pourrait qu'une petite mémoire soit moins chère / meilleure en termes de vitesse / nombre de portes que d'itérer. On peut bien sûr précalculer le pire (résultat le plus élevé possible compte tenu des entrées autorisées) et planifier la conception en conséquence.
la source
L'approche MSB est certainement plus facile, mais j'ai réussi à faire le diagramme d'état LSB sans avoir besoin de générer la solution MSB ... cela m'a juste pris quelques heures. Il s'avère être équivalent à celui montré par @ComFreek, juste annoté différemment.
Nous allons suivre deux numéros. Tout d'abord, nous allons suivre la somme cumulée, modulo 5 ("SUM"). Deuxièmement, nous suivrons la valeur de la prochaine puissance de 2 à déplacer, modulo 5 ("NEXT"). Je vais représenter chaque état avec des valeurs possibles pour "SUM" en haut, et leurs valeurs "NEXT" correspondantes en dessous.
Nous allons commencer avec le cas où "SUM" modulo 5 est 0:
Notez qu'un état qui ressemble à:
3,2,4,1
1,4,3,2
est équivalent à:
1,3,4,2
2,1,3,4
Parce que les deux états représentent que:
SUM = 1 et NEXT = 4 OR
SUM = 2 et NEXT = 3 OR
SUM = 3 et NEXT = 2 OR
SUM = 4 et NEXT = 1.
Bon, alors maintenant nous devons développer des états supplémentaires, car la plupart des enquêteurs ne seront pas impressionnés par un diagramme d'état avec un seul état. Nous avons terminé lorsque chaque État a deux transitions.
Chaque fois que vous passez à un nouvel état, chaque nombre dans "NEXT" est doublé, puis modulé 5. Pour le "SUM", suivez ces règles:
Commençons donc par remplir les transitions lorsque le bit entrant est à 1.
Très bien, maintenant nous remplissons les zéros. Il n'y a qu'un seul état ajouté, nous allons donc continuer et remplir ses transitions également.
Et le tour est joué! Nous avons une machine d'état qui accepte d'abord le LSB, sans avoir à générer la solution MSB.
la source
Tout ce qui précède semble si compliqué! Il existe un moyen mathématique simple de détecter si un entier binaire est divisible par cinq. Pour commencer, vous souvenez-vous comment faire pour "éliminer les neuf" en arithmétique décimale ordinaire? Le résidu modulo 9 d'un entier décimal est le même que le résidu modulo 9 de la somme de ses chiffres. Cela fonctionne car 9 est un de moins que la base numérique.
Il existe un processus similaire, «éliminer onze», où les signes de chiffres alternatifs sont négatifs. Cela fonctionne car onze est un de plus que la base numérique.
Donc, si nous voulons "éliminer cinq", nous pourrions représenter notre entier en nombre de base quatre. Ensuite, nous commençons avec la paire de chiffres la plus basse comme somme initiale et la soustrayons de la paire de chiffres suivante pour obtenir la somme suivante. Après avoir parcouru notre entier candidat de cette façon, la somme finale sera nulle ou divisible par 5 si notre entier d'origine est divisible par 5.
Exemple 70: 01 00 01 10 -> 01 00 -1 -> 01 01 -> 00, divisible par 5 Exemple 49: 11 00 01 -> 11 -1 -> 1 00 -> 1, NON divisible par 5
Notez que vous devez porter des bits supplémentaires pour le signe de la différence accumulée et pour les cas où il y a transport.
Une autre façon de procéder consiste à simplement ajouter les chiffres hexadécimaux pour obtenir le résidu modulo 15. Bien sûr, vous avez besoin d'une dernière étape logique pour identifier les trois résultats acceptables de zéro, cinq et dix.
Exemple 70: 4 6 -> A, donc 70 est divisible par 5 (mais pas par 15) Exemple 49: 3 1 -> 4, donc 70 n'est PAS divisible par 5.
Notez que vous pouvez utiliser différentes bases numériques pour construire de nombreux tests de divisibilité, bien que dans la logique informatique, ceux pour des puissances de 2 +/- 1 soient les plus faciles à implémenter.
En arithmétique décimale, l'un de mes favoris est mon test pour le résidu mod 7. Notez que 100 est deux supérieur à un multiple de 7, alors groupez les chiffres en paires (travaillez en base 100) et ajoutez les centaines DEUX FOIS des unités. Ici on travaille de gauche à droite ...
Exemple: 98 76 -> 2 72 -> 76, donc 9876 n'est pas divisible par 7. C'est 6 mod 7. Exemple: 03 45 67 -> 51 67 -> 1 69 -> 71 donc c'est 1 mod 7.
Bien sûr, en binaire, il suffit de prendre la somme des chiffres octaux (groupes de 3 bits).
Désolé, j'aurais aimé être un gourou de Verilog, mais l'arithmétique est tout ce que je peux offrir à ce stade de la vie. Voir "Dead Reckoning" de Ron Doerfler pour de nombreuses astuces comme celle-ci.
la source
Une question d'entrevue VHDL devrait entraîner un code VHDL.
J'ai eu l'occasion de trouver un bug de backend ghdl llvm avec une implémentation de la table de transition d'état de Dave Tweed où l'auteur de ghdl a distillé l'implémentation dans une fonction à 17 lignes:
Le scénario de test associé est assez petit, ce qui facilite le débogage et utilise des noms d'état compatibles avec VHDL dans le type énuméré qui reste:
(créé avec Dia)
L'idée ici est que la fonction (ou même un exemple de programme VHDL de 27 lignes) est suffisamment courte pour écrire une réponse VHDL lors d'un entretien. Pas besoin de s'inquiéter de gâcher une question d'entrevue nécessitant une démonstration des connaissances et des compétences, une personne interrogée devrait défendre une mise en œuvre lorsqu'elle est interrogée.
(Le bug du backend llvm a été corrigé dans commit 1f5df6e plus tôt dans la journée .)
La table de transition d'état nous indique également où un bit de quotient serait un `` 1 '' indiqué par une transition vers un état avec une valeur de reste inférieure (ou les deux transitions pour r4) lors de la soustraction de 5 du dividende. Cela peut être encodé dans une table séparée (ou une table d'un type d'enregistrement qui semble encombrant). Nous le faisons historiquement dans du matériel graphique traitant des résolutions d'écran horizontales qui se multiplient par 5 pixels.
Cela nous donne un div / mod5 produisant un quotient et un reste:
Implémenté ici avec une instruction generate, une instruction generate interne produisant des bits de quotient. Le tableau staydr fournit une trace de transition d'état:
Le tout sans opération arithmétique.
Il est également possible de l'implémenter dans une procédure sans que tous les registres profitent des paramètres avec mode out. Cela approcherait un nombre minimum de lignes pour une interview.
Une mise en œuvre séquentielle cadencée nécessiterait un compteur de bits et un contrôle de flux (une bascule JK et quelques portes).
Il y a un compromis temps / complexité en fonction de la taille du dividende que vous seriez également amené à défendre lors d'une interview.
la source