tag:linuxfr.org,2005:/tags/sshdl/publicLinuxFr.org : les contenus étiquetés avec « sshdl »2018-05-09T10:56:47+02:00/favicon.pngtag:linuxfr.org,2005:Diary/378932018-04-15T21:18:30+02:002018-05-09T10:55:58+02:00Un composant électronique TapTempo avec Chisel3Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<p>Le <a href="https://duckduckgo.com/?q=TapTempo+site%3Alinuxfr.org&ia=web">«défi» TapTempo</a> est un peu en train de faiblir je trouve. Du coup je vous propose un nouveau langage pour réaliser TapTempo : <a href="https://chisel.eecs.berkeley.edu/">Chisel</a>. Et pour être plus précis, la version 3 de Chisel.</p>
<p>Contrairement à tous les langages proposés jusqu'ici, Chisel ne permet pas de réaliser un programme qui sera exécuté par une machine réelle ou virtuelle. Chisel permet de décrire l'architecture de la machine elle-même !</p>
<p>C'est ce qu'on appelle un langage de description matériel ou HDL pour Hardware Description Langage. Ce sont des langages utilisés pour décrire les «IP» pour <a href="https://fr.wikipedia.org/wiki/Circuit_logique_programmable">les FPGA, les CPLD</a> mais aussi (et surtout en fait) les <a href="https://fr.wikipedia.org/wiki/Application-specific_integrated_circuit">ASIC</a>.</p>
<p>Les deux HDL les plus connus sont le VHDL et le Verilog. Cependant, ce sont de vieux langages extrêmement verbeux et pas très modulaires. Un design correct en simulation ne le sera pas forcément en synthèse.</p>
<p>C'est pourquoi plusieurs nouveaux langages de description de matériel sont en train de voir le jour aujourd'hui. Chisel est l'un d'eux. Lancé initialement par l'université de Berkley, <a href="https://chisel.eecs.berkeley.edu/">Chisel</a> est basé sur le langage Scala. Il permet de faire une description synchrone et synthétisable de son design. La même université utilise Chisel pour faire des «core» <a href="https://riscv.org/">Risc-V.</a></p>
<p>Pour pouvoir être compatible avec la plupart des logiciels de synthèse du marché les IP écrites en Chisel sont ensuite converties en (en passant par un langage «netlist» intermédiaire nommé FIRRTL) Verilog, qui lui sera synthétisable et simulable avec tous les logiciels connus.</p>
<p>Dans cette «IP» TapTempo nous laisserons de côté la partie synchronisation du signal externe ainsi que la gestion des rebonds du bouton qui sont propres à l'intégration. Nous nous concentrerons sur l'essence de la fonctionnalité.</p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f7777772e66616269656e6d2e65752f666c662f77702d636f6e74656e742f75706c6f6164732f323031382f30332f67656e6572616c2d312e6a7067/general-1.jpg" alt="Vue «externe» de TapTempo" title="Source : http://www.fabienm.eu/flf/wp-content/uploads/2018/03/general-1.jpg"></p>
<p>Plutôt que de taper une touche, l'idée ici est d'utiliser un bouton. Le résultat se présente ensuite sous la forme d'un signal binaire sur 9 bits. D'après la page wikipedia des battements par minute, 270bpm est déjà très rapide, pas la peine d'aller plus loin dans le dimensionnement. Par conséquent 9 bits suffisent pour présenter le résultat (entier positif).</p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f7777772e66616269656e6d2e65752f666c662f77702d636f6e74656e742f75706c6f6164732f323031382f30332f5374727563742d322e6a7067/Struct-2.jpg" alt="Architecture de TapTempo" title="Source : http://www.fabienm.eu/flf/wp-content/uploads/2018/03/Struct-2.jpg"></p>
<p>Le schéma d'architecture de TapTempo est un peu «à main levée» mais ça permet de comprendre l'esprit du composant. Un générateur de «ticks» génère des ticks à une fréquence de 1kHz. Ces ticks sont comptés par le compteur «count».<br>
À chaque appui sur le bouton le résultat du compteur est stocké dans un registre «countx», le pointeur «mux» est incrémenté et le compteur est remis à zéro.</p>
<p>On choisira une architecture avec seulement <strong>4</strong> registres d'échantillons «countx» car il est incroyablement plus facile de faire une division par 4 (un simple décalage à droite de deux) que si nous avions eu 5 valeurs comme pour les autres programmes.</p>
<p>Les 4 valeurs «countx» sont donc additionnées puis divisées par 4 et vient le problème de la division (inversion) permettant de convertir une période moyenne en une fréquence.</p>
<p>Il est très compliqué de diviser dans un FPGA. On emprunte donc généralement des chemins détournés pour arriver à nos fins. Ici nous allons créer une table de registres avec toutes les valeurs «en dur» pré-calculées. Puis nous comparerons (inégalité) la valeur du compteur à tous les registres de manière parallèle (toutes les comparaisons se font en même temps), le résultat sera un vecteur de 270 bits rempli de '1' jusqu'à la valeur voulue.<br>
Pour avoir une sortie sur 9 bits et non sur 270 (ça fait vraiment trop de LED à souder pour la maquette !) Chisel fournit une petite fonction bien utile permettant de sortir la valeur de l'index du bit de poids faible à '1' : le PriorityEncoder. Comme nous on veut le poids fort on retournera le vecteur et on fera une petite soustraction de 270.</p>
<p>Voila pour le paquet d'explications. Et voila pour le code :</p>
<pre><code class="scala"><span class="k">package</span> <span class="nn">taptempo</span>
<span class="k">import</span> <span class="nn">chisel3._</span>
<span class="k">import</span> <span class="nn">chisel3.util.</span><span class="o">{</span><span class="nc">Counter</span><span class="o">,</span> <span class="nc">PriorityEncoder</span><span class="o">,</span> <span class="nc">Reverse</span><span class="o">}</span>
<span class="k">import</span> <span class="nn">scala.language.reflectiveCalls</span> <span class="c1">//avoid reflective call warnings</span>
<span class="k">import</span> <span class="nn">scala.math.pow</span>
<span class="c1">// default clock 100Mhz -> T = 10ns</span>
<span class="k">class</span> <span class="nc">TapTempo</span><span class="o">(</span><span class="n">tclk_ns</span><span class="k">:</span> <span class="kt">Int</span><span class="o">,</span> <span class="n">bpm_max</span><span class="k">:</span> <span class="kt">Int</span> <span class="o">=</span> <span class="mi">270</span><span class="o">)</span> <span class="k">extends</span> <span class="nc">Module</span> <span class="o">{</span>
<span class="k">val</span> <span class="n">io</span> <span class="k">=</span> <span class="nc">IO</span><span class="o">(</span><span class="k">new</span> <span class="nc">Bundle</span> <span class="o">{</span>
<span class="k">val</span> <span class="n">bpm</span> <span class="k">=</span> <span class="nc">Output</span><span class="o">(</span><span class="nc">UInt</span><span class="o">(</span><span class="mf">9.</span><span class="n">W</span><span class="o">))</span>
<span class="k">val</span> <span class="n">button</span> <span class="k">=</span> <span class="nc">Input</span><span class="o">(</span><span class="nc">Bool</span><span class="o">())</span>
<span class="o">})</span>
<span class="cm">/* Constant parameters */</span>
<span class="k">val</span> <span class="nc">MINUTE_NS</span> <span class="k">=</span> <span class="mi">60</span><span class="o">*</span><span class="mi">1000</span><span class="o">*</span><span class="mi">1000</span><span class="o">*</span><span class="mi">1000L</span>
<span class="k">val</span> <span class="nc">PULSE_NS</span> <span class="k">=</span> <span class="mi">1000</span><span class="o">*</span><span class="mi">1000</span>
<span class="k">val</span> <span class="nc">TCLK_NS</span> <span class="k">=</span> <span class="n">tclk_ns</span>
<span class="k">val</span> <span class="nc">BPM_MAX</span> <span class="k">=</span> <span class="n">bpm_max</span>
<span class="cm">/* usefull function */</span>
<span class="k">def</span> <span class="n">risingedge</span><span class="o">(</span><span class="n">x</span><span class="k">:</span> <span class="kt">Bool</span><span class="o">)</span> <span class="k">=</span> <span class="n">x</span> <span class="o">&&</span> <span class="o">!</span><span class="nc">RegNext</span><span class="o">(</span><span class="n">x</span><span class="o">)</span>
<span class="k">val</span> <span class="n">tp_count</span> <span class="k">=</span> <span class="nc">RegInit</span><span class="o">(</span><span class="mf">0.</span><span class="n">asUInt</span><span class="o">(</span><span class="mf">16.</span><span class="n">W</span><span class="o">))</span>
<span class="k">val</span> <span class="o">(</span><span class="n">pulsecount</span><span class="o">,</span> <span class="n">timepulse</span><span class="o">)</span> <span class="k">=</span> <span class="nc">Counter</span><span class="o">(</span><span class="kc">true</span><span class="o">.</span><span class="n">B</span><span class="o">,</span> <span class="nc">PULSE_NS</span><span class="o">/</span><span class="n">tclk_ns</span><span class="o">)</span>
<span class="k">val</span> <span class="n">countx</span> <span class="k">=</span> <span class="nc">RegInit</span><span class="o">(</span><span class="nc">Vec</span><span class="o">(</span><span class="nc">Seq</span><span class="o">.</span><span class="n">fill</span><span class="o">(</span><span class="mi">4</span><span class="o">)(</span><span class="mf">0.</span><span class="n">asUInt</span><span class="o">(</span><span class="mf">19.</span><span class="n">W</span><span class="o">))))</span>
<span class="k">val</span> <span class="n">count_mux</span> <span class="k">=</span> <span class="nc">RegInit</span><span class="o">(</span><span class="mf">0.</span><span class="n">asUInt</span><span class="o">(</span><span class="mf">2.</span><span class="n">W</span><span class="o">))</span>
<span class="k">val</span> <span class="n">sum</span> <span class="k">=</span> <span class="nc">Wire</span><span class="o">(</span><span class="nc">UInt</span><span class="o">(</span><span class="mf">19.</span><span class="n">W</span><span class="o">))</span>
<span class="cm">/* div array calculation */</span>
<span class="k">val</span> <span class="n">x</span> <span class="k">=</span> <span class="nc">Seq</span><span class="o">.</span><span class="n">tabulate</span><span class="o">(</span><span class="n">pow</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span><span class="mi">16</span><span class="o">).</span><span class="n">toInt</span><span class="o">-</span><span class="mi">1</span><span class="o">)(</span><span class="n">n</span> <span class="k">=></span> <span class="o">((</span><span class="nc">MINUTE_NS</span><span class="o">/</span><span class="nc">PULSE_NS</span><span class="o">)/(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="o">)).</span><span class="n">U</span><span class="o">)</span>
<span class="k">val</span> <span class="n">bpm_calc</span> <span class="k">=</span> <span class="nc">RegInit</span><span class="o">(</span><span class="nc">Vec</span><span class="o">(</span><span class="n">x</span><span class="o">(</span><span class="mi">0</span><span class="o">)</span> <span class="o">+:</span> <span class="nc">Seq</span><span class="o">.</span><span class="n">tabulate</span><span class="o">(</span><span class="n">bpm_max</span><span class="o">)(</span><span class="n">n</span> <span class="k">=></span> <span class="n">x</span><span class="o">(</span><span class="n">n</span><span class="o">))))</span>
<span class="k">val</span> <span class="n">bpm_ineq</span> <span class="k">=</span> <span class="nc">RegInit</span><span class="o">(</span><span class="nc">Vec</span><span class="o">(</span><span class="nc">Seq</span><span class="o">.</span><span class="n">fill</span><span class="o">(</span><span class="mi">270</span><span class="o">)(</span><span class="mf">0.</span><span class="n">asUInt</span><span class="o">(</span><span class="mf">1.</span><span class="n">W</span><span class="o">))))</span>
<span class="n">when</span><span class="o">(</span><span class="n">timepulse</span><span class="o">)</span> <span class="o">{</span>
<span class="n">tp_count</span> <span class="o">:=</span> <span class="n">tp_count</span> <span class="o">+</span> <span class="mf">1.</span><span class="n">U</span>
<span class="o">}</span>
<span class="n">when</span><span class="o">(</span><span class="n">risingedge</span><span class="o">(</span><span class="n">io</span><span class="o">.</span><span class="n">button</span><span class="o">)){</span>
<span class="n">countx</span><span class="o">(</span><span class="n">count_mux</span><span class="o">)</span> <span class="o">:=</span> <span class="n">tp_count</span>
<span class="n">count_mux</span> <span class="o">:=</span> <span class="nc">Mux</span><span class="o">(</span><span class="n">count_mux</span> <span class="o">===</span> <span class="mf">3.</span><span class="n">U</span><span class="o">,</span> <span class="mf">0.</span><span class="n">U</span><span class="o">,</span> <span class="n">count_mux</span> <span class="o">+</span> <span class="mf">1.</span><span class="n">U</span><span class="o">)</span>
<span class="n">tp_count</span> <span class="o">:=</span> <span class="mf">0.</span><span class="n">U</span>
<span class="o">}</span>
<span class="n">sum</span> <span class="o">:=</span> <span class="n">countx</span><span class="o">(</span><span class="mi">0</span><span class="o">)</span> <span class="o">+</span> <span class="n">countx</span><span class="o">(</span><span class="mi">1</span><span class="o">)</span> <span class="o">+</span> <span class="n">countx</span><span class="o">(</span><span class="mi">2</span><span class="o">)</span> <span class="o">+</span> <span class="n">countx</span><span class="o">(</span><span class="mi">3</span><span class="o">)</span>
<span class="k">val</span> <span class="n">sum_by_4</span> <span class="k">=</span> <span class="n">sum</span><span class="o">(</span><span class="mi">18</span><span class="o">,</span> <span class="mi">2</span><span class="o">)</span>
<span class="k">for</span><span class="o">(</span><span class="n">i</span> <span class="k"><-</span> <span class="mi">0</span> <span class="n">to</span> <span class="o">(</span><span class="n">bpm_max</span><span class="o">-</span><span class="mi">1</span><span class="o">))</span> <span class="o">{</span>
<span class="n">bpm_ineq</span><span class="o">(</span><span class="n">i</span><span class="o">)</span> <span class="o">:=</span> <span class="nc">Mux</span><span class="o">(</span><span class="n">sum_by_4</span> <span class="o"><</span> <span class="n">bpm_calc</span><span class="o">(</span><span class="n">i</span><span class="o">),</span> <span class="mf">1.</span><span class="n">U</span><span class="o">,</span> <span class="mf">0.</span><span class="n">U</span><span class="o">)</span>
<span class="o">}</span>
<span class="n">io</span><span class="o">.</span><span class="n">bpm</span> <span class="o">:=</span> <span class="n">bpm_max</span><span class="o">.</span><span class="n">U</span> <span class="o">-</span> <span class="nc">PriorityEncoder</span><span class="o">(</span><span class="nc">Reverse</span><span class="o">(</span><span class="n">bpm_ineq</span><span class="o">.</span><span class="n">asUInt</span><span class="o">()))</span>
<span class="o">}</span></code></pre>
<p>La totalité du code, des outils de simulation et de visualisation sont disponibles sur un <a href="https://github.com/Martoni/TapTempoChisel">dépôt github</a> et accessible depuis la TapTempo Fédération.</p>
<p>Il est possible de simuler le composant avec la commande sbt suivante:</p>
<pre><code class="sh">$ sbt <span class="s1">'test:runMain taptempo.TapTempoMain --backend-name verilator'</span></code></pre>
<p>Un jour je ferais un vrai journal sur Chisel, mais là c'était surtout histoire d'être dans la course à TapTempo ;)</p><div><a href="https://linuxfr.org/users/martoni/journaux/un-composant-electronique-taptempo-avec-chisel3.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/114249/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/martoni/journaux/un-composant-electronique-taptempo-avec-chisel3#comments">ouvrir dans le navigateur</a>
</p>
martonihttps://linuxfr.org/nodes/114249/comments.atomtag:linuxfr.org,2005:News/376322016-11-12T21:13:28+01:002016-11-13T17:34:42+01:00Sortie de Chisel 3, un langage de description matériel basé sur ScalaLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Jonathan Bachrach vient de l’annoncer sur la liste de diffusion <em>chisel-user</em> : le <a href="https://github.com/ucb-bar/chisel3/releases/tag/v3.0-SNAPSHOT_2016-10-25">premier instantané</a> de Chisel 3 est officiellement sorti.</p>
<p>Chisel est un langage de <a href="https://fr.wikipedia.org/wiki/Langage_de_description_de_mat%C3%A9riel">description matériel</a> (HDL) basé sur le langage <a href="https://fr.wikipedia.org/wiki/Scala_%28langage%29">Scala</a>. Le langage n’étant pas reconnu par les principaux logiciels de synthèse, il génère du langage <a href="https://fr.wikipedia.org/wiki/Verilog" title="Définition Wikipédia">Verilog</a> synthétisable à la « compilation ».</p></div><ul><li>lien nᵒ 1 : <a title="https://groups.google.com/forum/#!topic/chisel-users/Byny_17AUJU" hreflang="en" href="https://linuxfr.org/redirect/98490">Annonce de la sortie du premier « snapshot » 3 de Chisel</a></li><li>lien nᵒ 2 : <a title="https://chisel.eecs.berkeley.edu/" hreflang="en" href="https://linuxfr.org/redirect/98491">Site officiel de Chisel</a></li><li>lien nᵒ 3 : <a title="http://bar.eecs.berkeley.edu/projects/2015-firrtl.html" hreflang="en" href="https://linuxfr.org/redirect/98493">FIRRTL</a></li><li>lien nᵒ 4 : <a title="http://www.veripool.org/wiki/verilator" hreflang="en" href="https://linuxfr.org/redirect/98503">Verilator</a></li><li>lien nᵒ 5 : <a title="https://github.com/ucb-bar/chisel3" hreflang="en" href="https://linuxfr.org/redirect/98510">GitHub de Chisel 3</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li><a href="#questce-que-chisel">Qu’est‐ce que Chisel ?</a></li>
<li><a href="#passage-de-chisel2-%C3%A0-chisel3">Passage de Chisel 2 à Chisel 3</a></li>
<li><a href="#petit-exemple-chisel">Petit exemple Chisel</a></li>
</ul><h2 id="questce-que-chisel">Qu’est‐ce que Chisel ?</h2>
<p>C’est un langage libre développé et soutenu par l’université de Berkeley (<a href="http://www.berkeley.edu/" title="University of California, Berkeley">UCB</a>). Université bien connue pour avoir « lancé » pas mal de standards libres d’aujourd’hui (pour rappel, BSD signifie <em>Berkeley Software Distribution</em>, soit collection de logiciels de Berkeley).</p>
<p>Contrairement à VHDL et Verilog — les deux langages de description de matériel (<a href="https://fr.wikipedia.org/wiki/Langage_de_description_de_mat%C3%A9riel" title="hardware description language">HDL</a>) considérés comme standards dans le monde du <a href="https://fr.wikipedia.org/wiki/Circuit_logique_programmable" title="field‐programmable gate array — circuit logique programmable">FPGA</a> et des <a href="https://fr.wikipedia.org/wiki/Application-specific_integrated_circuit" title="application‐specific integrated circuit — circuit intégré développé pour un client">ASIC</a> —, Chisel est un langage synthétisable et synchrone par construction. Ce qui signifie qu’une architecture décrite correctement (sans alertes) avec Chisel sera synthétisable directement.<br>
Chisel est également un langage synchrone, tous les changements d’états se font donc au rythme d’une horloge globale qui est implicite par défaut. Il existe cependant des stratégies de changement de domaines d’horloges pour les circuits complexes.</p>
<p>Chisel fait partie de ces nouveaux langages de description de matériel que l’on pourrait qualifier de <a href="http://www.fabienm.eu/flf/synchronous-synthesizable-hardware-description-language-sshdl/">SSHDL</a> — pour <em>Synchronous Synthesizable Hardware Description Language</em> —, dont font partie également <a href="https://github.com/m-labs/migen">Migen</a>, <a href="http://www.clash-lang.org/">Cλash</a> et <a href="https://github.com/SpinalHDL/SpinalHDL">SpinalHDL</a>.</p>
<h2 id="passage-de-chisel2-à-chisel3">Passage de Chisel 2 à Chisel 3</h2>
<p>La grosse différence entre Chisel 2 et Chisel 3 est l’utilisation d’un langage de <em>netlist</em> — on parle généralement de langage <a href="https://fr.wikipedia.org/wiki/Register_Transfer_Language" title="Register Transfer Language">RTL</a> — intermédiaire nommé <a href="http://bar.eecs.berkeley.edu/projects/2015-firrtl.html">FIRRTL</a> entre la description en Chisel et le Verilog généré.</p>
<p>Chisel 2 comportait un certain nombre de <em>backends</em> qui permettaient de transformer le programme Chisel en Verilog, modèle C++ ou <a href="https://fr.wikipedia.org/wiki/SystemC">SystemC</a> pour la simulation. Avec Chisel 3 la génération de ces <em>backends</em> a été abandonnée. Chisel 3 ne génère que du FIRRTL, FIRRTL génère à son tour du Verilog. Et la génération du modèle C++/SystemC a été déléguée à l’excellent <a href="http://www.veripool.org/wiki/verilator">Verilator</a> histoire de mutualiser les efforts de développement. Ce qui nous donne la chaîne de développement suivante :</p>
<pre><code>Chisel3 -> FIRRTL -> Verilog |-> C++/SystemC
|-> simulation
|−> synthèse
</code></pre>
<h2 id="petit-exemple-chisel">Petit exemple Chisel</h2>
<p>La documentation de Chisel donne comme exemple le calcul de <a href="https://fr.wikipedia.org/wiki/Plus_grand_commun_diviseur" title="Plus grand commun diviseur">PGCD</a> au moyen de l’<a href="https://fr.wikipedia.org/wiki/Algorithme_d'Euclide">algorithme d’Euclide</a>. Cet exemple permet de trouver le PGCD des deux entiers <em>a</em> et <em>b</em> donnés en entrée. La sortie se présente ensuite comme un entier sur 32 bits <em>z</em> et la sortie de validation <em>v</em> permet de signaler la fin du calcul.</p>
<pre><code class="scala"> <span class="k">import</span> <span class="nn">chisel3._</span>
<span class="k">class</span> <span class="nc">GCD</span> <span class="k">extends</span> <span class="nc">Module</span> <span class="o">{</span>
<span class="k">val</span> <span class="n">io</span> <span class="k">=</span> <span class="nc">IO</span><span class="o">(</span><span class="k">new</span> <span class="nc">Bundle</span> <span class="o">{</span>
<span class="k">val</span> <span class="n">a</span> <span class="k">=</span> <span class="nc">Input</span><span class="o">(</span><span class="nc">UInt</span><span class="o">.</span><span class="n">width</span><span class="o">(</span><span class="mi">32</span><span class="o">))</span>
<span class="k">val</span> <span class="n">b</span> <span class="k">=</span> <span class="nc">Input</span><span class="o">(</span><span class="nc">UInt</span><span class="o">.</span><span class="n">width</span><span class="o">(</span><span class="mi">32</span><span class="o">))</span>
<span class="k">val</span> <span class="n">e</span> <span class="k">=</span> <span class="nc">Input</span><span class="o">(</span><span class="nc">Bool</span><span class="o">())</span>
<span class="k">val</span> <span class="n">z</span> <span class="k">=</span> <span class="nc">Output</span><span class="o">(</span><span class="nc">UInt</span><span class="o">.</span><span class="n">width</span><span class="o">(</span><span class="mi">32</span><span class="o">))</span>
<span class="k">val</span> <span class="n">v</span> <span class="k">=</span> <span class="nc">Output</span><span class="o">(</span><span class="nc">Bool</span><span class="o">())</span>
<span class="o">})</span>
<span class="k">val</span> <span class="n">x</span> <span class="k">=</span> <span class="nc">Reg</span><span class="o">(</span><span class="nc">UInt</span><span class="o">.</span><span class="n">width</span><span class="o">(</span> <span class="mi">32</span><span class="o">))</span>
<span class="k">val</span> <span class="n">y</span> <span class="k">=</span> <span class="nc">Reg</span><span class="o">(</span><span class="nc">UInt</span><span class="o">.</span><span class="n">width</span><span class="o">(</span> <span class="mi">32</span><span class="o">))</span>
<span class="n">when</span> <span class="o">(</span><span class="n">x</span> <span class="o">></span> <span class="n">y</span><span class="o">)</span> <span class="o">{</span> <span class="n">x</span> <span class="o">:=</span> <span class="n">x</span> <span class="o">-%</span> <span class="n">y</span> <span class="o">}</span>
<span class="o">.</span><span class="n">otherwise</span> <span class="o">{</span> <span class="n">y</span> <span class="o">:=</span> <span class="n">y</span> <span class="o">-%</span> <span class="n">x</span> <span class="o">}</span>
<span class="n">when</span> <span class="o">(</span><span class="n">io</span><span class="o">.</span><span class="n">e</span><span class="o">)</span> <span class="o">{</span> <span class="n">x</span> <span class="o">:=</span> <span class="n">io</span><span class="o">.</span><span class="n">a</span><span class="o">;</span> <span class="n">y</span> <span class="o">:=</span> <span class="n">io</span><span class="o">.</span><span class="n">b</span> <span class="o">}</span>
<span class="n">io</span><span class="o">.</span><span class="n">z</span> <span class="o">:=</span> <span class="n">x</span>
<span class="n">io</span><span class="o">.</span><span class="n">v</span> <span class="o">:=</span> <span class="n">y</span> <span class="o">===</span> <span class="mf">0.</span><span class="n">U</span>
<span class="o">}</span></code></pre>
<p>On remarque le <em>bundle</em> d’entrée‐sortie <code>io = IO(new Bundle {})</code> permettant de déclarer les différents ports du module. Ce qui marque d’emblée, c’est l’absence d’entrée <em>clk</em>. C’est justement parce que c’est un langage synchrone que l’on ne voit pas l’horloge, elle sera générée à la « compilation » en FIRRTL (<code>*.fir</code>), puis en Verilog (<code>*.v</code>).</p>
<p>La base de la logique synchrone de Chisel est le registre <code>Reg()</code>. Ça n’est rien d’autre qu’une <a href="https://fr.wikipedia.org/wiki/Bascule_%28circuit_logique%29#Bascule_D">bascule <em>D</em></a> Qui recopie sa valeur d’entrée sur la sortie sur front montant de l’horloge, ce qui permet de synchroniser des valeurs d’entrée qui n’arriveraient pas en même temps et de présenter ces valeurs au prochain cycle d’horloge.</p>
<p>La connexion du registre avec les signaux d’entrée‐sortie se fait ensuite avec le symbole de connexion « := ».</p>
<p>On retrouvera tous les noms des signaux déclarés en Chisel dans le code Verilog généré. Ce qui permet un débogage plus facile et une simulation avec tous les simulateurs du marché.</p>
<p>Voici l’en‐tête Verilog généré par Chisel pour le module GCD :</p>
<pre><code class="verilog"><span class="p">...</span>
<span class="k">module</span> <span class="no">GCD</span><span class="p">(</span>
<span class="k">input</span> <span class="n">clock</span><span class="p">,</span>
<span class="k">input</span> <span class="n">reset</span><span class="p">,</span>
<span class="k">input</span> <span class="p">[</span><span class="mh">31</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">io_a</span><span class="p">,</span>
<span class="k">input</span> <span class="p">[</span><span class="mh">31</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">io_b</span><span class="p">,</span>
<span class="k">input</span> <span class="n">io_e</span><span class="p">,</span>
<span class="k">output</span> <span class="p">[</span><span class="mh">31</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">io_z</span><span class="p">,</span>
<span class="k">output</span> <span class="n">io_v</span>
<span class="p">);</span>
<span class="kt">reg</span> <span class="p">[</span><span class="mh">31</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">x</span><span class="p">;</span>
<span class="kt">reg</span> <span class="p">[</span><span class="mh">31</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="no">GEN_4</span><span class="p">;</span>
<span class="kt">reg</span> <span class="p">[</span><span class="mh">31</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">y</span><span class="p">;</span>
<span class="kt">reg</span> <span class="p">[</span><span class="mh">31</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="no">GEN_5</span><span class="p">;</span>
<span class="p">...</span></code></pre>
<p>Deux signaux d’entrées ont été ajoutés au module : ce sont l’horloge (<em>clock</em>) et la réinitialisation (<em>reset</em>). La conception étant synchrone, l’horloge est implicite et n’est ajoutée qu’au moment de générer le code synthétisable.</p>
<p>Comme Scala est un langage objet, il est possible de faire hériter le module GCD pour factoriser du code générique. Il est également possible d’instancier le module dans un module de niveau supérieur et de connecter ses entrées‐sorties avec d’autres modules.</p>
<p>D’une manière générale, l’utilisation d’un langage générique comme Scala pour définir un langage HDL permet de faire un code moins verbeux et décuple les possibilités de création et de développement HDL.</p>
<p>Chisel 3, tout comme ses concurrents Migen, Cλash et autre SpinalHDL sont désormais mûrs pour être utilisés dans de vrais projets industriels. C’est d’ailleurs la base du processeur RISC-V <a href="https://github.com/ucb-bar/riscv-sodor/wiki"><em>sodor</em></a> et <a href="https://github.com/ucb-bar/rocket-chip"><em>rocket-chip</em></a>.</p>
<p>Pourtant, les SSHDL ne sont pas encore enseignés dans les universités qui continuent à former sur VHDL en Europe et Verilog aux États‐Unis.</p>
<p>Il est temps de passer à des langages HDL de plus haut niveau et de considérer VHDL/Verilog comme l’assembleur des FPGA et ASIC !</p></div><div><a href="https://linuxfr.org/news/sortie-de-chisel-3-un-langage-de-description-materiel-base-sur-scala.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/110455/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/sortie-de-chisel-3-un-langage-de-description-materiel-base-sur-scala#comments">ouvrir dans le navigateur</a>
</p>
martoniDavy DefaudBenoît Sibaudpalm123Yves BourguignonOntologiaclaudexZeroHeurepatrick_ghttps://linuxfr.org/nodes/110455/comments.atom