Archives de catégorie : Non classé

CLEAR, production du premier microcontrôleur avec un eFPGA complètement open-source

[depêche parue initialement sur LinuxFR]

CLEAR est un microcontrôleur RISC-V (VexRISCV) muni d’un eFPGA gravé en 130 nm et produit avec le programme chipignite de la société de production d’ASIC Efabless. La totalité du « dossier de fabrication » du composant est publiée en open source.

Sommaire

Un FPGA est un type particulier de composant électronique. Il peut être vu comme un « kit » de portes logiques avec des connexions reconfigurables à l’infini. Le tout est assemblé dans un même composant. Les constructeurs de FPGA gardent jalousement secrète une partie de l’architecture de leurs composants et ne fournissent même pas la documentation permettant de les configurer. Il est nécessaire de passer par leurs logiciels (binaires) pour générer le fichier de configuration appelé bitstream.
La conception et la fabrication d’un FPGA passent par les mêmes procédés que pour n’importe quel composant électronique numérique (processeur, périphérique, microprocesseur) : on part d’un modèle numérique du composant que l’on va transformer en un dessin « 3D » du circuit final appelé GDSII. Toute cette chaîne de fabrication utilise un tas de formats et de standards jalousement gardés secrets par les différents acteurs de cette industrie. Il est évident que les fabricants de FPGA gardent secret ces « dossiers de fabrication ».

Il y a quelques années, Claire Clifford libérait le format des bitstreams de configuration du FPGA ice40 par rétro-ingénierie avec le projet Icestorm. D’autres FPGA ont ensuite été libérés par ingénierie inverse, sans soutien des différents constructeurs.

Un pas de plus dans la libération des FPGA a été franchi avec la production du EOS S3 de la société QuickLogic. QuickLogic a publié le format du bitstream de la partie FPGA (eFPGA) de son composant et supporte officiellement les outils opensource.

Avec le CLEAR, on passe à une toute autre échelle de libération pour les FPGA. En effet — cette fois — c’est la totalité du « dossier de fabrication » qui est libéré. Commençons par le cœur du composant : openFPGA.

openFPGA : le générateur de FPGA

Architecture CLB d'openFPGA

L’architecture utilisée dans le CLEAR est celle du projet openFPGA. Le projet propose de générer une structure de FPGA « prête à graver » à partir d’un simple fichier de configuration de l’architecture voulue. L’objectif étant de réduire le temps de développement d’un FPGA à 24 heures, au lieu des mois habituels.

L’architecture du eFPGA est constituée de 8 × 8 = 64 CLB. Chaque CLB contient quatre Blocs Logique Élémentaire (BLE) avec à chaque fois :

  • une LUT quatre entrées
  • une bascule D (Flip-Flop) – un multiplexeur de sortie (MUX).

Ce type d’architecture se retrouve dans tous les FPGA avec une variation sur le nombre d’entrées de la LUT. Cela nous permet de comparer les FPGA en termes de nombre de LUT.

Avec le CLEAR nous avons donc un eFPGA de 256 LUT. Pour comparer on peut parler du EOS S3 qui possède 891 LUT ou du ICE40 dont la gamme débute à 384 LUT et monte jusqu’à environ 8000 LUT.

On parle donc d’un tout petit eFPGA. Avec une architecture de FPGA open source, il est plus évident de développer des outils libres pour travailler sur ces FPGA. L’outil de référence pour configurer les FPGA générés avec openFPGA est issu majoritairement du projet VTR (Verilog To Routing).

La partie FPGA ainsi générée est prête à être intégrée dans la caravelle.

Caravel : embarquez votre composant avec un processeur RISC-V

La lectrice ou le lecteur aura certainement remarqué que le titre de la dépêche ne parle pas de FPGA mais de eFPGA. e qui signifie simplement « embedded ». Le FPGA généré est embarqué dans un composant plus gros muni d’un microprocesseur 32 bits nommé VexRisc qui est openSource lui aussi.

Ce processeur — développé par Charles Papon avec le langage HDL SpinalHDL — est la base du SoC Caravel développé par la société eFabless et open source lui aussi.

Synoptique général du CLEAR

L’objectif de Caravel est de proposer un SoC complet avec le CPU, quelques périphériques (UART, SPI, GPIO, RAM…) et une zone libre pour y graver un composant de son cru. Toute la partie « outils de déverminage » est ainsi standardisée avec tous les signaux nécessaires au bon fonctionnement du projet cible.

Avec cet outil libre, efabless veut démocratiser la fabrication de composant électronique et la rendre accessible aux petites PME, voire aux particuliers.

Ce kit de développement est proposé par la société efabless avec son programme chipignite.

Chipignite : les ASIC pour tous

Avec le programme Chipignite d’efabless, il est en effet possible de faire produire 100 composants (ou 300 selon le boîtier choisi) pour moins de 10 000 $ gravé en 130 nm.
À ce prix-là, on a tous les outils de développement à disposition ainsi que les bibliothèques du kit de développement (PDK) en 130 nm du fabricant, sans avoir à signer d’accord de non divulgation (NDA) pour lire l’accord de non divulgation à signer.

Comme le nom de la société le laisse entendre, efabless ne possède pas d’usine de fabrication. Elle se contente de réserver des slots (shuttle) de fabrication dans l’usine américaine skywater.

Sky130 : le « kit ASIC » (pdk) libéré

Skywater est un petit fabricant de composants électroniques américain. C’est une ancienne usine de Cypress qui a pris son indépendance.

Vue de l'usine skywater dans le Minesota

Cette entreprise fabrique des semi-conducteurs à des niveaux de gravure qui sont aujourd’hui considérés comme largement amortis. Le 130 nm par exemple est la finesse de gravure utilisée il y a 20 ans pour les processeurs Pentium III ou pour le processeur de la Gamecube.

Pour faire produire un composant électronique, il faut fournir un fichier de fabrication au format GDSII. Qui est un format ouvert de description des différentes couches de dopage et de connexions métal du composant.

Mais pour générer ce GDSII, l’entreprise qui conçoit des composants a besoin de connaître les propriétés du substrat fabriqué. Il faut un modèle pour simuler les composants que l’on « dessine ».
À partir de ce modèle il est possible d’établir une bibliothèque de composants comme des transistors, bascules, mémoire et autres.

Toutes ces informations sont rassemblées dans ce qu’on appelle un PDK (Process Design Kit). Le PDK est intimement lié au fabricant et au process de fabrication. Sans lui, impossible de concevoir et générer le GDSII, malgré la disponibilité de nombreux (et vieux) logiciels libres dans le domaine.

