tag:linuxfr.org,2005:/tags/verilog/publicLinuxFr.org : les contenus étiquetés avec « verilog »2021-10-30T22:28:06+02:00/favicon.pngtag:linuxfr.org,2005:News/406912021-10-04T11:51:54+02:002021-10-04T11:51:54+02:00Sortie de la version 0.10 de Yosys Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Yosys est devenu le pivot opensource du développement des circuits intégrés <a href="https://fr.wikipedia.org/wiki/Circuit_logique_programmable">FPGA</a> et <a href="https://fr.wikipedia.org/wiki/Application-specific_integrated_circuit">ASIC</a>.</p>
<p>Le 27 septembre 2021 a été publiée la <a href="https://github.com/YosysHQ/yosys/releases/tag/yosys-0.10">nouvelle version 0.10 de Yosys</a> sur l’hébergeur de gestionnaire de versions GitHub. <br>
Cette sortie tardive (la 0.9 date de 2019) est l’occasion de parler de ce logiciel libre de synthèse Verilog, <a href="//linuxfr.org/users/martoni/journaux/enfin-une-chaine-de-developpement-completement-open-source-pour-un-fpga">pivot de la libération des FPGA</a> (et des ASIC). Plutôt que de simplement présenter les changements nous allons présenter le logiciel et le principe de la synthèse «<a href="https://en.wikipedia.org/wiki/Register-transfer_level">RTL</a>».</p>
</div><ul><li>lien nᵒ 1 : <a title="https://github.com/YosysHQ/yosys/releases/tag/yosys-0.10" hreflang="en" href="https://linuxfr.org/redirect/109180">Changement de la version 0.10 de Yosys</a></li><li>lien nᵒ 2 : <a title="http://www.clifford.at/yosys/files/yosys_manual.pdf" hreflang="en" href="https://linuxfr.org/redirect/109201">Manuel de Yosys </a></li><li>lien nᵒ 3 : <a title="http://www.clifford.at/yosys/" hreflang="en" href="https://linuxfr.org/redirect/109202">Site officiel de Yosys</a></li><li>lien nᵒ 4 : <a title="https://linuxfr.org/tags/yosys/public" hreflang="fr" href="https://linuxfr.org/redirect/109230">Articles précédents sur LinuxFr.org</a></li></ul><div><p>Le <a href="http://www.clifford.at/yosys/files/yosys_manual.pdf">manuel de Yosys</a> représente les différentes couches d’abstractions utilisées en conception numérique.</p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f66616269656e6d2e65752f706172746167652f6c696e757866722f796f7379735f73796e7468657369735f6c6576656c732e706e67/yosys_synthesis_levels.png" alt="Couche d’abstraction utilisées en synthèse numérique" title="Source : http://fabienm.eu/partage/linuxfr/yosys_synthesis_levels.png"></p>
<p>Les couches «System Level» et «High Level» sont généralement des modèles écrits en C/C++/OpenCV/Matlab/… puis convertis en modèles «Behavioral» par un humain. Il existe quelques logiciels dit de «synthèse de haut niveau» qui permettent cette conversion en automatique, mais ça n’est pas la panacée, et (très) souvent verrouillé sur une seule marque de FPGA.</p>
<p>Le niveau «Behavioral» est celui dans lequel on décrit le comportement du composant en <a href="https://fr.wikipedia.org/wiki/Verilog"><strong>Verilog</strong></a> ou <a href="https://fr.wikipedia.org/wiki/VHDL"><strong>VHDL</strong></a>. Il est également possible aujourd’hui d’utiliser des langages comme <a href="https://clash-lang.org/">Clash</a>, <a href="https://www.chisel-lang.org/">Chisel</a> ou <a href="https://m-labs.hk/gateware/migen/">Migen</a>. Ces derniers généreront ensuite du code Verilog au niveau «RTL».<br>
Comme son nom l’indique, la couche «RTL» est une description au niveau «transfert de registres». On y décrit le comportement des registres au rythme de l’horloge. Yosys utilise son propre langage nommé RTLIL pour cette étape, mais il est parfaitement possible d’utiliser Verilog ici.<br>
Dans la couche «physique» on décrit le système au moyen de portes logiques disponibles dans le FPGA cible. À ce niveau on parlera souvent de «netlist». Cette netlist est souvent décrite au format <a href="https://fr.wikipedia.org/wiki/Electronic_Design_Interchange_Format">EDIF</a>, mais il est possible de la décrire en Verilog ou VHDL. Yosys propose également le format <a href="https://fr.wikipedia.org/wiki/JavaScript_Object_Notation">JSON</a> bien connu des développeurs JavaScript.<br>
Le niveau «switch level» n’est pas vraiment utilisé en synthèse sur FPGA. C’est la description des connexions entre transistors, elle ne fait pas vraiment de sens pour un FPGA dans la mesure où les cellules logiques sont figées dans le FPGA.</p>
<p>Arrivé au niveau portes (Physical Gate level) on quitte la synthèse – et donc yosys – pour passer à la mise en paquet (Pack), au placement puis au routage. Et on s’enfonce dans la jungle sombre et humide des logiciels gratuits-mais-pas-trop non libres fournis par les constructeurs. Il existe toutefois un logiciel libre nommé <a href="https://github.com/YosysHQ/nextpnr">nextpnr</a>, mais ça nous éloigne du sujet. Sachez juste que <strong>nextpnr</strong> est parfaitement utilisable pour certaines marques de FPGA (<strong>ICE40, Gowin, ECP5</strong> notamment).</p>
<p>Yosys est un logiciel de synthèse <strong>Verilog</strong>, il prend en entrée un source Verilog dans la couche «Behavioral Level» pour descendre dans les couches jusqu’au niveau «Physical Gate».</p>
<p>commençons donc par l’exemple de l’inverseur synchrone suivant (fichier <code>invert.v</code>):</p>
<pre><code class="Verilog"><span class="c1">// inverseur</span>
<span class="k">module</span> <span class="n">syncinvert</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="n">inval</span><span class="p">,</span>
<span class="k">output</span> <span class="n">outval</span><span class="p">);</span>
<span class="kt">reg</span> <span class="n">regval</span><span class="p">;</span>
<span class="k">assign</span> <span class="n">outval</span> <span class="o">=</span> <span class="n">regval</span><span class="p">;</span>
<span class="k">always</span><span class="p">@(</span><span class="k">posedge</span> <span class="n">clock</span><span class="p">,</span> <span class="k">posedge</span> <span class="n">reset</span><span class="p">)</span>
<span class="k">begin</span>
<span class="k">if</span><span class="p">(</span><span class="n">reset</span><span class="p">)</span>
<span class="n">regval</span> <span class="o"><=</span> <span class="mh">1</span><span class="mb">'b0</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">regval</span> <span class="o"><=</span> <span class="o">!</span><span class="n">inval</span><span class="p">;</span>
<span class="k">end</span>
<span class="k">endmodule</span></code></pre>
<p>Par défault, Yosys se présente sous la forme d’une console «REPL» (Read Eval Print Loop) et se lance en tapant son nom :</p>
<pre><code class="shell">$ yosys
/----------------------------------------------------------------------------<span class="se">\</span>
<span class="p">|</span> <span class="p">|</span>
<span class="p">|</span> yosys -- Yosys Open SYnthesis Suite <span class="p">|</span>
<span class="p">|</span> <span class="p">|</span>
<span class="p">|</span> Copyright <span class="o">(</span>C<span class="o">)</span> <span class="m">2012</span> - <span class="m">2020</span> Claire Xenia Wolf <claire@yosyshq.com> <span class="p">|</span>
<span class="p">|</span> <span class="p">|</span>
<span class="p">|</span> Permission to use, copy, modify, and/or distribute this software <span class="k">for</span> any <span class="p">|</span>
<span class="p">|</span> purpose with or without fee is hereby granted, provided that the above <span class="p">|</span>
<span class="p">|</span> copyright notice and this permission notice appear in all copies. <span class="p">|</span>
<span class="p">|</span> <span class="p">|</span>
<span class="p">|</span> THE SOFTWARE IS PROVIDED <span class="s2">"AS IS"</span> AND THE AUTHOR DISCLAIMS ALL WARRANTIES <span class="p">|</span>
<span class="p">|</span> WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF <span class="p">|</span>
<span class="p">|</span> MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR <span class="p">|</span>
<span class="p">|</span> ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES <span class="p">|</span>
<span class="p">|</span> WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN <span class="p">|</span>
<span class="p">|</span> ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF <span class="p">|</span>
<span class="p">|</span> OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. <span class="p">|</span>
<span class="p">|</span> <span class="p">|</span>
<span class="se">\-</span>---------------------------------------------------------------------------/
Yosys <span class="m">0</span>.10+0 <span class="o">(</span>git sha1 070cad5f4, clang <span class="m">8</span>.0.0-svn345496-1~exp1+0~20181029105533.852~1.gbpf10f36 -fPIC -Os<span class="o">)</span>
yosys></code></pre>
<p>Premier changement de cette version : l’auteur n’est plus <strong>Clifford Wolf</strong> mais <strong>Claire Xenia Wolf</strong>. Si la date du début du copyright n’a pas changée c’est que les deux sont une seule et même personne, elle a «juste» <a href="http://www.clifford.at/">changé de prénom</a> et d’état civil.</p>
<p>La ligne de commande se comporte comme une ligne de commande shell classique, avec le rappel des commandes par flèche haut/bas, et la complétion avec Ctrl+R et tabulation.<br>
On charge son fichier source verilog avec la commande <code>read_verilog</code>.</p>
<pre><code class="shell">yosys> read_verilog invert.v
<span class="m">1</span>. Executing Verilog-2005 frontend: invert.v
Parsing Verilog input from <span class="sb">`</span>invert.v<span class="s1">' to AST representation.</span>
<span class="s1">Generating RTLIL representation for module `\syncinvert'</span>.
Successfully finished Verilog frontend.</code></pre>
<p>Yosys nous informe ici qu’il a bien lu et analysé le fichier source. Le «<a href="https://www.reddit.com/r/FPGA/comments/b1qiru/definition_of_gateware/">gateware</a>» est bien conforme au standard Verilog-2005 et a été converti dans le langage interne nommé RTLIL (RTL Intermediate Language).</p>
<p>On peut lister les modules chargés en mémoire grâce à la commande <code>ls</code>.</p>
<pre><code class="shell">yosys> ls
<span class="m">1</span> modules:
syncinvert</code></pre>
<p>Et afficher une vue graphique du module avec <code>show</code>:</p>
<pre><code class="shell">yosys> show syncinvert
<span class="m">4</span>. Generating Graphviz representation of design.
Writing dot description to <span class="sb">`</span>/home/fabien/.yosys_show.dot<span class="s1">'.</span>
<span class="s1">Dumping module syncinvert to page 1.</span>
<span class="s1">Exec: { test -f '</span>/home/user/.yosys_show.dot.pid<span class="s1">' && fuser -s '</span>/home/user/.yosys_show.dot.pid<span class="s1">' 2> /dev/null; } || ( echo $$ >&3; exec xdot '</span>/home/fabien/.yosys_show.dot<span class="s1">'; ) 3> '</span>/home/user/.yosys_show.dot.pid<span class="err">'</span> <span class="p">&</span></code></pre>
<p>Qui affiche l’image suivante </p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f66616269656e6d2e65752f706172746167652f6c696e757866722f696e7665727465725f78646f742e706e67/inverter_xdot.png" alt="Rendu xdot de l’inverseur" title="Source : http://fabienm.eu/partage/linuxfr/inverter_xdot.png"></p>
<p>Cette simple lecture du fichier verilog nous a fait passer la première étape de la synthèse. Nous sommes presque descendus au niveau de la couche «RTL» de la synthèse. Presque, car il faut encore «mapper» la procédure que l’on voit au centre avec la commande <code>proc</code>:</p>
<pre><code class="shell">yosys> proc
<span class="m">10</span>. Executing PROC pass <span class="o">(</span>convert processes to netlists<span class="o">)</span>.
<span class="m">10</span>.1. Executing PROC_CLEAN pass <span class="o">(</span>remove empty switches from decision trees<span class="o">)</span>.
Cleaned up <span class="m">0</span> empty switches.
<span class="m">10</span>.2. Executing PROC_RMDEAD pass <span class="o">(</span>remove dead branches from decision trees<span class="o">)</span>.
Removed a total of <span class="m">0</span> dead cases.
<span class="m">10</span>.3. Executing PROC_PRUNE pass <span class="o">(</span>remove redundant assignments in processes<span class="o">)</span>.
Removed <span class="m">0</span> redundant assignments.
Promoted <span class="m">0</span> assignments to connections.
<span class="m">10</span>.4. Executing PROC_INIT pass <span class="o">(</span>extract init attributes<span class="o">)</span>.
<span class="m">10</span>.5. Executing PROC_ARST pass <span class="o">(</span>detect async resets in processes<span class="o">)</span>.
<span class="m">10</span>.6. Executing PROC_MUX pass <span class="o">(</span>convert decision trees to multiplexers<span class="o">)</span>.
<span class="m">10</span>.7. Executing PROC_DLATCH pass <span class="o">(</span>convert process syncs to latches<span class="o">)</span>.
<span class="m">10</span>.8. Executing PROC_DFF pass <span class="o">(</span>convert process syncs to FFs<span class="o">)</span>.
<span class="m">10</span>.9. Executing PROC_MEMWR pass <span class="o">(</span>convert process memory writes to cells<span class="o">)</span>.
<span class="m">10</span>.10. Executing PROC_CLEAN pass <span class="o">(</span>remove empty switches from decision trees<span class="o">)</span>.
Cleaned up <span class="m">0</span> empty switches.
<span class="m">10</span>.11. Executing OPT_EXPR pass <span class="o">(</span>perform const folding<span class="o">)</span>.
Optimizing module syncinvert.</code></pre>
<p>Le résultat ressemble beaucoup plus à la <a href="https://fr.wikipedia.org/wiki/Bascule_%28circuit_logique%29#Bascule_D">bascule D</a> que l’on connaît.</p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f66616269656e6d2e65752f706172746167652f6c696e757866722f796f7379735f6d61707065645f72746c2e706e67/yosys_mapped_rtl.png" alt="Rendu xdot de l’inverseur «mappé»" title="Source : http://fabienm.eu/partage/linuxfr/yosys_mapped_rtl.png"></p>
<p>On peut optimiser ce graphe avec la commande <code>opt</code>, ce qui supprimera la branche inutile <code>BUF -> $0\regval[0:0]</code>.</p>
<p>S’ensuit toute une série de commandes d’optimisation comme <code>memory</code> pour détecter les tableaux et utiliser des blocs de ram si possible ou <code>techmap</code> pour «mapper» les cellules d’une bibliothèque donnée.</p>
<pre><code class="shell">yosys> opt<span class="p">;</span> memory<span class="p">;</span> opt<span class="p">;</span> techmap<span class="p">;</span> opt</code></pre>
<p><img src="//img.linuxfr.org/img/687474703a2f2f66616269656e6d2e65752f706172746167652f6c696e757866722f796f7379735f746563686d61702e706e67/yosys_techmap.png" alt="Rendu xdot de l’inverseur mappé avec `techmap`" title="Source : http://fabienm.eu/partage/linuxfr/yosys_techmap.png"></p>
<p>Notez que toutes ces commandes étant des commandes d’optimisations, rien n’interdit de les relancer pour améliorer encore l’optimisation (ici les optimisation sont totalement inutiles vu la simplicité du schéma).</p>
<p>Beaucoup d’étapes dépendantes de la cible sont ensuite nécessaires pour obtenir une netlist correspondant au composant. Ces étapes étant différentes en fonction de l’architecture cible. Yosys inclut des scripts pour chaque composant supporté.</p>
<p>Par exemple, si nous voulons synthétiser pour <a href="http://www.fabienm.eu/flf/une-led-qui-clignote-sur-icestick-vite-vite-vite/">icestick</a>, le FPGA monté sur la carte est un <strong>ice40</strong>, nous pourrons donc utiliser le script nommé <code>synth_ice40</code> :</p>
<pre><code class="shell">yosys> synth_ice40
<span class="o">[</span>...<span class="o">]</span>
<span class="m">37</span>.47. Printing statistics.
<span class="o">===</span> <span class="nv">syncinvert</span> <span class="o">===</span>
Number of wires: <span class="m">6</span>
Number of wire bits: <span class="m">6</span>
Number of public wires: <span class="m">6</span>
Number of public wire bits: <span class="m">6</span>
Number of memories: <span class="m">0</span>
Number of memory bits: <span class="m">0</span>
Number of processes: <span class="m">0</span>
Number of cells: <span class="m">2</span>
SB_DFFR <span class="m">1</span>
SB_LUT4 <span class="m">1</span>
<span class="m">37</span>.48. Executing CHECK pass <span class="o">(</span>checking <span class="k">for</span> obvious problems<span class="o">)</span>.
Checking module syncinvert...
Found and reported <span class="m">0</span> problems.</code></pre>
<p>Le lecteur attentif reconnaîtra la <a href="https://magma-mantle.readthedocs.io/en/stable/ice40/">LUT 4 entrées</a> et la basculeD de l'<a href="https://www.latticesemi.com/iCE40">ICE40</a> dans le schéma généré :</p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f66616269656e6d2e65752f706172746167652f6c696e757866722f796f7379735f69636534302e706e67/yosys_ice40.png" alt="Rendu xdot de l’inverseur synthétisé pour ICE40" title="Source : http://fabienm.eu/partage/linuxfr/yosys_ice40.png"></p>
<p>Pour connaitre les scripts de synthèse disponibles dans yosys il suffit d’utiliser la complétion de commande avec <code>synth_</code> :</p>
<pre><code class="shell">yosys> synth_<TAB>
synth_achronix synth_coolrunner2 synth_ecp5 synth_gowin synth_ice40 synth_intel_alm synth_nexus synth_sf2
synth_anlogic synth_easic synth_efinix synth_greenpak4 synth_intel synth_machxo2 synth_quicklogic synth_xilinx</code></pre>
<p>Ce qui nous donne 16 modèles de FPGA supporté «officiellement» par Yosys.</p>
<p>Il n’est pas obligatoire d’avoir un script <code>synth_</code> pour pouvoir synthétiser pour un modèle de FPGA du moment que l’on fournit la bibliothèque des primitives. <a href="http://pepijndevos.nl/2019/07/18/vhdl-to-pcb.html">Pepijn De Vos</a> s’est par exemple amusé à synthétiser vers une bibliothèque de composants en logique discrète (la série des 74-* pour ceux qui connaissent un peu l'électronique). Il a ensuite produit, assemblé et soudé la carte électronique correspondante.</p>
<p>Mais! Pepijn est parti d’un gateware écrit en VHDL ! En quoi cela concerne-t-il yosys qui est censé être un logiciel de synthèse <strong>Verilog</strong> ?</p>
<p>Pepijn a utilisé pour cela une <a href="https://github.com/ghdl/ghdl-yosys-plugin">extension de yosys</a> permettant de se connecter au logiciel <a href="//linuxfr.org/news/sortie-de-ghdl-version-1-0-0">GHDL</a>. Avec cette extension (encore en bêta mais déjà bien avancée), le <a href="https://en.wikipedia.org/wiki/VHDL">VHDL</a> est décodé avec <strong>GHDL</strong> qui transmet ensuite les informations à Yosys pour la synthèse. Et comme yosys est capable de sortir une version verilog de sa représentation interne RTLIL, on peut s’en servir pour <a href="http://www.fabienm.eu/flf/convertir-du-vhdl-en-verilog-librement-avec-yosys-et-ghdl/">faire de la conversion VHDL->Verilog sans problème</a>.</p>
<p>Notre inverseur est désormais synthétisé. Nous pouvons donc l’enregistrer au format de notre choix pour passer ensuite au placement routage.</p>
<p>On peut l’écrire au format Verilog par exemple si nous souhaitons le simuler ou tout simplement lire la netlist :</p>
<pre><code class="shell">yosys> write_verilog invert_synth.v
<span class="m">41</span>. Executing Verilog backend.
Dumping module <span class="sb">`</span><span class="se">\s</span>yncinvert<span class="err">'</span>.</code></pre>
<p>Ce qui donnera les sources suivantes :</p>
<pre><code class="Verilog"><span class="cm">/* Generated by Yosys 0.10+0 (git sha1 070cad5f4, clang 8.0.0-svn345496-1~exp1+0~20181029105533.852~1.gbpf10f36 -fPIC -Os) */</span>
<span class="p">(</span><span class="o">*</span> <span class="n">top</span> <span class="o">=</span> <span class="mh">1</span> <span class="o">*</span><span class="p">)</span>
<span class="p">(</span><span class="o">*</span> <span class="n">src</span> <span class="o">=</span> <span class="s">"invert.v:2.1-19.10"</span> <span class="o">*</span><span class="p">)</span>
<span class="k">module</span> <span class="n">syncinvert</span><span class="p">(</span><span class="n">clock</span><span class="p">,</span> <span class="n">reset</span><span class="p">,</span> <span class="n">inval</span><span class="p">,</span> <span class="n">outval</span><span class="p">);</span>
<span class="p">(</span><span class="o">*</span> <span class="n">src</span> <span class="o">=</span> <span class="s">"invert.v:3.11-3.16"</span> <span class="o">*</span><span class="p">)</span>
<span class="k">input</span> <span class="n">clock</span><span class="p">;</span>
<span class="p">(</span><span class="o">*</span> <span class="n">src</span> <span class="o">=</span> <span class="s">"invert.v:5.11-5.16"</span> <span class="o">*</span><span class="p">)</span>
<span class="k">input</span> <span class="n">inval</span><span class="p">;</span>
<span class="p">(</span><span class="o">*</span> <span class="n">src</span> <span class="o">=</span> <span class="s">"invert.v:6.12-6.18"</span> <span class="o">*</span><span class="p">)</span>
<span class="k">output</span> <span class="n">outval</span><span class="p">;</span>
<span class="p">(</span><span class="o">*</span> <span class="n">src</span> <span class="o">=</span> <span class="s">"invert.v:7.5-7.11"</span> <span class="o">*</span><span class="p">)</span>
<span class="kt">wire</span> <span class="n">regval</span><span class="p">;</span>
<span class="p">(</span><span class="o">*</span> <span class="n">src</span> <span class="o">=</span> <span class="s">"invert.v:11.1-17.4"</span> <span class="o">*</span><span class="p">)</span>
<span class="kt">wire</span> <span class="n">regval_SB_DFFR_Q_D</span><span class="p">;</span>
<span class="p">(</span><span class="o">*</span> <span class="n">src</span> <span class="o">=</span> <span class="s">"invert.v:4.11-4.16"</span> <span class="o">*</span><span class="p">)</span>
<span class="k">input</span> <span class="n">reset</span><span class="p">;</span>
<span class="p">(</span><span class="o">*</span> <span class="n">module_not_derived</span> <span class="o">=</span> <span class="mh">32</span><span class="mi">'d1</span> <span class="o">*</span><span class="p">)</span>
<span class="p">(</span><span class="o">*</span> <span class="n">src</span> <span class="o">=</span> <span class="s">"/usr/local/bin/../share/yosys/ice40/cells_map.v:12.34-13.52"</span> <span class="o">*</span><span class="p">)</span>
<span class="no">SB_LUT4</span> <span class="p">#(</span>
<span class="p">.</span><span class="no">LUT_INIT</span><span class="p">(</span><span class="mh">16'h00ff</span><span class="p">)</span>
<span class="p">)</span> <span class="n">inval_SB_LUT4_I3</span> <span class="p">(</span>
<span class="p">.</span><span class="no">I0</span><span class="p">(</span><span class="mh">1'h0</span><span class="p">),</span>
<span class="p">.</span><span class="no">I1</span><span class="p">(</span><span class="mh">1'h0</span><span class="p">),</span>
<span class="p">.</span><span class="no">I2</span><span class="p">(</span><span class="mh">1'h0</span><span class="p">),</span>
<span class="p">.</span><span class="no">I3</span><span class="p">(</span><span class="n">inval</span><span class="p">),</span>
<span class="p">.</span><span class="no">O</span><span class="p">(</span><span class="n">regval_SB_DFFR_Q_D</span><span class="p">)</span>
<span class="p">);</span>
<span class="p">(</span><span class="o">*</span> <span class="n">module_not_derived</span> <span class="o">=</span> <span class="mh">32</span><span class="mi">'d1</span> <span class="o">*</span><span class="p">)</span>
<span class="p">(</span><span class="o">*</span> <span class="n">src</span> <span class="o">=</span> <span class="s">"invert.v:11.1-17.4|/usr/local/bin/../share/yosys/ice40/ff_map.v:9.57-9.103"</span> <span class="o">*</span><span class="p">)</span>
<span class="no">SB_DFFR</span> <span class="n">regval_SB_DFFR_Q</span> <span class="p">(</span>
<span class="p">.</span><span class="no">C</span><span class="p">(</span><span class="n">clock</span><span class="p">),</span>
<span class="p">.</span><span class="no">D</span><span class="p">(</span><span class="n">regval_SB_DFFR_Q_D</span><span class="p">),</span>
<span class="p">.</span><span class="no">Q</span><span class="p">(</span><span class="n">regval</span><span class="p">),</span>
<span class="p">.</span><span class="no">R</span><span class="p">(</span><span class="n">reset</span><span class="p">)</span>
<span class="p">);</span>
<span class="k">assign</span> <span class="n">outval</span> <span class="o">=</span> <span class="n">regval</span><span class="p">;</span>
<span class="k">endmodule</span></code></pre>
<p>Les sources sont annotées avec des références au verilog initial. On repère bien la bascule SB_DFFR et la SB_LUT4 avec sa configuration.<br>
Et dans la mesure du possible, les noms de registres ont été gardés, ce qui rend le fichier assez facile à lire.</p>
<p>Pour le placement routage, si on utilise <strong>nextpnr</strong> il faudra «sortir» au format json :</p>
<pre><code class="shell">yosys> write_json invert.json
<span class="m">42</span>. Executing JSON backend.</code></pre>
<p>Le fichier <code>invert.json</code> est beaucoup plus large que la sortie verilog (9779 lignes).<br>
Les différents formats de sortie disponibles sont visibles avec la complétion de commande <code>write_</code> :</p>
<pre><code class="shell">yosys> write_<TAB>
write_aiger write_btor write_edif write_firrtl write_intersynth write_rtlil write_smt2 write_spice write_verilog
write_blif write_cxxrtl write_file write_ilang write_json write_simplec write_smv write_table write_xaiger</code></pre>
<p>Cette possibilité de convertir dans différents formats le verilog initial fait de Yosys le couteau suisse du gateware. On peut s’en servir pour faire de la synthèse à destination des FPGA bien sûr, mais il est possible de «mapper» sur d’autres bibliothèques pour faire des PCB «discret» comme on l’a vu avec Pepijn De Vos.<br>
Il est également possible de faire de la synthèse à destination des ASIC. Yosys est d’ailleurs utilisé par la chaîne de développement opensource <a href="https://github.com/The-OpenROAD-Project/OpenLane">OpenLane</a>.</p>
<p>Enfin, les modèles synthétisés par yosys peuvent servir à faire de la preuve formelle, à partir de <a href="http://www.testandverification.com/wp-content/uploads/2017/Formal_Verification/Clifford_Wolf.pdf">sources verilog</a> mais également <a href="https://vhdlwhiz.com/formal-verification-in-vhdl-using-psl/">VHDL</a>.</p>
<p>En règle générale, il n’est pas nécessaire de connaître les détails des commandes de Yosys. L’utilisation de yosys est enfouie dans les scripts et autres Makefile des outils utilisés.</p>
<p>Bref, en quelques années, Yosys est devenu le pivot opensource du développement FPGA et ASIC. Il méritait bien une dépêche sur LinuxFr.org !</p>
</div><div><a href="https://linuxfr.org/news/sortie-de-la-version-0-10-de-yosys.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/125549/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/sortie-de-la-version-0-10-de-yosys#comments">ouvrir dans le navigateur</a>
</p>
martonipalm123Benoît SibaudPierre JarillonNicolas Boulayhttps://linuxfr.org/nodes/125549/comments.atomtag:linuxfr.org,2005:Diary/391322020-05-05T18:34:31+02:002020-05-05T23:14:53+02:00Verilog && récursivité(récursivité(récursivité( ERROR: STACK OVERFLOWLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<p>Cher journal,</p>
<p>Hier, j'ai découvert que l'on pouvait faire du code récursif en <a href="https://fr.wikipedia.org/wiki/Verilog">Verilog</a>. </p>
<h2 id="toc-le-verilog-quest-ce-que-cest-que-quoi">Le verilog, qu'est-ce que c'est que quoi ?</h2>
<p>Verilog est un vieux langage de description matériel. Il sert à modéliser des circuits qui pourront être ensuite <a href="https://fr.wikipedia.org/wiki/Simulateur_logique">simulé</a> et être implémenté sur un <a href="https://fr.wikipedia.org/wiki/Circuit_logique_programmable">FPGA</a> ou en <a href="https://fr.wikipedia.org/wiki/Application-specific_integrated_circuit">ASIC</a>.</p>
<p>En guise d'exemple, voici un petit module qui fait clignoter une DEL :</p>
<pre><code class="verilog"><span class="cp">`define CLOCK_FREQUENCY 25000000 </span><span class="c1">// Number of clock tick in 1 second - 25Mhz</span>
<span class="cp">`define LED_TICKS_COUNT `CLOCK_FREQUENCY </span><span class="c1">// Switch the LED state every second</span>
<span class="k">module</span> <span class="n">LedBlink</span><span class="p">(</span><span class="n">o_led</span><span class="p">,</span> <span class="n">i_clock</span><span class="p">,</span> <span class="n">i_nreset</span><span class="p">);</span>
<span class="k">output</span> <span class="kt">reg</span> <span class="n">o_led</span><span class="p">;</span>
<span class="k">input</span> <span class="n">i_clock</span><span class="p">,</span> <span class="n">i_nreset</span><span class="p">;</span>
<span class="kt">reg</span> <span class="p">[</span><span class="mh">24</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">r_counter</span><span class="p">;</span> <span class="c1">// 25 bits counter, up to 33,554,341</span>
<span class="k">always</span> <span class="p">@(</span><span class="k">posedge</span> <span class="n">i_clock</span><span class="p">,</span> <span class="k">negedge</span> <span class="n">i_nreset</span><span class="p">)</span> <span class="k">begin</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">i_nreset</span><span class="p">)</span> <span class="k">begin</span>
<span class="c1">// Reset the counter and switch off the LED</span>
<span class="n">r_counter</span> <span class="o"><=</span> <span class="mh">0</span><span class="p">;</span>
<span class="n">o_led</span> <span class="o"><=</span> <span class="mh">0</span><span class="p">;</span>
<span class="k">end</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">r_counter</span> <span class="o">==</span> <span class="no">`LED_TICKS_COUNT</span><span class="p">)</span> <span class="k">begin</span>
<span class="c1">// Reset the counter and switch the LED state</span>
<span class="n">r_counter</span> <span class="o"><=</span> <span class="mh">0</span><span class="p">;</span>
<span class="n">o_led</span> <span class="o"><=</span> <span class="o">!</span><span class="n">o_led</span><span class="p">;</span>
<span class="k">end</span> <span class="k">else</span> <span class="k">begin</span>
<span class="c1">// Update the counter</span>
<span class="n">r_counter</span> <span class="o"><=</span> <span class="n">r_counter</span> <span class="o">+</span> <span class="mh">1</span><span class="p">;</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">endmodule</span></code></pre>
<p>Le code ci dessus est équivalent à ce circuit :<br>
<img src="//img.linuxfr.org/img/68747470733a2f2f692e7a63726166742e66722f333733313834313538383638373434392e706e67/3731841588687449.png" alt="Représentation graphique du module LedBlink" title="Source : https://i.zcraft.fr/3731841588687449.png"></p>
<h2 id="toc-paramètres">Paramètres</h2>
<p>Il est possible de rendre les modules plus génériques via l'utilisation de paramètres dont la valeur est définissable lors de instanciation du module. Par exemple, au lieu d'avoir un module qui fait des additions sur 8 bits et un autre sur 16 bits, il est possible d'en avoir qu'un seul dont la taille est générique :</p>
<pre><code class="verilog"><span class="k">module</span> <span class="n">Adder</span><span class="p">(</span><span class="n">z</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">);</span>
<span class="c1">// Paramètre permettant de définir la taille de l'adder</span>
<span class="k">parameter</span> <span class="no">WIDTH</span> <span class="o">=</span> <span class="mh">8</span><span class="p">;</span> <span class="c1">// Valeur par défaut</span>
<span class="c1">// La taille des entrées/sorties dépend du paramètre WIDTH</span>
<span class="k">output</span> <span class="p">[</span><span class="no">WIDTH</span> <span class="o">-</span> <span class="mh">1</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">z</span><span class="p">;</span>
<span class="k">input</span> <span class="p">[</span><span class="no">WIDTH</span> <span class="o">-</span> <span class="mh">1</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">;</span>
<span class="k">assign</span> <span class="n">z</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">;</span>
<span class="k">endmodule</span>
<span class="k">module</span> <span class="n">Foo</span><span class="p">(</span><span class="n">z1</span><span class="p">,</span> <span class="n">z2</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">);</span>
<span class="k">output</span> <span class="p">[</span><span class="mh">7</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">z1</span><span class="p">;</span>
<span class="k">output</span> <span class="p">[</span><span class="mh">15</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">z2</span><span class="p">;</span>
<span class="k">input</span> <span class="p">[</span><span class="mh">15</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">;</span>
<span class="c1">// Instantiation de l'adder en utilisant la valeur par défaut du paramètre</span>
<span class="n">Adder</span> <span class="n">adder8</span><span class="p">(.</span><span class="n">z</span><span class="p">(</span><span class="n">z1</span><span class="p">),</span> <span class="p">.</span><span class="n">a</span><span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="mh">7</span><span class="o">:</span><span class="mh">0</span><span class="p">]),</span> <span class="p">.</span><span class="n">b</span><span class="p">(</span><span class="n">b</span><span class="p">[</span><span class="mh">7</span><span class="o">:</span><span class="mh">0</span><span class="p">]));</span>
<span class="c1">// Instantiation de l'adder en choississant la valeur du paramètre</span>
<span class="n">Adder</span> <span class="p">#(.</span><span class="no">WIDTH</span><span class="p">(</span><span class="mh">16</span><span class="p">))</span> <span class="n">adder16</span><span class="p">(.</span><span class="n">z</span><span class="p">(</span><span class="n">z2</span><span class="p">),</span> <span class="p">.</span><span class="n">a</span><span class="p">(</span><span class="n">a</span><span class="p">),</span> <span class="p">.</span><span class="n">b</span><span class="p">(</span><span class="n">b</span><span class="p">));</span>
<span class="k">endmodule</span></code></pre>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f692e7a63726166742e66722f353236303634313538383639303231362e706e67/5260641588690216.png" alt="Diagramme montrant les adders 8 et 16 bits" title="Source : https://i.zcraft.fr/5260641588690216.png"></p>
<h2 id="toc-la-récursivité-avec-un-exemple-à-la-con">La récursivité avec un exemple à la con</h2>
<p>Il est possible de créer une nouvelle instance d'un module en lui même et de jouer avec les paramètres pour définir la condition d'arrêt.</p>
<p>Nous allons prendre l'exemple d'un <a href="https://fr.wikipedia.org/wiki/Registre_%C3%A0_d%C3%A9calage">registre à décalage</a>. Une manière de l'écrire serait de la manière suivante :</p>
<pre><code class="verilog"> <span class="k">module</span> <span class="n">ShiftRegister</span><span class="p">(</span><span class="n">q</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">clk</span><span class="p">);</span>
<span class="k">parameter</span> <span class="no">WIDTH</span> <span class="o">=</span> <span class="mh">8</span><span class="p">;</span>
<span class="k">output</span> <span class="kt">reg</span> <span class="n">q</span><span class="p">;</span>
<span class="k">input</span> <span class="n">d</span><span class="p">,</span> <span class="n">clk</span><span class="p">;</span>
<span class="kt">reg</span> <span class="p">[</span><span class="no">WIDTH</span> <span class="o">-</span> <span class="mh">2</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">data</span><span class="p">;</span>
<span class="k">always</span> <span class="p">@(</span><span class="k">posedge</span> <span class="n">clk</span><span class="p">)</span> <span class="k">begin</span>
<span class="p">{</span><span class="n">q</span><span class="p">,</span> <span class="n">data</span><span class="p">}</span> <span class="o"><=</span> <span class="p">{</span><span class="n">data</span><span class="p">,</span> <span class="n">d</span><span class="p">};</span>
<span class="k">end</span>
<span class="k">endmodule</span></code></pre>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f692e7a63726166742e66722f373737313739313538383639313231302e706e67/7771791588691210.png" alt="Diagramme du registre à décalage" title="Source : https://i.zcraft.fr/7771791588691210.png"></p>
<p>Mais pourquoi faire simple et propre quand on peut utiliser de la récursion ? Mr Olivier Cogis, mon professeur d'algorithmie, disait qu'une forêt est une forêt vide ou un arbre et une forêt. Réutilisons ce principe pour définir notre registre à bascule :</p>
<pre><code class="verilog"> <span class="k">module</span> <span class="n">ShiftRegister</span><span class="p">(</span><span class="n">q</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">clk</span><span class="p">);</span>
<span class="k">parameter</span> <span class="no">WIDTH</span> <span class="o">=</span> <span class="mh">4</span><span class="p">;</span>
<span class="k">output</span> <span class="n">q</span><span class="p">;</span>
<span class="k">input</span> <span class="n">d</span><span class="p">,</span> <span class="n">clk</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="no">WIDTH</span> <span class="o"><=</span> <span class="mh">0</span><span class="p">)</span> <span class="k">begin</span>
<span class="c1">// Forêt vide</span>
<span class="k">assign</span> <span class="n">q</span> <span class="o">=</span> <span class="n">d</span><span class="p">;</span> <span class="c1">// passthrough</span>
<span class="k">end</span> <span class="k">else</span> <span class="k">begin</span>
<span class="c1">// Un arbre</span>
<span class="kt">reg</span> <span class="n">data</span><span class="p">;</span>
<span class="k">always</span> <span class="p">@(</span><span class="k">posedge</span> <span class="n">clk</span><span class="p">)</span> <span class="k">begin</span>
<span class="n">data</span> <span class="o"><=</span> <span class="n">d</span><span class="p">;</span>
<span class="k">end</span>
<span class="c1">// Une forêt</span>
<span class="n">ShiftRegister</span> <span class="p">#(.</span><span class="no">WIDTH</span><span class="p">(</span><span class="no">WIDTH</span> <span class="o">-</span> <span class="mh">1</span><span class="p">))</span> <span class="n">sr</span><span class="p">(.</span><span class="n">q</span><span class="p">(</span><span class="n">q</span><span class="p">),</span> <span class="p">.</span><span class="n">d</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="p">.</span><span class="n">clk</span><span class="p">(</span><span class="n">clk</span><span class="p">));</span>
<span class="k">end</span>
<span class="k">endmodule</span></code></pre>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f692e7a63726166742e66722f343539313736313538383639323232372e706e67/4591761588692227.png" alt="Diagramme du registre à décalage recursif" title="Source : https://i.zcraft.fr/4591761588692227.png"></p>
<h2 id="toc-multiplexeur">Multiplexeur</h2>
<p>Bon, je ne vais te mentir, l'exemple ci dessus n'est pas vraiment une bonne pratique. Mais il a le mérite d'être pour introduire le sujet. Par contre, j'ai trouvé un cas où la récursion est bien pratique : l'écriture d'un <a href="https://fr.wikipedia.org/wiki/Multiplexeur">multiplexeur</a>, mux de son petit nom. </p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f7468756d622f332f33392f4d756c7469706c657865725f322d746f2d312e7376672f31373570782d4d756c7469706c657865725f322d746f2d312e7376672e706e67/175px-Multiplexer_2-to-1.svg.png" alt="Un mux 2" title="Source : https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/Multiplexer_2-to-1.svg/175px-Multiplexer_2-to-1.svg.png"></p>
<p>Le mux de base, le mux 2, possède 2 entrées (d'où le nom), un sélecteur S et d'unes ortie Z. Quand S vaut 0, on retrouve la valeur de A sur la sortie Z sinon celle de B. Sa table de vérité est </p>
<pre><code>B A S | Z
---------
X 0 0 | 0
X 1 0 | 1
0 X 1 | 0
1 X 1 | 1
</code></pre>
<p>que l'on peut simplifier en</p>
<pre><code>S | Z
-----
0 | A
1 | B
</code></pre>
<p>Bref, c'est l'opérateur ternaire de l'électronique (<code>Z = S ? B : A</code>).</p>
<p>En chaînant les mux2 sous forme d'arbre, il est possible d'obtenir des multiplexeurs plus grands, tel que le mux4 :<br>
<img src="//img.linuxfr.org/img/68747470733a2f2f692e7a63726166742e66722f333732343839313538383639363535392e706e67/3724891588696559.png" alt="Diagramme d'un mux 4" title="Source : https://i.zcraft.fr/3724891588696559.png"></p>
<p>et le mux 8 :<br>
<img src="//img.linuxfr.org/img/68747470733a2f2f692e7a63726166742e66722f333435333037313538383639363434382e706e67/3453071588696448.png" alt="Diagramme d'un mux 8" title="Source : https://i.zcraft.fr/3453071588696448.png"></p>
<p>Comme tu est très perspicace, tu auras remarqué que un mux <code>2^S</code> est constitué de 2 mux <code>2^(S - 1)</code> et un mux 2. Le mux 4 (S = 2) est ainsi constitué de 2 mux 2 reliés par un mux 2 et le mux 8 (S = 3) est constitué de 2 mux 4 relié par un mux 2. </p>
<pre><code class="verilog"><span class="k">module</span> <span class="n">Mux</span><span class="p">(</span><span class="n">z</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">s</span><span class="p">);</span>
<span class="k">parameter</span> <span class="no">S</span> <span class="o">=</span> <span class="mh">3</span><span class="p">;</span>
<span class="k">output</span> <span class="n">z</span><span class="p">;</span>
<span class="k">input</span> <span class="p">[</span><span class="mh">2</span> <span class="o">**</span> <span class="no">S</span> <span class="o">-</span> <span class="mh">1</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">d</span><span class="p">;</span>
<span class="k">input</span> <span class="p">[</span><span class="no">S</span> <span class="o">-</span> <span class="mh">1</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">s</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="no">S</span> <span class="o">==</span> <span class="mh">1</span><span class="p">)</span> <span class="k">begin</span>
<span class="k">assign</span> <span class="n">z</span> <span class="o">=</span> <span class="n">s</span> <span class="o">?</span> <span class="n">d</span><span class="p">[</span><span class="mh">1</span><span class="p">]</span> <span class="o">:</span> <span class="n">d</span><span class="p">[</span><span class="mh">0</span><span class="p">];</span>
<span class="k">end</span> <span class="k">else</span> <span class="k">begin</span>
<span class="kt">wire</span> <span class="n">z1</span><span class="p">,</span> <span class="n">z2</span><span class="p">;</span>
<span class="n">Mux</span> <span class="p">#(.</span><span class="no">S</span><span class="p">(</span><span class="no">S</span> <span class="o">-</span> <span class="mh">1</span><span class="p">))</span> <span class="n">mux1</span><span class="p">(.</span><span class="n">z</span><span class="p">(</span><span class="n">z1</span><span class="p">),</span> <span class="p">.</span><span class="n">d</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="mh">2</span> <span class="o">**</span> <span class="p">(</span><span class="no">S</span> <span class="o">-</span> <span class="mh">1</span><span class="p">)</span> <span class="o">-</span> <span class="mh">1</span><span class="o">:</span><span class="mh">0</span><span class="p">]),</span> <span class="p">.</span><span class="n">s</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="no">S</span> <span class="o">-</span> <span class="mh">2</span><span class="o">:</span><span class="mh">0</span><span class="p">]));</span>
<span class="n">Mux</span> <span class="p">#(.</span><span class="no">S</span><span class="p">(</span><span class="no">S</span> <span class="o">-</span> <span class="mh">1</span><span class="p">))</span> <span class="n">mux2</span><span class="p">(.</span><span class="n">z</span><span class="p">(</span><span class="n">z2</span><span class="p">),</span> <span class="p">.</span><span class="n">d</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="mh">2</span> <span class="o">**</span> <span class="no">S</span> <span class="o">-</span> <span class="mh">1</span><span class="o">:</span><span class="mh">2</span> <span class="o">**</span> <span class="p">(</span><span class="no">S</span> <span class="o">-</span> <span class="mh">1</span><span class="p">)]),</span> <span class="p">.</span><span class="n">s</span><span class="p">(</span><span class="n">s</span><span class="p">[</span><span class="no">S</span> <span class="o">-</span> <span class="mh">2</span><span class="o">:</span><span class="mh">0</span><span class="p">]));</span>
<span class="k">assign</span> <span class="n">z</span> <span class="o">=</span> <span class="n">s</span><span class="p">[</span><span class="no">S</span> <span class="o">-</span> <span class="mh">1</span><span class="p">]</span> <span class="o">?</span> <span class="n">z2</span> <span class="o">:</span> <span class="n">z1</span><span class="p">;</span>
<span class="k">end</span>
<span class="k">endmodule</span></code></pre>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f692e7a63726166742e66722f313636383732313538383639353339372e706e67/1668721588695397.png" alt="Diagramme du mux récursif" title="Source : https://i.zcraft.fr/1668721588695397.png"></p>
<div><a href="https://linuxfr.org/users/killruana/journaux/verilog-recursivite-recursivite-recursivite-error-stack-overflow.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/120329/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/killruana/journaux/verilog-recursivite-recursivite-recursivite-error-stack-overflow#comments">ouvrir dans le navigateur</a>
</p>
jtremesayhttps://linuxfr.org/nodes/120329/comments.atomtag:linuxfr.org,2005:News/395372019-11-13T09:05:15+01:002019-11-13T09:05:15+01:00Simplifier la visualisation de chronogrammesLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Le développement avec des langages de description matériel, le (System)Verilog par exemple, nécessite très souvent de visualiser les chronogrammes afin de vérifier le comportement du composant en développement. Ces chronogrammes sont générés par un simulateur tel qu’<a href="http://iverilog.icarus.com/">Icarus</a> et <a href="https://github.com/ghdl/ghdl">GHDL</a>, pour les versions libres, ou bien encore par <a href="https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=2ahUKEwj7rvvkgeDlAhUPaBoKHZ4MBsMQFjAAegQIABAB&url=https%3A%2F%2Ffr.wikipedia.org%2Fwiki%2FModelSim&usg=AOvVaw3kRJJ0P8geA9YIMlm9lkKs">ModelSim</a>, <a href="https://www.synopsys.com/verification/simulation/vcs.html">VCS</a> et consorts, pour les versions propriétaires.</p>
<p><a href="https://en.wikipedia.org/wiki/Waveform_viewer">GTKWave</a> est la référence dans le monde du logiciel libre pour afficher les chronogrammes, mais il existe également autant d’afficheurs que de simulateurs propriétaires. De très nombreux développeurs ont sans doute été confrontés au côté rébarbatif de l’insertion à la souris des signaux à observer. GTKWave, ainsi que les simulateurs propriétaires, embarquent un interpréteur de langage <a href="https://fr.wikipedia.org/wiki/Tool_Command_Language" title="Tool Command Language">Tcl</a> afin de faciliter l’édition des signaux à observer avec, bien sûr, une syntaxe différente à chaque fois…</p>
<p>J’ai donc décidé de créer le module Python <a href="https://github.com/cclienti/wavedisp">Wavedisp</a> permettant de décrire hiérarchiquement les signaux à observer, ainsi que de procéder à la génération de scripts d’affichage pour différents outils de visualisation, dont GTKWave.</p>
</div><ul><li>lien nᵒ 1 : <a title="https://github.com/cclienti/wavedisp" hreflang="en" href="https://linuxfr.org/redirect/105229">Page GitHub du projet Wavedisp</a></li><li>lien nᵒ 2 : <a title="https://wavecruncher.net/wavedisp" hreflang="en" href="https://linuxfr.org/redirect/105230">Page Web de Wavedisp</a></li><li>lien nᵒ 3 : <a title="https://en.wikipedia.org/wiki/Waveform_viewer" hreflang="en" href="https://linuxfr.org/redirect/105231">Page Wikipédia anglaise de GTKWave</a></li><li>lien nᵒ 4 : <a title="https://pypi.org/project/wavedisp/" hreflang="en" href="https://linuxfr.org/redirect/105232">Wavedisp sur PyPI</a></li></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li><a href="#toc-introduction">Introduction</a></li>
<li><a href="#toc-installation">Installation</a></li>
<li>
<a href="#toc-description-dun-fichierwave">Description d’un fichier Wave</a><ul>
<li><a href="#toc-un-premier-test">Un premier test</a></li>
<li><a href="#toc-un-cas-plus-ambitieux">Un cas plus ambitieux</a></li>
</ul>
</li>
<li><a href="#toc-conclusion">Conclusion</a></li>
</ul>
<h2 id="toc-introduction">Introduction</h2>
<p><a href="https://github.com/cclienti/wavedisp">Wavedisp</a> est un ensemble de classes Python pour vous aider à générer les scripts d’affichage pour différents outils de visualisation de chronogrammes. Au sein d’un fichier <em>Wave</em>, il vous permet de sélectionner facilement les signaux de vos composants à afficher.</p>
<p>En plus de déclarer les signaux, il permet également d’ajouter des groupes, de spécifier la hiérarchie des composants, d’ajouter des barres de division et aussi d’inclure d’autres fichiers <em>Wave</em>. Il prend en charge la génération des fichiers Tcl pour GTKWave, ModelSim (Mentor) et RivieraPro (Aldec).</p>
<h2 id="toc-installation">Installation</h2>
<p>Le module Wavedisp est disponible dans le <a href="https://pypi.org/project/wavedisp/">dépôt PyPI</a> :</p>
<pre><code class="bash">python3 -m venv wavedisp-venv
pip install wavedisp</code></pre>
<h2 id="toc-description-dun-fichierwave">Description d’un fichier Wave</h2>
<p>Généralement, les projets de description de matériel reposent sur une hiérarchie de modules et de tests. Supposons que nous avons réalisé une file d’attente (<a href="https://fr.wikipedia.org/wiki/File_(structure_de_donn%C3%A9es)" title="File d’attente">FIFO</a>) qui utilise deux modules pour coder et décoder le <a href="https://fr.wikipedia.org/wiki/Code_de_Gray">code de Gray</a> depuis et vers le code binaire.</p>
<p>La hiérarchie du projet est la suivante :</p>
<pre><code>dclkfifolut_tb (test)
├── dclkfifolut (composant principal)
├── gray2bin (sous‑composant)
├── bin2gray (sous‑composant)
</code></pre>
<h3 id="toc-un-premier-test">Un premier test</h3>
<p>Les sous‐composants <em>gray2bin</em> et <em>bin2gray</em> disposent eux aussi de leurs propres fichiers de test et nous proposons de décrire dans un premier temps les fichiers <em>Wave</em> pour un de ces sous‑modules.</p>
<p>Le code ci-dessous montre la structure du fichier <em>Wave</em> (<code>gray2bin.wave.py</code>) pour le composant <em>gray2bin</em> :</p>
<pre><code class="python"><span class="kn">from</span> <span class="nn">wavedisp.ast</span> <span class="kn">import</span> <span class="o">*</span>
<span class="k">def</span> <span class="nf">generator</span><span class="p">():</span>
<span class="n">blk</span> <span class="o">=</span> <span class="n">Block</span><span class="p">()</span>
<span class="n">blk</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'gray'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'hexadecimal'</span><span class="p">))</span>
<span class="n">blk</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'bin'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'hexadecimal'</span><span class="p">))</span>
<span class="k">return</span> <span class="n">blk</span></code></pre>
<p>On remarque dans le code ci‑dessus qu’il faut en premier lieu importer les classes permettant d’instancier notre arbre de syntaxe (<em>AST</em>). Il faut également déclarer une fonction <em>generator</em> afin de retourner le point d’entrée de notre <em>AST</em>.</p>
<p>Le nœud <em>Disp</em> permet d’afficher un signal avec différentes propriétés :</p>
<ul>
<li>
<em>radix</em> (<em>hexadecimal</em>, <em>decimal</em>, <em>octal</em> ou <em>binary</em>) ;</li>
<li>
<em>color</em> ;</li>
<li>
<em>height</em>.</li>
</ul>
<p>Le nœud <em>Block</em> ne représentera rien dans le code généré mais permet de définir un ensemble de propriétés par défaut pour tous ses enfants. Charge à ces derniers de les redéfinir ou non. Tous les nœuds ayant des enfants rattachés ont le même comportement que <em>Block</em>.</p>
<p>Procédons maintenant à l’écriture du fichier <em>Wave</em> (<code>gray2bin_tb.wave.py</code>) pour le test de notre module <em>gray2bin</em> :</p>
<pre><code class="python"><span class="kn">from</span> <span class="nn">wavedisp.ast</span> <span class="kn">import</span> <span class="o">*</span>
<span class="k">def</span> <span class="nf">generator</span><span class="p">():</span>
<span class="n">hier</span> <span class="o">=</span> <span class="n">Hierarchy</span><span class="p">(</span><span class="s1">'/gray2bin_tb'</span><span class="p">)</span>
<span class="n">inst</span> <span class="o">=</span> <span class="n">hier</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Hierarchy</span><span class="p">(</span><span class="s1">'gray2bin_inst'</span><span class="p">))</span>
<span class="n">inst</span><span class="o">.</span><span class="n">include</span><span class="p">(</span><span class="s1">'gray2bin_wave.py'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">hier</span></code></pre>
<p>Dans ce dernier fichier nous avons ajouté un nœud déclarant la hiérarchie de notre test ainsi qu’une inclusion vers le fichier <em>Wave</em> <code>gray2bin_wave.py</code> déclarant les signaux du module testé.</p>
<p>L’inclusion de fichiers <em>Wave</em> permet de séparer la déclaration des chronogrammes pour un module de test de ceux pour un module synthétisable. Cela permet donc de hiérarchiser nos fichiers <em>Wave</em> avec la même structure que celle du projet.</p>
<p>Nous pouvons maintenant produire un fichier <em>dot</em> représentant notre <em>AST</em> :</p>
<pre><code class="bash">wavedisp -t dot -o wave.dot gray2bin_tb.wave.py</code></pre>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f776176656372756e636865722e6e65742f7374617469632f696d616765732f677261793262696e5f74622e737667/gray2bin_tb.svg" alt="AST" title="Source : https://wavecruncher.net/static/images/gray2bin_tb.svg"></p>
<p>La commande suivante génère le script Tcl pour note visualiseur GTKWave :</p>
<pre><code class="bash">wavedisp -t gtkwave -o wave.tcl gray2bin_tb.wave.py</code></pre>
<p>Le contenu du fichier <code>wave.tcl</code> est le suivant :</p>
<pre><code class="tcl"><span class="c"># Wavedisp generated gtkwave file</span>
<span class="nv">gtkwave</span><span class="o">::/</span>Edit<span class="o">/</span>Set_Trace_Max_Hier <span class="mi">0</span>
<span class="nv">gtkwave</span><span class="o">::</span>addSignalsFromList <span class="k">[</span><span class="nb">list</span> <span class="k">{</span><span class="nv">gray2bin_tb.gray2bin_inst.gray</span><span class="k">}]</span>
<span class="nv">gtkwave</span><span class="o">::/</span>Edit<span class="o">/</span>Data_Format<span class="o">/</span>Hex <span class="k">{</span><span class="nv">gray2bin_tb.gray2bin_inst.gray</span><span class="k">}</span>
<span class="nv">gtkwave</span><span class="o">::</span>addSignalsFromList <span class="k">[</span><span class="nb">list</span> <span class="k">{</span><span class="nv">gray2bin_tb.gray2bin_inst.bin</span><span class="k">}]</span>
<span class="nv">gtkwave</span><span class="o">::/</span>Edit<span class="o">/</span>Data_Format<span class="o">/</span>Hex <span class="k">{</span><span class="nv">gray2bin_tb.gray2bin_inst.bin</span><span class="k">}</span>
<span class="nv">gtkwave</span><span class="o">::/</span>Edit<span class="o">/</span>Set_Trace_Max_Hier <span class="mi">1</span></code></pre>
<h3 id="toc-un-cas-plus-ambitieux">Un cas plus ambitieux</h3>
<p>Nous pouvons maintenant décrire le fichier <em>Wave</em> pour notre projet complet, à savoir la file d’attente (<a href="https://fr.wikipedia.org/wiki/File_(structure_de_donn%C3%A9es)" title="First in, first out">FIFO</a>) qui instancie plusieurs sous‑composants :</p>
<pre><code class="python"><span class="kn">from</span> <span class="nn">wavedisp.ast</span> <span class="kn">import</span> <span class="o">*</span>
<span class="k">def</span> <span class="nf">generator</span><span class="p">():</span>
<span class="n">block</span> <span class="o">=</span> <span class="n">Block</span><span class="p">()</span>
<span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'rclk'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'binary'</span><span class="p">))</span>
<span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'rsrst'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'binary'</span><span class="p">))</span>
<span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'ren'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'binary'</span><span class="p">))</span>
<span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'rdata'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'hexadecimal'</span><span class="p">))</span>
<span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'rlevel'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'hexadecimal'</span><span class="p">))</span>
<span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'rempty'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'binary'</span><span class="p">))</span>
<span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'wclk'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'binary'</span><span class="p">))</span>
<span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'wsrst'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'binary'</span><span class="p">))</span>
<span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'wen'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'binary'</span><span class="p">))</span>
<span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'wdata'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'hexadecimal'</span><span class="p">))</span>
<span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'wlevel'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'hexadecimal'</span><span class="p">))</span>
<span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Disp</span><span class="p">(</span><span class="s1">'wfull'</span><span class="p">,</span> <span class="n">radix</span><span class="o">=</span><span class="s1">'binary'</span><span class="p">))</span>
<span class="n">read_ptr_gray</span> <span class="o">=</span> <span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Hierarchy</span><span class="p">(</span><span class="s1">'read_ptr_gray'</span><span class="p">))</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Group</span><span class="p">(</span><span class="s1">'read_ptr_gray'</span><span class="p">))</span>
<span class="n">read_ptr_gray</span><span class="o">.</span><span class="n">include</span><span class="p">(</span><span class="s1">'../../bin2gray/project/bin2gray_wave.py'</span><span class="p">)</span>
<span class="n">write_ptr_gray</span> <span class="o">=</span> <span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Hierarchy</span><span class="p">(</span><span class="s1">'write_ptr_gray'</span><span class="p">))</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Group</span><span class="p">(</span><span class="s1">'write_ptr_gray'</span><span class="p">))</span>
<span class="n">write_ptr_gray</span><span class="o">.</span><span class="n">include</span><span class="p">(</span><span class="s1">'../../bin2gray/project/bin2gray_wave.py'</span><span class="p">)</span>
<span class="n">read_ptr_bin</span> <span class="o">=</span> <span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Hierarchy</span><span class="p">(</span><span class="s1">'read_ptr_bin'</span><span class="p">))</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Group</span><span class="p">(</span><span class="s1">'read_ptr_bin'</span><span class="p">))</span>
<span class="n">read_ptr_bin</span><span class="o">.</span><span class="n">include</span><span class="p">(</span><span class="s1">'../../gray2bin/project/gray2bin_wave.py'</span><span class="p">)</span>
<span class="n">write_ptr_bin</span> <span class="o">=</span> <span class="n">block</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Hierarchy</span><span class="p">(</span><span class="s1">'write_ptr_bin'</span><span class="p">))</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Group</span><span class="p">(</span><span class="s1">'write_ptr_bin'</span><span class="p">))</span>
<span class="n">write_ptr_bin</span><span class="o">.</span><span class="n">include</span><span class="p">(</span><span class="s1">'../../gray2bin/project/gray2bin_wave.py'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">block</span></code></pre>
<p>Le fichier <em>Wave</em> pour le test est séparé dans un fichier à part pour les raisons énoncées dans la section précédente :</p>
<pre><code class="python"><span class="kn">from</span> <span class="nn">wavedisp.ast</span> <span class="kn">import</span> <span class="o">*</span>
<span class="k">def</span> <span class="nf">generator</span><span class="p">():</span>
<span class="n">hier</span> <span class="o">=</span> <span class="n">Hierarchy</span><span class="p">(</span><span class="s1">'/dclkfifolut_tb'</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="s1">'blue'</span><span class="p">)</span>
<span class="n">inst</span> <span class="o">=</span> <span class="n">hier</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">Hierarchy</span><span class="p">(</span><span class="s1">'DUT'</span><span class="p">))</span>
<span class="n">inst</span><span class="o">.</span><span class="n">include</span><span class="p">(</span><span class="s1">'dclkfifolut_wave.py'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">hier</span></code></pre>
<p>La commande suivante génère le script Tcl pour le simulateur ModelSim :</p>
<pre><code class="bash">$ wavedisp -t modelsim -o wave.tcl dclkfifolut_tb_wave.py</code></pre>
<p>Le contenu du fichier généré est le suivant :</p>
<pre><code class="tcl"><span class="c"># Wavedisp generated modelsim file</span>
<span class="nv">onerror</span> <span class="k">{</span><span class="nv">resume</span><span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix binary <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>rclk<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix binary <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>rsrst<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix binary <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>ren<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix hex <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>rdata<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix hex <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>rlevel<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix binary <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>rempty<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix binary <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>wclk<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix binary <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>wsrst<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix binary <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>wen<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix hex <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>wdata<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix hex <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>wlevel<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix binary <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>wfull<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix hex <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="o">-</span>group <span class="k">{</span><span class="nv">read_ptr_gray</span><span class="k">}</span> <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>read_ptr_gray<span class="o">/</span>bin<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix hex <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="o">-</span>group <span class="k">{</span><span class="nv">read_ptr_gray</span><span class="k">}</span> <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>read_ptr_gray<span class="o">/</span>gray<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix hex <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="o">-</span>group <span class="k">{</span><span class="nv">write_ptr_gray</span><span class="k">}</span> <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>write_ptr_gray<span class="o">/</span>bin<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix hex <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="o">-</span>group <span class="k">{</span><span class="nv">write_ptr_gray</span><span class="k">}</span> <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>write_ptr_gray<span class="o">/</span>gray<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix hex <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="o">-</span>group <span class="k">{</span><span class="nv">read_ptr_bin</span><span class="k">}</span> <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>read_ptr_bin<span class="o">/</span>gray<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix hex <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="o">-</span>group <span class="k">{</span><span class="nv">read_ptr_bin</span><span class="k">}</span> <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>read_ptr_bin<span class="o">/</span>bin<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix hex <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="o">-</span>group <span class="k">{</span><span class="nv">write_ptr_bin</span><span class="k">}</span> <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>write_ptr_bin<span class="o">/</span>gray<span class="k">}</span>
<span class="nv">add</span> wave <span class="o">-</span>radix hex <span class="o">-</span>color <span class="err">#</span><span class="mo">0000</span>ff <span class="o">-</span>group <span class="k">{</span><span class="nv">write_ptr_bin</span><span class="k">}</span> <span class="k">{</span><span class="o">/</span><span class="nv">dclkfifolut_tb</span><span class="o">/</span>DUT<span class="o">/</span>write_ptr_bin<span class="o">/</span>bin<span class="k">}</span>
<span class="k">update</span></code></pre>
<h2 id="toc-conclusion">Conclusion</h2>
<p>Le module Python <a href="https://github.com/cclienti/wavedisp">Wavedisp</a> permet donc simplement de gérer l’édition de vos chronogrammes dans des environnements complexes et variés, à la fois en termes de hiérarchie de composants, mais aussi en termes d’outils de simulation HDL.</p>
<p>Ce module est encore jeune et des retours sont les bienvenus, soit via des commentaires ou sur GitHub.</p>
</div><div><a href="https://linuxfr.org/news/simplifier-la-visualisation-de-chronogrammes.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/118587/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/simplifier-la-visualisation-de-chronogrammes#comments">ouvrir dans le navigateur</a>
</p>
ChristopheDavy Defaudpalm123gUIhttps://linuxfr.org/nodes/118587/comments.atomtag:linuxfr.org,2005:News/390252019-01-26T13:20:55+01:002019-01-26T17:15:22+01:00Sortie de la version 1.1 de CocotbLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>Voici une excellente nouvelle pour la conception des composants électroniques numériques : la version 1.1 de Cocotb est sortie, la nouvelle vient de tomber sur la liste de diffusion de Cocotb. </p>
<p>C’est une grande nouvelle pour cette bibliothèque Python de co‐simulation <a href="https://fr.wikipedia.org/wiki/Langage_de_description_de_mat%C3%A9riel">HDL</a>, sous licence BSD modifiée. En effet, malgré le travail de cinquante contributeurs, elle était bloquée dans sa version 1.0 depuis plus de quatre ans maintenant. La nouvelle organisation qui vient d’être mise en place devrait garantir la pérennité de Cocotb.</p>
</div><ul><li>lien nᵒ 1 : <a title="https://github.com/potentialventures/cocotb/releases/tag/v1.1" hreflang="en" href="https://linuxfr.org/redirect/103449">Télécharger la version 1.1 de Cocotb</a></li><li>lien nᵒ 2 : <a title="https://lists.librecores.org/pipermail/cocotb/2019-January/000053.html" hreflang="en" href="https://linuxfr.org/redirect/103450">Annonce de la sortie sur la liste de diffusion</a></li><li>lien nᵒ 3 : <a title="http://potential.ventures/cocotb/" hreflang="en" href="https://linuxfr.org/redirect/103451">Site officiel de Cocotb</a></li></ul><div><p>Comme les deux principaux mainteneurs travaillaient sur d’autres sujets, ils ne trouvaient plus le temps de s’occuper de ce projet. Malgré la communauté d’utilisateurs grossissante, les correctifs et les propositions d’améliorations restaient jusqu’ici lettre morte, faute de temps pour les relire.</p>
<p>Cette annonce de sortie d’une nouvelle version permet surtout au logiciel de sortir de sa torpeur. Les principaux développeurs du projet ont réussi à s’organiser pour déléguer le développement et entrer dans un cycle vertueux de vérification et publication.</p>
<p>Cocotb est une bibliothèque Python permettant de faire de la co‐simulation HDL. Un HDL est un langage de description matériel permettant de décrire un composant électronique numérique. Les deux HDL majoritairement utilisés sont <a href="https://fr.wikipedia.org/wiki/VHDL" title="Définition Wikipédia">VHDL</a> et <a href="https://fr.wikipedia.org/wiki/Verilog">Verilog</a>. En phase de développement, il est nécessaire de simuler son composant avec un logiciel de simulation VHDL et/ou Verilog. Habituellement, les stimuli permettant de le tester sont écrits dans le même langage que le composant lui‐même : VHDL ou Verilog. Comme ce sont des vieux langages très spécifiques, c’est fastidieux.</p>
<p>Cocotb permet de s’affranchir du HDL utilisé et d’écrire son banc de tests (les stimulus ou stimuli) en Python. Ce qui est bien plus plaisant et permet d’utiliser l’immense base de fonctionnalités disponible dans le langage Python. Cocotb étant un langage de <strong>co</strong>‐simulation, il se contente de piloter un autre simulateur. Cela permet de s’affranchir du langage simulé et même de faire de la simulation mixte si le simulateur le permet.</p>
<p>Nous allons enfin pouvoir sérieusement écrire nos bancs de tests en Python et oublier les usines à gaz que sont <a href="https://en.wikipedia.org/wiki/Universal_Verification_Methodology">UVM</a>, <a href="https://github.com/UVVM/UVVM">UVVM</a> et consort. Et ce, tout en gardant notre logiciel de simulation HDL préféré, c’est toute la magie de la co‐simulation.</p>
</div><div><a href="https://linuxfr.org/news/sortie-de-la-version-1-1-de-cocotb.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/116282/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/sortie-de-la-version-1-1-de-cocotb#comments">ouvrir dans le navigateur</a>
</p>
martoniBenoît SibaudZeroHeurePierre JarillonDavy Defaudpalm123https://linuxfr.org/nodes/116282/comments.atomtag:linuxfr.org,2005:Diary/383192019-01-16T09:28:00+01:002019-01-16T09:28:00+01:002019, l’année de la libération des FPGA ?Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<p>En matière de liberté le monde du FPGA est resté dans les années 90. Une époque obscure où l’on cachait le mode de fonctionnement des logiciels, où il fallait signer des accords de non divulgation (NDA) avant de pouvoir simplement utiliser un logiciel. Une époque où l’on croyait encore que <a href="https://fr.wikipedia.org/wiki/S%C3%A9curit%C3%A9_par_l%27obscurit%C3%A9">la sécurité par l’obfuscation</a> était le summum de l’état de l’art pour sécuriser et protéger son logiciel et ses données. Mais il est possible que les nouvelles de sorties de nouveaux logiciels libre de fin d'année 2018 changent la donne.</p>
<p>Un FPGA est littéralement un champs de portes programmable. Le paysan-développeur ensemence son champs avec un fichier nommé «bitstream». Ce bitstream permet de configurer les liens entre les différentes portes logiques du FPGA et constituer ainsi un circuit électronique (numérique).</p>
<p>C’est ce fichier qui n’est documenté par <strong>aucun</strong> fabricant de FPGA.</p>
<p>Jusqu’à très récemment pour ses semailles, le développeur devait passer par le logiciel fourni par le fabricant pour générer son bitstream. À chaque modèle un logiciel spécifique, avec tous les défauts inhérent aux logiciels fermés :</p>
<ul>
<li> Obligé d’utiliser un ordinateur et un système d’exploitation supporté officiellement par le fabricant (impossible de générer le bitstream sur un système embarqué ARM par exemple).</li>
<li> Grande difficulté à gérer les bugs du logiciels (et les bugs c’est vraiment pas ça qui manque)</li>
<li> Support aléatoire</li>
<li> Obligé de payer une licence pour les «gros» FPGA</li>
<li> Licence Gratuite pour les petits FPGA mais un système de gestion de ladite licence obligeant à être fliqué par le fabricant (serveur de gestion de licence, obligation d’identification, collectes de données personnelles, …).</li>
</ul>
<p>L’argument principale des fabricants est qu’ils risquent de perdre toutes crédibilités en matière de sécurité auprès des clients militaires notamment. Et qu’ils risquent d’être plus facilement copié par les chinois (Même s’ils y a déjà <a href="http://www.fabienm.eu/flf/fpga-chinois/">des copies fabriquées en chine</a>).</p>
<p>Il a pourtant été démontré depuis longtemps qu’il est tout à fait possible de faire le reverse-engineering des bitstream. C’est notamment ce qu’avait fait en 2008 <a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.117.6043&rep=rep1&type=pdf">Jean-Baptiste Note et Éric Rannaud</a> avec <a href="https://github.com/Martoni/debit">debit</a> pour les FPGA de Xilinx notamment. Mais c’est surtout ce qu’a fait Wolf Clifford en <a href="https://connect.ed-diamond.com/Open-Silicium/OS-017/Icestorm-une-chaine-de-developpement-libre-pour-FPGA">2015</a> avec <a href="http://www.clifford.at/icestorm/">Icestorm</a> pour servir notamment à son logiciel de synthèse <a href="http://www.clifford.at/yosys/">Yosys</a> en utilisant une plate-forme réel : les <a href="https://www.latticesemi.com/Products/FPGAandCPLD/iCE40.aspx">ice40</a> de Lattice.</p>
<p>Ce «déverrouillage» des ice40 a permis une véritable révolution dans le domaine du FPGA chez les bidouilleurs. Beaucoup de cartes électroniques utilisant un ice40 on vu le jours, et le projet à fédéré tout un tas de nouveau projet de logiciels libre.</p>
<p>À l’origine, icestorm permettait de faire la synthèse avec yosys (transformer du verilog en netlist), le placement routage avec arachne-pnr (placer les différentes portes dans le FPGA et les relier entre elles) ainsi que la génération du bitstream avec icestorm (icepack).</p>
<p>Un fois le bitstream généré il est nécessaire de vérifier que les temps de propagation entre les différentes portes soient inférieur au cycle d’horloge. Il est donc nécessaire de posséder la spécification des temps de propagation entre les portes dans le FGPA. Chose qui a également été documenté dans le projet Icestorm (<a href="https://youtu.be/IG5CpFJRnOk">icetime</a>).</p>
<p>Le problème qui persistait avec cette chaîne de développement était <a href="https://github.com/YosysHQ/arachne-pnr/commits/master">arachne-pnr</a> qui ne prenait pas en compte les timings du FPGA pour faire son placement routage. C’est ce verrou qui vient de sauter fin 2018 avec la <a href="https://www.youtube.com/watch?v=Zi9gaSPFqM0">sortie du nouveau logiciel</a> de placement routage <a href="https://github.com/YosysHQ/nextpnr">nextpnr</a> initié par Clifford mais fédérant une communauté de développeurs de plus en plus grosse.</p>
<p>En plus de faire du placement routage en fonction des temps de propagations, nextpnr possède une interface graphique permettant une visualisation du FPGA une fois le projet routé.<br>
Vue de l'interface graphique de nextpnr.</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f63616d6f2e67697468756275736572636f6e74656e742e636f6d2f353534393464333835613036623238616662653964666331306332343534353361633965326137662f3638373437343730373333613266326636393265363936643637373537323265363336663664326633303733373036643663343236313265373036653637/68747470733a2f2f692e696d6775722e636f6d2f3073706d6c42612e706e67" alt="Vu de l’interface graphique de nextpnr (source github officiel)" title="Source : https://camo.githubusercontent.com/55494d385a06b28afbe9dfc10c245453ac9e2a7f/68747470733a2f2f692e696d6775722e636f6d2f3073706d6c42612e706e67"></p>
<p>Tous ces outils sont désormais regroupés dans un projet opensource ayant pour objectif de réaliser un IDE complet pour les FPGA et nommé <a href="https://symbiflow.github.io/">SymbiFlow</a>.</p>
<p>Le projet SymbiFlow a pour objectif de devenir le <a href="https://www.youtube.com/watch?v=5RryRQ1Rr0M">«GCC du FPGA et des ASIC»</a>. En plus de icestorm, SymbiFlow intègre d’autres projets de «reverse-bitstream», notamment:</p>
<ul>
<li> <a href="https://github.com/cliffordwolf/icestorm">icestorm</a>: déjà longuement décrit dans cet article, permet de faire un développement complet avec des outils opensource.</li>
<li> <a href="https://github.com/SymbiFlow/prjxray">X-Ray</a>: Projet de rétro-ingénierie des FPGA de la série 7 de xilinx. Les «tuiles standard» de ces FPGA sont déjà bien documenté et il est possible de générer un bitstream pour des Artix 7.</li>
<li> <a href="https://github.com/SymbiFlow/prjtrellis">Trellis</a>: Projet de rétro-ingénierie des FPGA <a href="https://www.latticesemi.com/Products/FPGAandCPLD/ECP5.aspx">ECP5</a> de Lattice. Toute la matrice a été documenté, et il est désormais possible de faire un projet pour ECP5 de bout en bout avec des outils open-source.</li>
<li> <a href="https://github.com/JohnDMcMaster/project2064">2064</a>: Projet de rétro-ingénierie des FPGA XC2064 de xilinx. Bon ce projet peut être considéré comme anecdotique puisque il vise à reverser le premier fpga de Xilinx du début des années 80 : le <a href="https://spectrum.ieee.org/tech-history/silicon-revolution/chip-hall-of-fame-xilinx-xc2064-fpga">xc2064</a>.</li>
</ul>
<p>Le projet SymbiFlow est un projet encore «en travaux» mais il permet de tracer une voie et fournir des outils permettant de faire la retro-ingénierie d’autres FPGA. Comme on le voit dans les différents projets intégrés il est possible de voir fleurir d’autre projets de retro-ingénierie de FPGA et voir émerger une solution opensource solide pour développer sur FPGA.</p>
<p>L’année 2018 s’est terminée en fanfare avec la présentation de <a href="https://www.youtube.com/watch?v=Zi9gaSPFqM0">nextpnr au 35c3</a>. L’année 2019 sera-t-elle celle de la libération des FPGA avec une fédération des projets de rétro-ingénierie de tous les FPGA du Marché ? Un fabricant de FPGA osera-t-il publier la documentation des ses bitstream pour ses FPGA ? Vera-t-on l’émergence de nouveaux acteur du FPGA faisant du libre ?</p>
<p>Vous saurez tous cela en suivant le prochain épisode de l’année 2019 !</p>
<div><a href="https://linuxfr.org/users/martoni/journaux/2019-l-annee-de-la-liberation-des-fpga.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/116216/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/martoni/journaux/2019-l-annee-de-la-liberation-des-fpga#comments">ouvrir dans le navigateur</a>
</p>
martonihttps://linuxfr.org/nodes/116216/comments.atomtag:linuxfr.org,2005:News/388502018-10-24T10:38:12+02:002018-10-24T22:14:47+02:00Sortie de Yosys Open Synthesis Suite 0.8Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>L’annonce a été faite mardi 16 octobre par W. Clifford : la version 0.8 de Yosis, un logiciel libre de synthèse Verilog est sortie.</p>
<p>Dans le processus de développement <a href="https://fr.wikipedia.org/wiki/FPGA" title="Définition Wikipédia">FPGA</a>/<a href="https://fr.wikipedia.org/wiki/ASIC" title="Définition Wikipédia">ASIC</a> la synthèse est l’étape de conversion du modèle matériel simulé en « <em>netlist RTL</em> », d’où l’on peut dériver le circuit réel.</p>
</div><ul><li>lien nᵒ 1 : <a title="http://www.clifford.at/yosys/" hreflang="en" href="https://linuxfr.org/redirect/102882">Site officiel de Yosys</a></li><li>lien nᵒ 2 : <a title="https://github.com/YosysHQ/yosys/releases/tag/yosys-0.8" hreflang="en" href="https://linuxfr.org/redirect/102894">Page de téléchargement de la version 0.8</a></li><li>lien nᵒ 3 : <a title="https://github.com/YosysHQ/yosys/releases" hreflang="en" href="https://linuxfr.org/redirect/102895">La liste des changements dans le fichier CHANGELOG du projet</a></li></ul><div><p>Le <a href="https://fr.wikipedia.org/wiki/Verilog" title="Définition Wikipédia">Verilog</a> est un langage de modélisation du matériel (HDL pour <em>Hardware Description Langage</em>) permettant de décrire un circuit numérique en simulation. Ce modèle Verilog sert de spécification pour une réalisation « physique » du composant modélisé. La synthèse HDL peut‐être considérée comme une conversion du code HDL en un « schéma électronique » constitué de composants numériques reliés entre eux. On parle alors de « <em>netlist RTL</em> » (<em><a href="https://fr.wikipedia.org/wiki/Register%20Transfer%20Level" title="Définition Wikipédia">Register Transfer Level</a></em>).</p>
<p>Yosys n’est pas le seul logiciel libre permettant de faire de la synthèse Verilog (on peut penser également à <a href="http://docs.verilogtorouting.org/en/latest/odin/">ODIN II</a> utilisé dans la suite logiciel <a href="https://verilogtorouting.org/">VTR</a>). Mais c’est sans contestation possible le logiciel libre qui fait le plus parler de lui ces derniers temps et dont le développement est le plus actif.</p>
<p>En effet, Yosys cible désormais beaucoup de FPGA bon marché, comme le CoolRunner-II, l’ECP5, le MAX10, le Cyclone IV et surtout le ICE40. </p>
<p>L’ICE40 est un peu particulier dans la liste puisque pour ce FPGA toute la chaîne de développement a été libérée. On peut bien sûr faire de la synthèse Verilog, puisque le FPGA est pris en charge par Yosys, mais également le placement routage avec <a href="https://github.com/YosysHQ/arachne-pnr">arachne-pnr</a>, ainsi que la génération du fichier de configuration (<em>bitstream</em>) avec <a href="http://www.clifford.at/icestorm/">icepack/iceprog</a>. Il est également possible de vérifier les <em>timings</em> grâce à icetime.</p>
<p>Beaucoup de choses ont été ajoutées à cette version, mais l’information principale que l’on peut voir dans les notes de version, c’est que le développement de Yosys est très actif. L’objectif de Yosys de devenir le « couteau suisse » libre du FPGA peut presque être considéré comme atteint aujourd’hui.</p>
<p>Même si cela n’est pas apparu avec la version 0.8, on peut noter les fonctionnalités suivantes :</p>
<ul>
<li>le langage FIRRTL utilisé par Chisel3 est une « sortie » (<em>back‐end</em>) possible pour la génération de la <em>netlist</em> ;</li>
<li>le prise en charge du moteur de vérification formelle <a href="http://www.clifford.at/papers/2017/smtbmc-sby/slides.pdf">yosys-smtbmc</a> peut quasiment être considéré comme stable — ce n’est pas notre <a href="https://zipcpu.com/about/gisselquist-technology.html">blogueur chrétien préféré</a> qui dirait le contraire à la vue des <a href="https://zipcpu.com/blog/2017/10/19/formal-intro.html">nombreuses notes</a> expliquant son fonctionnement ;</li>
<li>la liste des FPGA (et autre ASIC) pris en charge s’allonge irrémédiablement ;</li>
<li>ainsi que les formats de « <em>netlist</em> » permettant d’être réintégrés dans les logiciels privateurs des fondeurs : BLIF, EDIF, BTOR, SMT-LIB, RTL Verilog, FIRRTL, etc.</li>
</ul>
<p>Pour comprendre comment fonctionne Yosys, des aperçus sont donnés à la page <a href="http://www.clifford.at/yosys/screenshots.html"><em>screenshots</em></a> du site officiel. Notamment avec un simple compteur :</p>
<pre><code class="verilog"> <span class="k">module</span> <span class="n">counter</span> <span class="p">(</span><span class="n">clk</span><span class="p">,</span> <span class="n">rst</span><span class="p">,</span> <span class="n">en</span><span class="p">,</span> <span class="n">count</span><span class="p">);</span>
<span class="k">input</span> <span class="n">clk</span><span class="p">,</span> <span class="n">rst</span><span class="p">,</span> <span class="n">en</span><span class="p">;</span>
<span class="k">output</span> <span class="kt">reg</span> <span class="p">[</span><span class="mh">3</span><span class="o">:</span><span class="mh">0</span><span class="p">]</span> <span class="n">count</span><span class="p">;</span>
<span class="k">always</span> <span class="p">@(</span><span class="k">posedge</span> <span class="n">clk</span><span class="p">)</span>
<span class="k">if</span> <span class="p">(</span><span class="n">rst</span><span class="p">)</span>
<span class="n">count</span> <span class="o"><=</span> <span class="mh">4</span><span class="mi">'d0</span><span class="p">;</span>
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">en</span><span class="p">)</span>
<span class="n">count</span> <span class="o"><=</span> <span class="n">count</span> <span class="o">+</span> <span class="mh">4</span><span class="mi">'d1</span><span class="p">;</span>
<span class="k">endmodule</span></code></pre>
<p>Yosys se présente sous forme de ligne de commande. On commence par lire et déchiffrer le fichier source :</p>
<pre><code>yosys> read_verilog counter.v
1. Executing Verilog-2005 frontend.
Parsing Verilog input from `counter.v' to AST representation.
Generating RTLIL representation for module `\counter'.
Successfully finished Verilog frontend.
</code></pre>
<p>La synthèse à proprement parler se lance avec la commande <code>proc</code> (<em>process to netlist</em>). Mais il est possible de lancer tout un tas de commandes pour optimiser la synthèse : <code>opt</code>, <code>fsm</code>, <code>memory</code>, etc. On peut également lancer la commande <code>synth</code> pour exécuter toutes ces étapes automatiquement.</p>
<p>À chaque instant on peut voir le « schéma » généré si graphiz est installé (et xdot) avec la commande <code>show</code> :</p>
<pre><code>yosys> show
</code></pre>
<p><img src="//img.linuxfr.org/img/687474703a2f2f7777772e636c6966666f72642e61742f796f7379732f696d616765732f73686f775f72746c2e706e67/show_rtl.png" alt="Schéma généré par Yosis" title="Source : http://www.clifford.at/yosys/images/show_rtl.png"></p>
<p>Pour terminer la synthèse à proprement parler, il faut associer nos blocs à des composants issus d’une bibliothèque fondeur/FPGA (que l’on optimisera avec <a href="https://people.eecs.berkeley.edu/%7Ealanmi/abc/"><em>abc</em></a>) :</p>
<pre><code>yosys> dfflibmap -liberty mylib.lib
yosys> abc -liberty mylib.lib
</code></pre>
<p>On peut ensuite sauvegarder notre design ainsi synthétisé dans différents formats au moyen des commandes <code>write_*</code> :</p>
<pre><code>yosys> write_<TAB>
write_aiger write_btor write_file write_ilang write_json write_smt2 write_spice write_verilog
write_blif write_edif write_firrtl write_intersynth write_simplec write_smv write_table
</code></pre>
<p>On remarquera la présence du format FIRRTL de <a href="https://chisel.eecs.berkeley.edu/">Chisel3</a> ou de Spice pour faire de la simulation analogique. Il est également possible de réécrire la sortie en Verilog « bas niveau » ou en EDIF/BLIF, reconnu par la plupart des fondeurs/FPGA.</p>
<p>Ceci n’est qu’un aperçu (vraiment) très rapide de Yosys, j’encourage toutes celles et ceux intéressés par le sujet à lire le <a href="http://www.clifford.at/yosys/files/yosys_manual.pdf">manuel de Yosys</a> qui est plutôt bien fait.</p>
</div><div><a href="https://linuxfr.org/news/sortie-de-yosys-open-synthesis-suite-0-8.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/115507/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/sortie-de-yosys-open-synthesis-suite-0-8#comments">ouvrir dans le navigateur</a>
</p>
martoniZeroHeureDavy Defaudpalm123bubar🦥BAudhttps://linuxfr.org/nodes/115507/comments.atomtag:linuxfr.org,2005:News/387892018-09-24T01:33:18+02:002018-10-07T17:26:34+02:00Verilator 4.002Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>La version 4.002 de Verilator <a href="https://www.veripool.org/papers/Verilator_v4_Multithreaded_OrConf2018.pdf">a été annoncée</a> à la conférence <a href="https://orconf.org/">ORConf2018</a> en Pologne.</p>
<p>Verilator est sans conteste le simulateur <a href="https://en.wikipedia.org/wiki/Hardware_description_language">HDL</a> <em>open source</em> le plus rapide du « marché ». Il permet de simuler des <a href="http://www.fabienm.eu/flf/et-pourquoi-pas-portegramme/">porte‐grammes</a> écrits en Verilog <strong>synthétisable</strong>.</p>
<p><img src="//img.linuxfr.org/img/68747470733a2f2f7777772e76657269706f6f6c2e6f72672f696d672f766572696c61746f725f3235365f3230305f6d696e2e706e67/verilator_256_200_min.png" alt="Le nouveau logo de Verilator" title="Source : https://www.veripool.org/img/verilator_256_200_min.png"></p>
</div><ul><li>lien nᵒ 1 : <a title="https://www.veripool.org/wiki/verilator" hreflang="en" href="https://linuxfr.org/redirect/102672">Page officielle de Verilator</a></li><li>lien nᵒ 2 : <a title="http://www.fabienm.eu/flf/icarus-vs-verilator/" hreflang="fr" href="https://linuxfr.org/redirect/102673">Comparaison de temps de simulation Verilator vs Icarus</a></li><li>lien nᵒ 3 : <a title="https://www.veripool.org/news/241-Verilator-Verilator-4-002-Released" hreflang="en" href="https://linuxfr.org/redirect/102698">Notes de version de la 4.002</a></li><li>lien nᵒ 4 : <a title="https://www.veripool.org/papers/Verilator_v4_Multithreaded_OrConf2018.pdf" hreflang="en" href="https://linuxfr.org/redirect/102738">La présentation à ORConf2018</a></li></ul><div><p>Synthétisable ? Ce point est important. En effet, le langage <a href="https://fr.wikipedia.org/wiki/Verilog">Verilog</a> (tout comme son homologue VHDL) permet de décrire des modèles de circuits numériques destinés à être utilisés dans des <a href title="Field‐Programmable Gate Array — circuit logique programmable">FPGA</a> mais aussi des <a href="https://fr.wikipedia.org/wiki/Application-specific_integrated_circuit" title="Application‐Specific Integrated Circuit — circuit intégré propre à une application">ASIC</a>. En plus de la partie « modélisation », Verilog (comme VHDL) inclut la partie tests. On peut donc écrire tout notre <em>testbench</em> en Verilog, puisque nous avons des fonctions d’affichage, d’accès aux fichiers, etc. Cependant, seule une sous‐partie du langage Verilog est capable de décrire le circuit final, c’est ce qu’on appelle la partie « synthétisable » car elle peut être synthétisée en un schéma électronique numérique.</p>
<p>Si verilator n’est capable de prendre en entrée que du Verilog synthétisable, c’est parce qu’il convertit ce code en un objet en C++ et/ou SystemC (le <a href="https://fr.wikipedia.org/wiki/SystemC">SystemC</a> n’étant qu’une bibliothèque C++). La partie code de test sera donc écrite en C++/SystemC et le programme final compilé avec <em>gcc</em>. <br>
Le binaire ainsi compilé peut ensuite être exécuté comme n’importe quel exécutable et lancera la simulation de notre modèle numérique (le porte‐gramme).</p>
<p>Le résultat est un temps de simulation incroyablement plus rapide qu’<a href="https://www.veripool.org/wiki/veripool/Verilog_Simulator_Benchmarks">avec les simulateurs classiques</a>. Le site officiel donne des vitesses 90 fois supérieures au célèbre simulateur Verilog <em>open source</em> <a href="http://iverilog.icarus.com/">Icarus</a>. Personnellement, sur mon porte‐gramme d’anti‐rebond j’obtiens une vitesse 20 fois supérieure, mais c’est en enregistrant des traces très lourdes (700 Mio) permettant de visualiser les signaux une fois la simulation terminée.<br>
Il est possible de faire tourner des modèles de microprocesseurs écrit en Verilog en « temps réel » (à quelques kilohertz).</p>
<p>Concrètement, si l’on prend l’exemple d’un porte‐gramme simple permettant de filtrer les rebonds d’un bouton (pour le code complet c’est <a href="https://github.com/Martoni/blp/blob/master/verilog/src/button_deb.v">par ici</a>). On aura les ports d’entrée‐sortie suivants :</p>
<pre><code class="verilog"><span class="k">module</span> <span class="n">button_deb</span><span class="p">(</span>
<span class="c1">// sync design</span>
<span class="k">input</span> <span class="n">clk</span><span class="p">,</span>
<span class="k">input</span> <span class="n">rst</span><span class="p">,</span>
<span class="c1">// in-out</span>
<span class="k">input</span> <span class="n">button_in</span><span class="p">,</span>
<span class="k">output</span> <span class="n">button_valid</span><span class="p">);</span></code></pre>
<p>Une fois « compilé » avec verilator :</p>
<pre><code>verilator -Wall -cc src/button_deb.v --trace --exe test/test_button_deb.cpp
</code></pre>
<p>On obtient un objet que l’on peut instancier dans son programme principal :</p>
<pre><code class="c++"> <span class="n">Vbutton_deb</span><span class="o">*</span> <span class="n">top</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Vbutton_deb</span><span class="p">;</span></code></pre>
<p>L’accès aux signaux d’entrée‐sortie se fait ensuite simplement comme un accès aux variables de l’objet :</p>
<pre><code class="c++"><span class="n">top</span><span class="o">-></span><span class="n">rst</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">top</span><span class="o">-></span><span class="n">button_in</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">top</span><span class="o">-></span><span class="n">clk</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span></code></pre>
<p>On évalue les valeurs de sortie par l’appel à la fonction <code>eval()</code> :</p>
<pre><code class="c++"><span class="n">top</span><span class="o">-></span><span class="n">eval</span><span class="p">();</span></code></pre>
<p>C’est cet appel à la fonction <code>eval()</code> qui fera avancer la simulation d’un « pas ». À nous de connaître le temps que nous souhaitons avoir entre deux pas.</p>
<p>Hormis la collection de corrections de bogues, la fonctionnalité majeure de cette nouvelle version est la prise en charge de multiple fils d’exécution (<em>multi‐threads</em>), qui divise encore le temps de simulation de beaucoup, en fonction du nombre de cœurs présents sur sa machine.</p>
<p>Cette nouvelle version de Verilator prouve surtout que ce vénérable projet (créé en 1994 d’après la <a href="https://en.wikipedia.org/wiki/Verilator">page Wikipédia</a>) est encore largement actif, il est désormais pris au sérieux par tous les concepteurs de matériel. Et si l’on en croit son auteur, la plupart des équipes qui conçoivent des microprocesseurs l’utilisent intensément.</p>
<p>Bref, un très bel exemple d’outil de libération des FPGA. ;)</p>
</div><div><a href="https://linuxfr.org/news/verilator-4-002.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/115258/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/verilator-4-002#comments">ouvrir dans le navigateur</a>
</p>
martoniDavy DefaudBAudZeroHeurebubar🦥palm123Benoît Sibaudhttps://linuxfr.org/nodes/115258/comments.atomtag: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:Diary/369912016-11-29T22:30:17+01:002016-11-29T22:30:17+01:00HiFive1: Un Arduino à 320Mhz entièrement libre pour 2017Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<p>À l'heure où j'écris ces lignes a lieu le <a href="https://riscv.org/2016/11/5th-risc-v-workshop-proceedings/">5 ème workshop</a> sur jeux d'instruction libre (ISA <a href="https://riscv.org/">Risc-V</a> au campus google à Mountain View.</p>
<p>Et c'est à cette occasion qu'est présenté la carte HiFive1 composée d'un microcontrôleur Freedom Everywhere 310 (FE310) à cœur SiFive (utilisant le jeux d'instructions Risc-V). Une carte compatible Arduino mais 10 fois plus puissante et entièrement libre, jusqu'au silicium.</p>
<p>La description hardware en Chisel/Verilog est disponible sur <a href="https://github.com/sifive/freedom">github</a> et il est possible de simuler intégralement le modèle qui tournera sur la carte.</p>
<p>Contrairement à l'<a href="//linuxfr.org/users/ghusson/journaux/open-v-premier-microcontroleur-libre">open-v</a>, le développement du HiFive1 est déjà terminé et le <a href="https://www.crowdsupply.com/sifive/hifive1">crowdfunding</a> organisé n'est là que pour les précommandes.</p>
<p>La société SiFive se base sur ce microcontrôleur ainsi que sur un microprocesseur Freedom U500 pour promouvoir son savoir faire et proposer à ses clients des puce «full-custom» à base de briques opensource.</p>
<p>Visiblement, pour 60$ il est donc possible de se procurer le kit compatible arduino intégralement open-source qui sera disponible en février 2017.</p><div><a href="https://linuxfr.org/users/martoni/journaux/hifive1-un-arduino-a-320mhz-entierement-libre-pour-2017.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/110659/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/martoni/journaux/hifive1-un-arduino-a-320mhz-entierement-libre-pour-2017#comments">ouvrir dans le navigateur</a>
</p>
martonihttps://linuxfr.org/nodes/110659/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.atomtag:linuxfr.org,2005:News/374542016-07-24T23:26:31+02:002016-07-25T09:44:16+02:00Icestudio 0.2, du schéma au verilogLicence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<div><p>IceStudio est un logiciel graphique permettant de concevoir un design <a href="https://fr.wikipedia.org/wiki/FPGA" title="Définition Wikipédia">FPGA</a> à la manière d’un schéma électronique. Le logiciel est encore largement expérimental et centré sur les FPGA ice40 de chez <a href="http://www.latticesemi.com/Products/FPGAandCPLD/iCE40.aspx">lattice</a>. Écrit en JavaScript autour de Nodejs, le logiciel permet de dessiner son projet au moyen de blocs reliés entre eux par des signaux.</p>
<p>IceStudio est sous licence GPLv2.</p>
<p><abbr title="Note des modérateurs">NdM</abbr> : à noter, ce projet bénéficie d'un soutien du fabricant espagnol <a href="https://www.bq.com/fr/">BQ</a> (connu également pour fournir des matériels avec Ubuntu pré-installée)</p></div><ul><li>lien nᵒ 1 : <a title="https://github.com/FPGAwars/icestudio" hreflang="en" href="https://linuxfr.org/redirect/97795">IceStudio</a></li><li>lien nᵒ 2 : <a title="http://www.clifford.at/icestorm/" hreflang="en" href="https://linuxfr.org/redirect/97796">IceStorm</a></li></ul><div><p><img src="//img.linuxfr.org/img/687474703a2f2f7777772e66616269656e6d2e65752f666c662f77702d636f6e74656e742f75706c6f6164732f323031362f30372f69636573747564696f2d302e322d63726f6e6f5f2e706e67/icestudio-0.2-crono_.png" alt="icestudiocrono" title="Source : http://www.fabienm.eu/flf/wp-content/uploads/2016/07/icestudio-0.2-crono_.png"></p>
<p>IceStudio se veut une extension graphique au projet <a href="http://www.clifford.at/icestorm/">IceStorm</a> (chaine de synthèse/place&route/bitstream opensource), qui a été développé par ingénierie inversée. Voir la <a href="http://www.clifford.at/papers/2015/icestorm-flow/slides.pdf">présentation</a> du projet lors du <a href="https://events.ccc.de/category/32c3/">32C3</a>. Le projet IceStorm est composé de trois logiciels distincts : <a href="https://github.com/cseed/icestorm">IceStorm</a>, <a href="https://github.com/cseed/arachne-pnr">Arachne-PnR</a> pour construire le routage des signaux, et <a href="http://www.clifford.at/yosys/">Yosis</a> permettant de synthétiser/compiler le verilog.</p>
<p>Les blocs peuvent être pris dans une bibliothèque fournie avec le logiciel, mais il est également possible de créer des blocs «vierges» dans lesquels on écrira le <a href="https://fr.wikipedia.org/wiki/Verilog">code verilog</a> correspondant au comportement souhaité.</p>
<p>Le format de sauvegarde du projet est en JSON, un outils de conversion permet ensuite de le transformer en code Verilog pour la synthèse.</p>
<p><img src="//img.linuxfr.org/img/687474703a2f2f7777772e66616269656e6d2e65752f666c662f77702d636f6e74656e742f75706c6f6164732f323031362f30372f69636573747564696f2d302e322d636f756e7465722d696e7370656374696f6e2e706e67/icestudio-0.2-counter-inspection.png" alt="icestudioinspection" title="Source : http://www.fabienm.eu/flf/wp-content/uploads/2016/07/icestudio-0.2-counter-inspection.png"></p>
<p>Le projet est encore jeune mais très prometteur. Espérons que nous verrons rapidement l’intégration de nouvelles plateformes/FPGA.</p></div><div><a href="https://linuxfr.org/news/icestudio-0-2-du-schema-au-verilog.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/109619/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/icestudio-0-2-du-schema-au-verilog#comments">ouvrir dans le navigateur</a>
</p>
martonibubar🦥Nils RatusznikNÿcoXavier TeyssierBenoît Sibaudpalm123https://linuxfr.org/nodes/109619/comments.atomtag:linuxfr.org,2005:Diary/353982014-11-12T13:48:50+01:002014-11-12T13:48:50+01:00Le VHDL prend-il l'eau ?Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr<p>Le <a href="http://en.wikipedia.org/wiki/VHDL">VHDL</a> est un langage de simulation numérique. C'est initialement une commande de l'armée américaine pour standardiser les spécifications de circuits numériques. Le VHDL a été standardisé à coup de pelle à neige par l'IEEE en se basant sur le langage ADA.</p>
<p>Du langage de simulation, le VHDL est passé au langage de description hardware avec l'arrivée des FPGA/ASIC. Les constructeurs de FPGA fournissant des outils de conversion VHDL->netlist pour leurs propres composants. Chacun y allant de son interprétation du langage pour son propre compte.</p>
<p>Parallèlement, Cadence qui avait développé son propre langage de simulation pour ses outils a elle aussi ouvert son propre langage en le standardisant : le <a href="http://en.wikipedia.org/wiki/Verilog">verilog</a>.</p>
<p>Alors soyons clair, les deux langages sont relativement mauvais, verbeux, mal standardisés et sujet à interprétation en fonction de l'outil utilisé. La question n'est pas de savoir si Verilog est meilleur que le VHDL mais plutôt de discuter des projets libres tournant autour d'eux.</p>
<p>En se qui concerne les outils privateurs (cadence, mentor, xilinx, altera, …) le choix de l'un ou l'autre des langages n'a que peu de conséquences. Ces outils supportent très bien les deux langages, ils supportent même le mélange des deux dans un même projet.</p>
<p>En ce qui concerne les outils libres c'est une toute autre histoire.</p>
<p>Le seul projet sérieux se basant sur VHDL que je connaisse est <a href="http://ghdl.free.fr/">GHDL</a>. Un simulateur basé sur gcc et maintenu par <a href="//linuxfr.org/news/entretien-avec-tristan-gingold-auteur-de-ghdl">Tristan Gringold</a>. Ce simulateur fonctionne bien malgrés qu'il soit relativement lent. C'est l'outil que j'utilise intensivement pour le développement de mes projets FPGA (avec <a href="http://gtkwave.sourceforge.net/">gtkwave</a> pour la visualisation des signaux).</p>
<p>Mais en ce qui concerne le Verilog. On trouve beaucoup plus de projets libres qui semblent relativement abouti:</p>
<ul>
<li>
<a href="http://iverilog.icarus.com/">Icarus</a>: Permet de simuler ses projets verilog à la manière de ghdl, d'après le site internet icarus est même capable de générer la netlist pour la synthèse.</li>
<li>
<a href="http://www.veripool.org/wiki/verilator">Verilator</a>: La simulation direct du verilog étant relativement lente, verilator converti le code en C++ pour améliorer la vitesse de simulation.</li>
<li>
<a href="https://github.com/m-labs/migen">Migen</a>: Un module python permettant de décrire son architecture hard en python puis de générer le verilog synthétisable et simulable.</li>
<li>
<a href="https://chisel.eecs.berkeley.edu/">Chisel</a>: Ce projet permet de décrire son architecture matérielle en <a href="http://www.scala-lang.org/">scala</a> et de générer soit du verilog pour la synthèse, soit du C++ pour la simulation.</li>
<li>…</li>
</ul><p>Il y a certainement beaucoup d'autre projet libre que je n'ai pas exploré. Mais ce que je constate dans ma quête de logiciels libres pour les FPGA, c'est que la plupart des projets sur lesquels je tombe se basent sur du Verilog et non du VHDL.</p>
<p>Faut-il en déduire que le VHDL prend l'eau ? Que si l'on veut travailler avec des logiciels libres il vaut mieux se mettre au verilog ?</p><div><a href="https://linuxfr.org/users/martoni/journaux/le-vhdl-prend-il-l-eau.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/103933/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/martoni/journaux/le-vhdl-prend-il-l-eau#comments">ouvrir dans le navigateur</a>
</p>
martonihttps://linuxfr.org/nodes/103933/comments.atom