Jusqu’à l’année dernière, il n’existait pas de PDK « ouvert » : impossible pour une petite entreprise d’y avoir accès sans payer des sommes folles en licences de développement. Sans compter sur les accords de non divulgation qui rendaient impossible la diffusion du GDSII en dehors de la production.

Pour dynamiser sa production, Skywater a donc décidé, avec l’aide de Google, de libérer son PDK pour la finesse de gravure de 130 nm. Le PDK se nomme Sky130 et est disponible à tous sous licence Apache 2.0 sur github.

Open MPW shuttle : les ASIC open source gratuits de google

10 000 $ ça ne se trouve pas sous le sabot d’un cheval. Il y a intérêt d’avoir un projet un peu plus solide qu’un simple TapTempo. Une PME peut prendre des risques avec cette somme mais de manière mesurée.

Pour favoriser l’émergence d’une communauté open source dans le développement matériel et pour encourager les développeuses et développeurs à prendre des risques et innover, Google a décidé de financer des productions de composants tous les six mois.

Pour être dans la « navette » nommée Open MPW shuttle il faut proposer un composant totalement open source et publier tous les scripts permettant de re-générer le GDSII.
Si le projet est jugé intéressant, efabless fera fabriquer une série de composants gratuitement.

Et c’est ce qui s’est passé avec le projet Caravel-OpenFPGA-EF qui a été produit dans la première navette MPW-1.
OpenFPGA a également été utilisé dans la seconde navette MPW-2 avec le projet SOFA.

Il y a d’autre projet de eFPGA dans les navettes, mais OpenFPGA semble être le plus utilisé et le plus facile d’accès.

La production de CLEAR en financement participatif

Pour montrer la possibilité de produire un eFPGA open source un financement participatif a été lancé sur le site groupgets.

Moyennant 75 $ (plus les frais de port plus certainement la douane) il est possible d’acquérir ce microcontrôleur soudé sur une carte de développement.

photo de la carte clear

Une fois la levée de fonds bouclée, le projet sera embarqué dans la navette 2204C pour une production prévue en avril 2022.

Bien sûr, une carte de développement à ce prix pour un eFPGA aussi petit peut sembler inintéressante. Il faut plutôt le voir comme une somme accessible à (presque) tout le monde pour entrer dans le monde du silicium et des FPGA opensource. C’est, en tout cas la preuve, qu’il est possible de produire un FPGA (+ microcontrôleur) intégralement open source à des tarifs raisonnables.

Aller plus loin

Sortie de la version 0.10 de Yosys

[Dépêche paru initialement sur LinuxFR]

Yosys est devenu le pivot opensource du développement des circuits intégrés FPGA et ASIC.

Le 27 septembre 2021 a été publiée la nouvelle version 0.10 de Yosys sur l’hébergeur de gestionnaire de versions GitHub.
Cette sortie tardive (la 0.9 date de 2019) est l’occasion de parler de ce logiciel libre de synthèse Verilog, pivot de la libération des FPGA (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 «RTL».

Le manuel de Yosys représente les différentes couches d’abstractions utilisées en conception numérique.

Couche d’abstraction utilisées en synthèse numérique

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.

Le niveau «Behavioral» est celui dans lequel on décrit le comportement du composant en Verilog ou VHDL. Il est également possible aujourd’hui d’utiliser des langages comme Clash, Chisel ou Migen. Ces derniers généreront ensuite du code Verilog au niveau «RTL».
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.
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 EDIF, mais il est possible de la décrire en Verilog ou VHDL. Yosys propose également le format JSON bien connu des développeurs JavaScript.
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.

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é nextpnr, mais ça nous éloigne du sujet. Sachez juste que nextpnr est parfaitement utilisable pour certaines marques de FPGA (ICE40, Gowin, ECP5 notamment).

Yosys est un logiciel de synthèse Verilog, il prend en entrée un source Verilog dans la couche «Behavioral Level» pour descendre dans les couches jusqu’au niveau «Physical Gate».

commençons donc par l’exemple de l’inverseur synchrone suivant (fichier invert.v):

// inverseur
module syncinvert(
    input clock,
    input reset,
    input inval,
    output outval);
reg regval;

assign outval = regval;

always@(posedge clock, posedge reset)
begin
    if(reset)
        regval <= 1'b0;
    else
        regval <= !inval;
end

endmodule

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 :

$ yosys

 /----------------------------------------------------------------------------\
 |                                                                            |
 |  yosys -- Yosys Open SYnthesis Suite                                       |
 |                                                                            |
 |  Copyright (C) 2012 - 2020  Claire Xenia Wolf <claire@yosyshq.com>         |
 |                                                                            |
 |  Permission to use, copy, modify, and/or distribute this software for any  |
 |  purpose with or without fee is hereby granted, provided that the above    |
 |  copyright notice and this permission notice appear in all copies.         |
 |                                                                            |
 |  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES  |
 |  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF          |
 |  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR   |
 |  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    |
 |  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN     |
 |  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF   |
 |  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.            |
 |                                                                            |
 \----------------------------------------------------------------------------/

 Yosys 0.10+0 (git sha1 070cad5f4, clang 8.0.0-svn345496-1~exp1+0~20181029105533.852~1.gbpf10f36 -fPIC -Os)

yosys>

Premier changement de cette version : l’auteur n’est plus Clifford Wolf mais Claire Xenia Wolf. 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» changé de prénom et d’état civil.

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.
On charge son fichier source verilog avec la commande read_verilog.

yosys> read_verilog invert.v 
1. Executing Verilog-2005 frontend: invert.v
Parsing Verilog input from `invert.v' to AST representation.
Generating RTLIL representation for module `\syncinvert'.
Successfully finished Verilog frontend.

Yosys nous informe ici qu’il a bien lu et analysé le fichier source. Le «gateware» est bien conforme au standard Verilog-2005 et a été converti dans le langage interne nommé RTLIL (RTL Intermediate Language).

On peut lister les modules chargés en mémoire grâce à la commande ls.

yosys> ls

1 modules:
  syncinvert

Et afficher une vue graphique du module avec show:

yosys> show syncinvert 

4. Generating Graphviz representation of design.
Writing dot description to `/home/fabien/.yosys_show.dot'.
Dumping module syncinvert to page 1.
Exec: { test -f '/home/user/.yosys_show.dot.pid' && fuser -s '/home/user/.yosys_show.dot.pid' 2> /dev/null; } || ( echo $$ >&3; exec xdot '/home/fabien/.yosys_show.dot'; ) 3> '/home/user/.yosys_show.dot.pid' &

Qui affiche l’image suivante

Rendu xdot de l’inverseur

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 proc:

yosys> proc
10. Executing PROC pass (convert processes to netlists).
10.1. Executing PROC_CLEAN pass (remove empty switches from decision trees).
Cleaned up 0 empty switches.
10.2. Executing PROC_RMDEAD pass (remove dead branches from decision trees).
Removed a total of 0 dead cases.
10.3. Executing PROC_PRUNE pass (remove redundant assignments in processes).
Removed 0 redundant assignments.
Promoted 0 assignments to connections.
10.4. Executing PROC_INIT pass (extract init attributes).
10.5. Executing PROC_ARST pass (detect async resets in processes).
10.6. Executing PROC_MUX pass (convert decision trees to multiplexers).
10.7. Executing PROC_DLATCH pass (convert process syncs to latches).
10.8. Executing PROC_DFF pass (convert process syncs to FFs).
10.9. Executing PROC_MEMWR pass (convert process memory writes to cells).
10.10. Executing PROC_CLEAN pass (remove empty switches from decision trees).
Cleaned up 0 empty switches.
10.11. Executing OPT_EXPR pass (perform const folding).
Optimizing module syncinvert.

Le résultat ressemble beaucoup plus à la bascule D que l’on connaît.

Rendu xdot de l’inverseur «mappé»

On peut optimiser ce graphe avec la commande opt, ce qui supprimera la branche inutile BUF -> $0\regval[0:0].

S’ensuit toute une série de commandes d’optimisation comme memory pour détecter les tableaux et utiliser des blocs de ram si possible ou techmap pour «mapper» les cellules d’une bibliothèque donnée.

yosys> opt; memory; opt; techmap; opt
Rendu xdot de l’inverseur mappé avec `techmap`

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).

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é.

Par exemple, si nous voulons synthétiser pour icestick, le FPGA monté sur la carte est un ice40, nous pourrons donc utiliser le script nommé synth_ice40 :

yosys> synth_ice40 
[...]
37.47. Printing statistics.

=== syncinvert ===

   Number of wires:                  6
   Number of wire bits:              6
   Number of public wires:           6
   Number of public wire bits:       6
   Number of memories:               0
   Number of memory bits:            0
   Number of processes:              0
   Number of cells:                  2
     SB_DFFR                         1
     SB_LUT4                         1

37.48. Executing CHECK pass (checking for obvious problems).
Checking module syncinvert...
Found and reported 0 problems.

Le lecteur attentif reconnaîtra la LUT 4 entrées et la basculeD de l’ICE40 dans le schéma généré :

Rendu xdot de l’inverseur synthétisé pour ICE40

Pour connaitre les scripts de synthèse disponibles dans yosys il suffit d’utiliser la complétion de commande avec synth_ :

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

Ce qui nous donne 16 modèles de FPGA supporté «officiellement» par Yosys.

Il n’est pas obligatoire d’avoir un script synth_ pour pouvoir synthétiser pour un modèle de FPGA du moment que l’on fournit la bibliothèque des primitives. Pepijn De Vos 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.

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 Verilog ?

Pepijn a utilisé pour cela une extension de yosys permettant de se connecter au logiciel GHDL. Avec cette extension (encore en bêta mais déjà bien avancée), le VHDL est décodé avec GHDL 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 faire de la conversion VHDL->Verilog sans problème.

Notre inverseur est désormais synthétisé. Nous pouvons donc l’enregistrer au format de notre choix pour passer ensuite au placement routage.

On peut l’écrire au format Verilog par exemple si nous souhaitons le simuler ou tout simplement lire la netlist :

yosys> write_verilog invert_synth.v

41. Executing Verilog backend.
Dumping module `\syncinvert'.

Ce qui donnera les sources suivantes :

/* Generated by Yosys 0.10+0 (git sha1 070cad5f4, clang 8.0.0-svn345496-1~exp1+0~20181029105533.852~1.gbpf10f36 -fPIC -Os) */

(* top =  1  *)
(* src = "invert.v:2.1-19.10" *)
module syncinvert(clock, reset, inval, outval);
  (* src = "invert.v:3.11-3.16" *)
  input clock;
  (* src = "invert.v:5.11-5.16" *)
  input inval;
  (* src = "invert.v:6.12-6.18" *)
  output outval;
  (* src = "invert.v:7.5-7.11" *)
  wire regval;
  (* src = "invert.v:11.1-17.4" *)
  wire regval_SB_DFFR_Q_D;
  (* src = "invert.v:4.11-4.16" *)
  input reset;
  (* module_not_derived = 32'd1 *)
  (* src = "/usr/local/bin/../share/yosys/ice40/cells_map.v:12.34-13.52" *)
  SB_LUT4 #(
    .LUT_INIT(16'h00ff)
  ) inval_SB_LUT4_I3 (
    .I0(1'h0),
    .I1(1'h0),
    .I2(1'h0),
    .I3(inval),
    .O(regval_SB_DFFR_Q_D)
  );
  (* module_not_derived = 32'd1 *)
  (* src = "invert.v:11.1-17.4|/usr/local/bin/../share/yosys/ice40/ff_map.v:9.57-9.103" *)
  SB_DFFR regval_SB_DFFR_Q (
    .C(clock),
    .D(regval_SB_DFFR_Q_D),
    .Q(regval),
    .R(reset)
  );
  assign outval = regval;
endmodule

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.
Et dans la mesure du possible, les noms de registres ont été gardés, ce qui rend le fichier assez facile à lire.

Pour le placement routage, si on utilise nextpnr il faudra «sortir» au format json :

yosys> write_json invert.json

42. Executing JSON backend.

Le fichier invert.json est beaucoup plus large que la sortie verilog (9779 lignes).
Les différents formats de sortie disponibles sont visibles avec la complétion de commande write_ :

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

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.
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 OpenLane.

Enfin, les modèles synthétisés par yosys peuvent servir à faire de la preuve formelle, à partir de sources verilog mais également VHDL.

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.

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 !

Une LED qui clignote sur ICEStick vite vite vite !

Historiquement le ICE40 soudé sur la carte icestick est le premier supporté par des outils libres.

Le célèbre icestick qui a libéré les FPGA

Il est maintenant possible d’utiliser plusieurs programmes open-source pour développer dessus. Voici une méthode avec yosys, nextpnr, icestorm et openFPGALoader.

Dans un premier temps, allez donc cloner, compiler makeInstaller les 4 programmes cités ci-avant :

  • Yosys: Logiciel de synthèse Verilog couteau suisse du monde du FPGA.
  • nextpnr: Logiciel de placement routage supportant de plus en plus de famille de FPGA
  • icestorm: La tempête à l’origine de la libération des ICE40 de Lattice.
  • openFPGALoader: Le configurateur universel pour FPGA.

N’oubliez pas l’option de compilation «ICE40» quand elle est requise, mais c’est expliqué dans les différents tutos de compilation des outils.

Une fois que tout est installé on peut prendre le source Verilog «Blinking Led Project» et le modifier comme ci-dessous :

module blink (
    // Horloge
    input clock,
    output led
);

// Icestick clock : 12Mhz
parameter clock_freq = 12_000_000; // clock frequency
localparam MAX_COUNT = clock_freq;
localparam MAX_COUNT_UPPER = $clog2(MAX_COUNT) - 1;

reg [MAX_COUNT_UPPER:0] counter;
reg led_reg;

assign led = led_reg;

always@(posedge clock)
begin
    if(counter < MAX_COUNT/2)
        led_reg <= 1;
    else
        led_reg <= 0;

    if(counter >= MAX_COUNT)
        counter <= 0;
    else
        counter <= counter + 1;
end

endmodule

Il faut ensuite ajouter les informations de pinout pour l’horloge et la LED dans un fichier pcf que nous nommerons blink.pcf:

set_io clock  21
set_io led 98

Puis enfin, lancer les différentes commande de synthèse/pnr/bitstream :

$ PROJECTNAME=blink
$ VERILOGS="$PROJECTNAME.v"
  • Synthèse avec yosys:
$ yosys -q -p "synth_ice40 -top $PROJECTNAME -json $PROJECTNAME.json" $VERILOGS
  • Placement routage avec nextpnr:
$ nextpnr-ice40 --force --json $PROJECTNAME.json --pcf $PROJECTNAME.pcf --asc $PROJECTNAME.asc --freq 12 --hx1k --package tq144 $1
  • Vérification des timings avec icetime:
$ icetime -p $PROJECTNAME.pcf -P tq144 -r $PROJECTNAME.timings -d hx1k -t $PROJECTNAME.asc
// Reading input .pcf file..
// Reading input .asc file..
// Reading 1k chipdb file..
// Creating timing netlist..
// Timing estimate: 6.12 ns (163.28 MHz)
  • Packaging du bitstream avec icepack :
$ icepack $PROJECTNAME.asc $PROJECTNAME.bin
  • Configuration du fpga avec openFPGALoader:
$ openFPGALoader -b ice40_generic blink.bin 
write to ram
Jtag frequency : requested 6.00MHz   -> real 6.00MHz  
Parse file DONE
00
Detail: 
Jedec ID          : 20
memory type       : ba
memory capacity   : 16
EDID + CFD length : 10
EDID              : 0000
CFD               : 
Erasing: [==================================================] 100.00%
Done
Writing: [==================================================] 100.00%
Done
Wait for CDONE DONE

Et voila, la LED clignote.

Réception du kit Tang Nano 4K

La désormais célèbre société chinoise Sipeed vient de sortir un tout petit kit de développement autour d’un FPGA Gowin et muni d’une sortie HDMI ainsi que d’une entrée caméra : la Tang Nano 4K.

Principaux périphériques disponibles sur la Tang Nano 4K

Et non, elle n’est pas compatible avec des écrans HDMI 4K 😉 Le nom marketing bien choisi désigne le nombre de LUT disponibles.

Le pinout trouvé sur la fiche descriptive d’aliexpress
Attention à certain IO du pinout, qu’il vaut mieux éviter d’utiliser… comme la sortie LED (IOT7A) ! Le document en question semble être celui là

Il est encore difficile de trouver des informations techniques sur cette carte, pourtant disponible (et rapidement livrée) sur aliexpress. Le wiki officiel est encore intégralement en chinois, mais on trouve le code d’exemple sur github. Le schéma de la carte est dispo sur le site de sipeed ici (ou sur le blog du flf si le firewall chinois fait des caprices 😉

À 18$ il n’était pas question de passer à coté, j’ai donc commandé une version avec caméra OV2640 ainsi qu’une version sans caméra :

Les deux kits tels que reçu dans ma boite aux lettres.

Le tout pour une quarantaine d’€.

Branchement

Un câble USB-C est fourni dans la boite, voyons ce qu’il se passe au branchement de la version sans caméra:

 sudo dmesg -c
[34644.177355] usb 1-2.1.1: new full-speed USB device number 14 using xhci_hcd
[34644.283502] usb 1-2.1.1: not running at top speed; connect to a high speed hub
[34644.305274] usb 1-2.1.1: New USB device found, idVendor=0403, idProduct=6010, bcdDevice= 5.00
[34644.305288] usb 1-2.1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[34644.305292] usb 1-2.1.1: Product: JTAG Debugger
[34644.305295] usb 1-2.1.1: Manufacturer: SIPEED
[34644.305298] usb 1-2.1.1: SerialNumber: FactoryAIOT Pro
[34644.311295] ftdi_sio 1-2.1.1:1.0: FTDI USB Serial Device converter detected
[34644.311336] usb 1-2.1.1: Detected FT2232C
[34644.316362] usb 1-2.1.1: FTDI USB Serial Device converter now attached to ttyUSB0
[34644.316513] ftdi_sio 1-2.1.1:1.1: FTDI USB Serial Device converter detected
[34644.316548] usb 1-2.1.1: Detected FT2232C
[34644.322352] usb 1-2.1.1: FTDI USB Serial Device converter now attached to ttyUSB1

La version avec caméra donne exactement la même chose.

Le dmesg de Linux laisse apparaître deux interfaces tty. L’une est certainement un convertisseur jtag pour configurer le FPGA et l’autre une interface uart permettant de communiquer avec l’application comme on a pu le voir avec la Tang Nano «classique».

Si l’on branche un écran au HDMI on voit défiler quelques «pattern» avant de s’arrêter sur un écran vert sur fond bleu.

Pour le moment je n’ai pas réussi à obtenir grand chose de ces deux uarts.

Par la suite j’éditerais cet article pour vous parler de la configuration du FPGA.

Synthèse et configuration

Le plus simple pour commencer avec le kit est d’aller voir les deux projets proposés par Sipeed sur github et de les cloner.

$ git clone https://github.com/sipeed/TangNano-4K-example.git
$ cd TangNano-4K-example/

Deux projets sont disponible dans ce dépôt, vus de loin l’un est pour faire clignoter une led et l’autre pour l’exemple HDMI programmé par défaut dans l’eeprom du kit :

$ ls
dk_video/  led_test/

Pour se faire la main il est donc naturel de commencer par la led.

Il faut d’abord lancer l’IDE officiel de gowin, comme décrit dans l’article de hackable-32 (le plus compliqué avec l’installation de gowin est d’obtenir la licence, après ça roule). Puis ouvrir le fichier de projet fourni nommé project/led_test.gprj et se trouvant dans le répertoire led_test/projet.

Le FPGA du kit se nomme GW1NSR-LV4CQN48PC7/I6 et le code Verilog de clignotement est le suivant. Quand au pinout le voici au format «cst» ci-dessous :

IO_LOC "led" 10;
IO_PORT "led" PULL_MODE=NONE DRIVE=8;
IO_LOC "sys_rst_n" 15;
IO_PORT "sys_rst_n" PULL_MODE=UP;
IO_LOC "sys_clk" 45;
IO_PORT "sys_clk" PULL_MODE=UP;

Le projet est déjà synthétisé, si on souhaite le relancer il suffit de faire un clic-droit «rerun» sur «Synthesize» . Le bitstream est généré au format «fs» et se nomme project/impl/pnr/led_test.fs.

Le kit est désormais reconnu par openFPGALoader:

$ openFPGALoader --detect
write to ram
Jtag frequency : requested 6.00MHz   -> real 6.00MHz  
index 0:
	idcode 0x100981b
	manufacturer Gowin
	family GW1NSR
	model  GW1NSR-4C
	irlength 8

Il suffit donc de programmer le bistrteam (format fs) au moyen de la commande :

$ openFPGALoader led_test/project/impl/pnr/led_test.fs
write to ram
Jtag frequency : requested 6.00MHz   -> real 6.00MHz  
Parse file Parse led_test/project/impl/pnr/led_test.fs: 
Done
DONE
Jtag frequency : requested 2.50MHz   -> real 2.00MHz  
erase SRAM Done
Flash SRAM: [==================================================] 100.00%
Done
SRAM Flash: Success

Et pour l’écrire dans l’eeprom il suffit d’ajouter l’option -f:

$ openFPGALoader ide/gbhdmi/impl/pnr/gbhdmi.fs -f
write to flash
Jtag frequency : requested 6.00MHz   -> real 6.00MHz  
Parse file Parse ide/gbhdmi/impl/pnr/gbhdmi.fs: 
Done
DONE
Jtag frequency : requested 2.50MHz   -> real 2.00MHz  
erase SRAM Done
erase Flash Done
write Flash: [==================================================] 100.00%
Done
CRC check: Success

Le truc se programme et la led clignote.

Le HDMI

Le deuxième projet proposé dans le dépôt concerne le HDMI. Bon si on regarde le contenu du Top on se rend compte qu’il fait bien plus que le simple HDMI puisqu’il pilote également la ram, la Nor et la caméra.

Le générateur de pattern se charge également de générer les signaux de synchronisation vidéo. Mais ce qui nous intéresse particulièrement c’est le bloc qui pilote le HDMI. Ce bloc se prénomme DVI_TX_top et … il est encrypté 🙁

Le bloc est tout de même instanciable au moyen d’une BlackBox chisel. Ce qui permet d’adapter le projet GbVGA en GbHDMI

Pour la vidéo du montage en fonctionnement c’est par là.

La caméra OV2640

Je n’ai pas vu d’exemple de code utilisant la caméra ov2640 avec ce kit pour le moment. Il est probable que ça ne soit pas encore disponible.

Ressources

Convertir du VHDL en Verilog librement avec Yosys et GHDL

Il y a quelques années, nous parlions de l’utilitaire vhdl2vl sur ce blog. Cette solution est intéressante mais limitée car le projet est relativement au point mort.

Depuis quelques mois une solution beaucoup plus «hype» est disponible, alliant le couteau suisse du Verilog Yosys, la référence en simulation libre en VHDL GHDL et le plugin ghdl-yosys-plugin. Cette solution permet dès à présent de convertir la plupart des codes VHDL en Verilog.

Voyons comment faire avec le module de réception uart proposé par nandland : UART_RX.vhd.

$ mkdir vhdlconv
$ cd vhdlconv
$ ls
UART_RX.vhd

Il faut tout d’abord compiler et installer Yosys et GHDL selon la procédure donnée sur les sites respectif.

Un fois fait il faut installer et compiler le plugin ghdl-yosys-plugin comme expliqué sur le dépot. Dans notre cas, cette compilation sera faite dans le répertoire /opt/ghdl-yosys-plugin.

Un fois l’installation effectuée nous pouvons nous lancer dans la conversion avec le plugin :

$ export GHDL_YOSYS_PLUGIN=/opt/ghdl-yosys-plugin/ghdl.so

On élabore le vhdl avec ghdl :

$ ghdl -a UART_RX.vhd 
$ ls
UART_RX.vhd  work-obj93.cf

On lance yosys avec le module ghdl :

$ yosys -m $GHDL_YOSYS_PLUGIN 
...
 |  yosys -- Yosys Open SYnthesis Suite                                       
 |  Copyright (C) 2012 - 2020  Claire Xenia Wolf <claire@yosyshq.com>         
...
 Yosys 0.9+4081 (git sha1 862e84eb, clang 10.0.0-4ubuntu1 -fPIC -Os)

On lit le module fraîchement élaboré:

...
yosys> ghdl UART_RX
1. Executing GHDL.
Importing module UART_RX.

Puis on lance la synthèse :

yosys> proc; opt; fsm; opt; memory; opt;

2. Executing PROC pass (convert processes to netlists).

2.1. Executing PROC_CLEAN pass (remove empty switches from decision trees).
Cleaned up 0 empty switches.

2.2. Executing PROC_RMDEAD pass (remove dead branches from decision trees).
Removed a total of 0 dead cases.

[...]

7.8. Executing OPT_EXPR pass (perform const folding).
Optimizing module UART_RX.

7.9. Finished OPT passes. (There is nothing left to do.)

Et enfin, on peut écrire le Verilog du module converti :

yosys> write_verilog UART_RX.v

8. Executing Verilog backend.
Dumping module `\UART_RX'.

yosys> exit

Le module verilog ainsi généré possède les même noms d’interfaces:

$ head -n 20 UART_RX.v
/* Generated by Yosys 0.9+4081 (git sha1 862e84eb, clang 10.0.0-4ubuntu1 -fPIC -Os) */

module UART_RX(i_Clk, i_RX_Serial, o_RX_DV, o_RX_Byte);
  (* unused_bits = "7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" *)
  wire [31:0] _00_;
  wire [2:0] _01_;
  wire [6:0] _02_;
  wire _03_;
  wire _04_;
  wire _05_;
  (* unused_bits = "3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31" *)
  wire [31:0] _06_;
  wire [2:0] _07_;
  wire [2:0] _08_;
  wire [2:0] _09_;
  wire [6:0] _10_;
  wire [2:0] _11_;
  wire _12_;
  wire [2:0] _13_;
  wire _14_;

$ head -n 20 UART_RX.vhd
library ieee;
use ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;
 
entity UART_RX is
  generic (
    g_CLKS_PER_BIT : integer := 115     -- Needs to be set correctly
    );
  port (
    i_Clk       : in  std_logic;
    i_RX_Serial : in  std_logic;
    o_RX_DV     : out std_logic;
    o_RX_Byte   : out std_logic_vector(7 downto 0)
    );
end UART_RX;
 
 
architecture rtl of UART_RX is
 
  type t_SM_Main is (s_Idle, s_RX_Start_Bit, s_RX_Data_Bits,

Et même si le code n’est pas très lisible on retrouve ses petits avec le nom des signaux interne du module.

Ce qui est vraiment intéressant ici c’est que le code verilog généré est parfaitement synthétisable avec n’importe quel logiciel de synthèse verilog, on peut également utiliser Verilator pour accélérer nos simulation et enfin il est possible de faire de la preuve formelle avec Yosys.

Plus d’excuse pour ne pas mixer du code VHDL avec du Verilog maintenant puisque tout est convertible en Verilog !

VHDL: afficher du texte au moment de la synthèse vivado

Lorsque l’on essait de faire des modules VHDL génériques, on utilise massivement les paramètres generic map des modules.

Ces paramètres sont utilisés ensuite à la synthèse pour calculer des tailles de tableaux, des constantes et autre structures matérielles générées.

Pour déverminer cette partie du code on a besoin de «voir» les valeurs qui sont calculées. En VHDL il n’y a pas de printf pour ça, mais il y a report utilisé en simulation dans un process :

process is
begin
    report "Affichons des trucs" severity note;
    wait;
end process;

Sauf que nous ne somme pas en simulation, ce process ne sera même pas traité à la synthèse.

Pour pouvoir afficher du texte on peut utiliser les assertions en les mettant systématiquement à faux pour être sur qu’elles soient affichées :

assert false report "Affichons des trucs à la synthèse" severity note;

Mais rien ne s’affiche dans les log à la synthèse Vivado. Ça n’est pas un bug, c’est juste que Xilinx a désactivé ces messages par défaut. Pour les réactiver il suffit de taper cette ligne magique dans la console tcl avant de lancer la synthèse :

set_param synth.elaboration.rodinMoreOptions {rt::set_parameter ignoreVhdlAssertStmts false}

Le message est ensuite visible dans les log:

INFO: [Synth 8-63] RTL assertion: "Affichons des trucs à la synthèse" [plop.vhd:108]

Merci à brimdavis pour le truc.

Test d’une carte Gowin avec LiteX

Après avoir déballé le kit gowin proposé par trenz micro. Il faut trouver quelques chose à faire de plus avancé qu’un simple clignotement de LED. Pour le clignotement de LED et la prise en main des outils, le lecteur se référera à l’article Hackable 32.

Pourquoi ne pas tenter le Linux des FPGA, j’ai nommé LiteX (Prononcez Lahïtixe ) ? LiteX est un framework HDL basé sur Migen pour construire des systèmes matériel facilement en python.

LiteX inclut un langage de description matériel, mais également tous les outils permettant de faire des simulations, la synthèses et générer les bitstreams pour la plupart des FPGA du marché. Bien évidement, en ce qui concerne la synthèse et les bitstreams, LiteX pilote les outils propriétaires des constructeurs. Ce pilotage ne pose généralement pas trop de problème, car tous les outils constructeurs proposent des interfaces en ligne de commande.

La carte que nous allons tenter de faire fonctionner avec LiteX est donc la TEC0117-1 produite par Trenz electronic et munie d’un FPGA gowin .

La carte TEC0117-1 de trenz micro se pilote intégralement avec le port série.

D’après le wiki, la carte n’est pas encore officiellement supporté par LiteX puisqu’elle ne se trouve pas dans la liste du projet LiteX-Boards

Pas dans le tableau de la documentation du moins, car en fouillant dans le code du projet, il semble qu’il y ait déjà un embryon de quelques chose ici. Voila qui est très engageant pour tester la carte.

Voyons donc voir les étapes nous permettant de construire un système avec LiteX.

Installation de LiteX

Le plus simple pour installer LiteX sur son ordinateur est d’aller suivre le guide officiel d’installation.

$ wget https://raw.githubusercontent.com/enjoy-digital/litex/master/litex_setup.py
$ chmod +x litex_setup.py
$ ./litex_setup.py init install --user (--user to install to user directory)

Attention, si comme moi vous avez un pc qui commence à prendre sérieusement de l’âge, sachez que le script litex_setup.py va descendre beaucoup de projets annexes de LiteX. Ça va prendre quelques minutes.

On aura besoin également de gcc compilé pour RISC-V :

$ ./litex_setup.py gcc

Il faudra bien penser à l’exporter à chaque fois qu’on en aura besoin :

$ export PATH=$PATH:$(echo $PWD/riscv64-*/bin/)

Construire le système pour TEC0117

Pour construire un système pour la carte il faut ensuite se rendre dans le répertoire contenant la carte puis lancer le script python correspondant:

$ export PATH=$PATH:$(echo $PWD/riscv64-*/bin/)
$ cd litex-boards/litex_boards/targets
$ python3 trenz_tec0117.py

Pour synthétiser et générer le bitstream il faut d’abord ajouter le lien vers l’ide (1.9.7 minimum) de gowin :

$ export PATH=$PATH:/opt/gowin/1_9_7/IDE/bin/

Puis lancer le build:

$ python litex-boards/litex_boards/targets/trenz_tec0117.py --build
INFO:SoC:        __   _ __      _  __  
INFO:SoC:       / /  (_) /____ | |/_/  
INFO:SoC:      / /__/ / __/ -_)>  <    
INFO:SoC:     /____/_/\__/\__/_/|_|  
INFO:SoC:  Build your hardware, easily!
INFO:SoC:--------------------------------------------------------------------------------

...

Running timing analysis......
[95%] Timing analysis completed
Bitstream generation in progress......
Bitstream generation completed
Running power analysis......
[100%] Power analysis completed
Generate file "/home/fabienm/myapp/litex/build/trenz_tec0117/gateware/impl/pnr/project.power.html" completed
Generate file "/home/fabienm/myapp/litex/build/trenz_tec0117/gateware/impl/pnr/project.pin.html" completed
Generate file "/home/fabienm/myapp/litex/build/trenz_tec0117/gateware/impl/pnr/project.rpt.html" completed
Generate file "/home/fabienm/myapp/litex/build/trenz_tec0117/gateware/impl/pnr/project.rpt.txt" completed
Generate file "/home/fabienm/myapp/litex/build/trenz_tec0117/gateware/impl/pnr/project.tr.html" completed
Fri Jul  9 13:18:07 2021

Le bitstream généré au format *.fs se trouve ensuite dans le répertoire

./build/trenz_tec0117/gateware/impl/pnr/project.fs

On pourra configurer le FPGA directement avec openFPGALoader :

$ openFPGALoader ./build/trenz_tec0117/gateware/impl/pnr/project.fs
Parse ./build/trenz_tec0117/gateware/impl/pnr/project.fs: 
checksum 0x15d3
Done
erase SRAM Done
Flash SRAM: [==================================================] 100.000000%
Done
SRAM Flash: Success

Ou avec la bonne option litex (qui fait appel à openFPGALoader de toute manière):

$ python3 ../litex-boards/litex_boards/targets/trenz_tec0117.py --load
INFO:SoC:        __   _ __      _  __  
INFO:SoC:       / /  (_) /____ | |/_/  
INFO:SoC:      / /__/ / __/ -_)>  <    
INFO:SoC:     /____/_/\__/\__/_/|_|  
INFO:SoC:  Build your hardware, easily!
INFO:SoC:--------------------------------------------------------------------------------
INFO:SoC:Creating SoC... (2021-07-12 19:05:10)
INFO:SoC:--------------------------------------------------------------------------------
INFO:SoC:FPGA device : GW1NR-LV9QN88C6/I5.
INFO:SoC:System clock: 25.00MHz.
INFO:SoCBusHandler:Creating Bus Handler...

...

INFO:SoC:Initializing ROM rom with contents (Size: 0x51cc).
INFO:SoC:Auto-Resizing ROM rom from 0x6000 to 0x51cc.
Parse /home/user/myapp/litex/myapp/build/trenz_tec0117/gateware/impl/pnr/project.fs: 
checksum 0xa3a3
Done
erase SRAM Done
Flash SRAM: [==================================================] 100.000000%
Done
SRAM Flash: Success

La confirmation de la bonne configuration est donnée par le message de la console, mais également par le chenillard de LED rouge.

Console litex>

Le convertisseur USB-uart de la carte possède deux interfaces ttyUSB, la première vient d’être utilisée par openFPGALoader pour charger le bitstream, la seconde permet de se connecter à la console litex :

$ screen /dev/ttyUSB1 115200
litex> reboot


        __   _ __      _  __
       / /  (_) /____ | |/_/
      / /__/ / __/ -_)>  <
     /____/_/\__/\__/_/|_|
   Build your hardware, easily!

 (c) Copyright 2012-2021 Enjoy-Digital
 (c) Copyright 2007-2015 M-Labs

 BIOS built on Jul  9 2021 13:17:06
 BIOS CRC passed (855636f6)

 Migen git sha1: 3ffd64c
 LiteX git sha1: 2b49430f

--=============== SoC ==================--
CPU:            VexRiscv_Lite @ 25MHz
BUS:            WISHBONE 32-bit @ 4GiB
CSR:            32-bit data
ROM:            24KiB
SRAM:           4KiB
L2:             0KiB
SDRAM:          8192KiB 16-bit @ 25MT/s (CL-2 CWL-2)

--========== Initialization ============--
Initializing SDRAM @0x40000000...
Switching SDRAM to software control.
Switching SDRAM to hardware control.
Memtest at 0x40000000 (2.0MiB)...
  Write: 0x40000000-0x40200000 2.0MiB     
   Read: 0x40000000-0x40200000 2.0MiB     
Memtest OK
Memspeed at 0x40000000 (2.0MiB)...
  Write speed: 5.6MiB/s
   Read speed: 6.2MiB/s

--============== Boot ==================--
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
             Timeout
No boot medium found

--============= Console ================--

litex> 

La commande help nous donnes les commandes disponibles :

litex> help


LiteX BIOS, available commands:

leds                     - Set Leds value
flush_l2_cache           - Flush L2 cache
flush_cpu_dcache         - Flush CPU data cache
crc                      - Compute CRC32 of a part of the address space
ident                    - Identifier of the system
help                     - Print this help

serialboot               - Boot from Serial (SFL)
reboot                   - Reboot
boot                     - Boot from Memory

mem_speed                - Test memory speed
mem_test                 - Test memory access
mem_copy                 - Copy address space
mem_write                - Write address space
mem_read                 - Read address space
mem_list                 - List available memory regions

sdram_test               - Test SDRAM

Photo traditionnelle

Avec LiteX, une tradition «twitter» veux que l’on fasse une photo du kit démarrant LiteX avec la console démarrée.

Photo trophée de la tec0117 avec LiteX

Et voila \o/

L’entrée en matière est incroyablement facile et fait honneur au slogan «Build your hardware, easily!».

Nous regarderons dans de futur articles ce que l’on peut faire avec.

Utiliser UNISIM avec GHDL et CocoTB

Les constructeurs de FPGA fournissent des modèles VHDL de leurs primitives. Chez Xilinx cela se présente sous la forme d’une librairie nommée UNISIM.

Le logiciel libre de simulation GHDL n’inclut pas les sources VHDL de cette librairie dans son dépôt officiel car ça n’est pas sa propriété. Cependant, GHDL fourni des scripts permettant de les pré-compiler pour son projet.

Nous allons voir ici comment se servir des primitives disponible dans vivado avec une simulation utilisant CocoTB.

Les sources des primitives se trouvent dans le répertoire d’installation de Vivado

data/vhdl/src/unisims/

Pour les retrouver on peut utiliser la commande fd-find comme ceci :

$ fd unisim -e vhd
Vitis/2021.2/scripts/rt/data/unisim_VCOMP.vhd
Vitis/2021.2/scripts/rt/data/unisim_VCOMP_8h.vhd
Vitis/2021.2/scripts/rt/data/unisim_VCOMP_diablo.vhd
Vitis/2021.2/scripts/rt/data/unisim_VCOMP_e.vhd
Vitis/2021.2/scripts/rt/data/unisim_VPKG.vhd
Vivado/2021.2/data/vhdl/src/unisims/unisim_VCOMP.vhd
Vivado/2021.2/data/vhdl/src/unisims/unisim_VPKG.vhd
Vivado/2021.2/data/vhdl/src/unisims/unisim_retarget_VCOMP.vhd
Vivado/2021.2/ids_lite/ISE/vhdl/src/unisims/unisim_VCOMP.vhd
Vivado/2021.2/ids_lite/ISE/vhdl/src/unisims/unisim_VPKG.vhd
Vivado/2021.2/scripts/rt/data/unisim_VCOMP.vhd
Vivado/2021.2/scripts/rt/data/unisim_VCOMP_8h.vhd
Vivado/2021.2/scripts/rt/data/unisim_VCOMP_diablo.vhd
Vivado/2021.2/scripts/rt/data/unisim_VCOMP_e.vhd

# et pour unimacro :
$ fd unimacro -e vhd
Vitis/2021.2/scripts/rt/data/unimacro_VCOMP.vhd
Vivado/2021.2/data/vhdl/src/unimacro/unimacro_VCOMP.vhd
Vivado/2021.2/ids_lite/ISE/vhdl/src/unimacro/unimacro_VCOMP.vhd
Vivado/2021.2/scripts/rt/data/unimacro_VCOMP.vhd$ fd unimacro -e vhd
Vitis/2021.2/scripts/rt/data/unimacro_VCOMP.vhd
Vivado/2021.2/data/vhdl/src/unimacro/unimacro_VCOMP.vhd
Vivado/2021.2/ids_lite/ISE/vhdl/src/unimacro/unimacro_VCOMP.vhd
Vivado/2021.2/scripts/rt/data/unimacro_VCOMP.vhd
$ fd unimacro -e vhd
Vitis/2021.2/scripts/rt/data/unimacro_VCOMP.vhd
Vivado/2021.2/data/vhdl/src/unimacro/unimacro_VCOMP.vhd
Vivado/2021.2/ids_lite/ISE/vhdl/src/unimacro/unimacro_VCOMP.vhd
Vivado/2021.2/scripts/rt/data/unimacro_VCOMP.vhd

On s’assure d’avoir la variable d’environnement XILINX_VIVADO bien configurée :

$ export XILINX_VIVADO=/opt/Xilinx/Vivado/2021.2/Vivado/2021.2/
$ echo $XILINX_VIVADO
/opt/Xilinx/Vivado/2021.2/Vivado/2021.2/

Il peut être intéressant de mettre les librairies compilé à cet endroit pour y faire référence depuis tous ses projets ensuite :

cd data/vhdl
mkdir ghdl
cd ghdl
/usr/local/lib/ghdl/vendors/compile-xilinx-vivado.sh -all --vhdl2008
[...]

Pour compiler la librairie unisim pour vivado on utilisera le script suivant :

/usr/local/lib/ghdl/vendors/compile-xilinx-vivado.sh -a --vhdl2008
Loading environment...
Not all Xilinx primitives are VHDL-2008 compatible! Setting CONTINUE_ON_ERROR to TRUE.
Analyzing library 'unisim'...
Creating VHDL Library 'unisim'...
Analyzing files into library 'unisim'...
  WARNING: /opt/Xilinx/Vivado/2020.2/data/vhdl/src/unisims/primitive/SYSMONE4.vhd:1536:44:warning: prefix of array attribute must be an object name [-Wattribute]
SCRIPT ERROR: Unfiltered line
v_str_time_length := time'image(now)'length;
SCRIPT ERROR: Unfiltered line
^
  Warnings detected by filtering script.
Analyzing library 'secureip'...
Creating VHDL Library 'secureip'...
Analyzing files into library 'secureip'...
Analyzing library 'unimacro'...
Creating VHDL Library 'unimacro'...
Analyzing files into library 'unimacro'...
Analyzing library 'unifast'...
Creating VHDL Library 'unifast'...
Analyzing files into library 'unifast'...
Analyzing library 'secureip'...
Creating VHDL Library 'secureip'...
Analyzing files into library 'secureip'...
  WARNING: /opt/Xilinx/Vivado/2020.2/data/vhdl/src/unifast/secureip/GTHE2_CHANNEL.vhd:29:1:warning: entity "gthe2_channel" was also defined in file "/opt/Xilinx/Vivado/2020.2/data/vhdl/src/unisims/secureip/GTHE2_CHANNEL.vhd" [-Wlibrary]
SCRIPT ERROR: Unfiltered line
library IEEE;
SCRIPT ERROR: Unfiltered line
^
  Warnings detected by filtering script.
  WARNING: /opt/Xilinx/Vivado/2020.2/data/vhdl/src/unifast/secureip/GTXE2_CHANNEL.vhd:34:1:warning: entity "gtxe2_channel" was also defined in file "/opt/Xilinx/Vivado/2020.2/data/vhdl/src/unisims/secureip/GTXE2_CHANNEL.vhd" [-Wlibrary]
SCRIPT ERROR: Unfiltered line
library IEEE;
SCRIPT ERROR: Unfiltered line
^
  Warnings detected by filtering script.
--------------------------------------------------------------------------------
Compiling Xilinx Vivado libraries [SUCCESSFUL]

La compilation prend un temps infini, compter au moins 5 minutes sur un PC muni de 16 cœurs. Il suffira ensuite d’ajouter les lignes suivantes à son makefile CocoTB :


EXTRA_ARGS+=--std=08
EXTRA_ARGS+=-frelaxed-rules

UNISIMDIR=$(VIVADODIR)/data/vhdl/ghdl/xilinx-vivado/unisim/v93
EXTRA_ARGS=-P$(UNISIMDIR)
...
EXTRA_ARGS=-P$(UNIMACRODIR)

Et roulez jeunesse.