Archives mensuelles : mai 2022

Découverte du FPGA européen, le GateMate de CologneChip

Nous l’attendions depuis au moins deux ans, le FPGA européen GateMate des allemands de CologneChip est désormais disponible dans votre crémerie habituelle.

Ça y est il est arrivé, le kit de développement GateMate !

La dimension européenne de ce FPGA n’est pas la seule nouveauté, c’est également un des premier (mais pas le premier) à privilégier les outils open source pour son utilisation. Que cela soit pour la simulation ou pour la synthèse tous les exemples donnés dans la documentation utilisent des logiciels libres (Icarus, GHDL et surtout Yosys). Même pour la visualisation des chronogrammes, gtkwave est utilisé par défaut en exemple.

[À noter que le kit de développement m’a été offert gracieusement par CologneChip]

Caractéristiques du GateMate

Les caractéristiques du GateMate le positionne au niveau d’un petit Spartan7 de Xilinx ou d’un Trion T20 de Efinix.

Le composant est gravé par GlobalFounderies en 28nm.

Architecture générale (DS1001)

La cellule de base est nommée CPE pour «Central Programming Element».

Structure du CPE (DS1001)

On notera l’absence remarqué de blocs multiplieurs. Cette absence est compensée par le «fast signal path routing» qui permet de chaîner les CPE afin de construire un multiplieur de dimension voulue.

Caractéristiques du kit

Pour le moment, seuls les trois petit FPGA de la gamme GateMate semblent être en production. CologneChip propose un kit de développement muni du plus petit GateMate : le CCGM1A1

Le schéma blocs de la carte de développement (source pdf officiel)

La carte de développement possède deux entrées USB:

  • une pour l’alimentation
  • et une pour la programmation et la communication avec le FPGA (FTDI 2232), mais qui peut également servir d’alimentation.

La magie du logiciel libre openFPGALoader permet de détecter le FPGA directement au branchement:

$ openFPGALoader --detect
Jtag frequency : requested 6.00MHz   -> real 6.00MHz  
index 0:
	idcode 0x20000001
	manufacturer colognechip
	family GateMate Series
	model  GM1Ax
	irlength 6

En effet, avant même la sortie du gatemate, CologneChip avait déjà proposé le support du composant sur le dépot openFPGALoader.

Toolchain

CologneChip fourni un guide d’installation de la chaîne de développement sur son site internet.

Hormis le logiciel de placement routage (GateMate), tous les outils sont des logiciels libre bien connus du monde du FPGA (source UG1002).

Tous les outils sont connus du monde du FPGA opensource et leurs installations sont intensivement décrites dans les différents dépôts des projets.

Si l’on souhaite éviter la case compilation, l’entreprise fournie même des versions binaires. Ces binaires ne sont téléchargeable que via un compte enregistré sur leur site pour le moment. Deux paquets de logiciels sont nécessaires :

  • Yosys compilé pour le gatemate: pour la synthèse Verilog
  • p_r: le logiciel de placement routage.

Pour le moment, la version binaire proposée en téléchargement sur le site n’est disponible que pour windows. Ces «.exe» s’exécutent cependant parfaitement sous Linux au moyen de l’émulateur wine bien connu des Linuxiens.

L’archive téléchargée se décompresse simplement avec unzip :

$ unzip cc-toolchain-win.zip 
Archive:  cc-toolchain-win.zip
 extracting: cc-toolchain-win/openFPGALoader-mingw64-v.0.8.0+80eeaef.zip  
 extracting: cc-toolchain-win/p_r-2022.04-001.zip  
  inflating: cc-toolchain-win/ug1002-toolchain-install-2022-04.pdf  
 extracting: cc-toolchain-win/yosys-win32-mxebin-0.15+57.zip  

La version windows de openFPGALoader ne fonctionne pas bien en émulation wine, il est préférable d’en compiler une version à jour à partir des sources officiels.

Pour le reste, on peut s’affranchir de compiler yosys en utilisant celle fournie. Et pour p_r, les sources n’étant pas fournies pour le moment, cette version est la seule que nous pourrons utiliser.

Pour les installer, il suffit de les décompresser :

$ cd cc-toolchain-win/
$ unzip p_r-2022.04-001.zip
$ unzip yosys-win32-mxebin-0.15+57.zip

La notice d’utilisation des commandes est données dans le pdf de l’archive nommé ug1002-toolchain-install-2022-04.pdf.

C’est l’installation la plus simple que j’ai pu avoir à faire pour des outils de développement FPGA. La place occupée sur le disque dur de son ordinateur est plusieurs milliers de fois plus petites que les logiciels habituels :

$ cd p_r-2022.04-001/
$ du -sh .
24M	.
$ cd yosys-win32-mxebin-0.15+57/
$ du -sh .
32M	.

Évidemment, c’est pour seulement un modèle de FPGA, mais cela reste beaucoup plus petit.

Clignotons

Il est temps de rentrer dans le vif du sujet et de faire clignoter les LED. L’exemple donné dans le document ug1002 est trop rapide pour voir les LED clignoter. Nous allons donc faire un clignoteur plus traditionnel comme visible ci-dessous en Verilog :

`timescale 1ns / 1ps

module blink(
		input wire clk,
		input wire rst,
		output reg led
	);

	localparam MAX_COUNT = 10_000_000;
	localparam CNT_TOP = $clog2(MAX_COUNT);

	wire i_clk;
	reg [CNT_TOP-1:0] counter;

	assign i_clk = clk;

	always @(posedge i_clk)
	begin
		if (!rst) begin
			led <= 0;
			counter <= 0;
		end else begin
			if(counter < MAX_COUNT/2)
				led <= 1;
			else
				led <= 0;

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

endmodule

Contrairement à beaucoup de FPGA, le GateMate ne définit pas d’états initial à 0 de ses registres. Une entrée reset est donc nécessaire.

Le pinout est décrit au moyen d’un fichier «ccf» :

## blink.ccf

Pin_in   "clk"  Loc = "IO_SB_A8" | SCHMITT_TRIGGER=true;
Pin_in   "rst"  Loc = "IO_EB_B0"; # SW3
Pin_out  "led"  Loc = "IO_EB_B1"; # D1

Une fois que ces deux fichiers sont prêt il suffit de lancer yosys pour la synthèse :

$ wine ../../cc-toolchain-win/yosys-win32-mxebin-0.15+57/yosys.exe -l yosys.log -p 'read_verilog blink.v; synth_gatemate -top blink -vlog blink_synth.v'

Wine génère tout un tas d’erreurs mais fini par nous lancer la synthèse tout de même

$ wine ../../cc-toolchain-win/yosys-win32-mxebin-0.15+57/yosys.exe -l yosys.log -p 'read_verilog blink.v; synth_gatemate -top blink -vlog blink_synth.v'
wine: created the configuration directory '/home/oem/.wine'
0012:err:ole:marshal_object couldn't get IPSFactory buffer for interface {00000131-0000-0000-c000-000000000046}
0012:err:ole:marshal_object couldn't get IPSFactory buffer for interface {6d5140c1-7436-11ce-8034-00aa006009fa}
0012:err:ole:StdMarshalImpl_MarshalInterface Failed to create ifstub, hres=0x80004002
0012:err:ole:CoMarshalInterface Failed to marshal the interface {6d5140c1-7436-11ce-8034-00aa006009fa}, 80004002
0012:err:ole:get_local_server_stream Failed: 80004002
0014:err:ole:marshal_object couldn't get IPSFactory buffer for interface {00000131-0000-0000-c000-000000000046}
0014:err:ole:marshal_object couldn't get IPSFactory buffer for interface {6d5140c1-7436-11ce-8034-00aa006009fa}
0014:err:ole:StdMarshalImpl_MarshalInterface Failed to create ifstub, hres=0x80004002
0014:err:ole:CoMarshalInterface Failed to marshal the interface {6d5140c1-7436-11ce-8034-00aa006009fa}, 80004002
0014:err:ole:get_local_server_stream Failed: 80004002
Could not find Wine Gecko. HTML rendering will be disabled.
Could not find Wine Gecko. HTML rendering will be disabled.
wine: configuration in L"/home/oem/.wine" has been updated.

On ne va pas recopier toute la trace de synthèse ici mais juste la partie ressources utilisées donnée en fin de synthèse :

2.49. Printing statistics.

=== blink ===

   Number of wires:                 49
   Number of wire bits:            294
   Number of public wires:           5
   Number of public wire bits:      28
   Number of memories:               0
   Number of memory bits:            0
   Number of processes:              0
   Number of cells:                159
     CC_ADDF                        65
     CC_BUFG                         1
     CC_DFF                         25
     CC_IBUF                         2
     CC_LUT1                        24
     CC_LUT2                         5
     CC_LUT4                        36
     CC_OBUF                         1

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

2.51. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \blink..

2.52. Executing Verilog backend.

2.52.1. Executing BMUXMAP pass.

2.52.2. Executing DEMUXMAP pass.
Dumping module `\blink'.

End of script. Logfile hash: dcf7a4084e
Yosys 0.15+57 (git sha1 207417617, i686-w64-mingw32.static-g++ 11.2.0 -Os)
Time spent: 1% 19x opt_clean (0 sec), 1% 18x opt_expr (0 sec), ...

Le fichier de sortie blink_synth.v est au format … Verilog également! C’était bien la peine de lancer Yosys tient !

Mais non, Verilog est un excellent format pour décrire une netlist autant que du RTL. Et de fait, le code Verilog généré n’est pas hyper lisible. Il est constitué d’une série d’instanciations et de connections des primitives du FPGA :

//...
 
 CC_LUT2 #(
    .INIT(4'h8)
  ) _051_ (
    .I0(_041_[0]),
    .I1(_041_[1]),
    .O(_043_[2])
  );
  CC_LUT4 #(
    .INIT(16'h0001)
  ) _052_ (
    .I0(counter[15]),
    .I1(counter[20]),
    .I2(counter[23]),
    .I3(counter[13]),
    .O(_041_[0])
  );

//...

Code qui reste parfaitement simulable avec Icarus pour faire de la simulation post-synthèse comme expliqué dans la documentation officielle.

Maintenant que nous avons notre netlist passons aux choses sérieuses avec le placement routage :

$ wine ../../cc-toolchain-win/p_r-2022.04-001/p_r.exe -i blink_synth.v -o blink -lib ccag
GateMate (c) Place and Route
Version 4.0 (4 April 2022)
All Rights Reserved (c) Cologne Chip AG

...

Comme pour la synthèse, nous n’allons pas mettre tous les messages ici. Une des information qui nous intéresse en priorité pour le placement routage est la performance en vitesse.

...
Static Timing Analysis
Longest Path from Q of Component 25_1 to D-Input of Component 33/1 Delay: 18215 ps
Maximum Clock Frequency on CLK 230/3:   54.90 MHz
...

La vitesse d’horloge maximale est donc de 54.90Mhz. Cela peut sembler ridicule mais il faut prendre en compte que :

  • L’architecture du «clignoteur» avec un énorme compteur pour diviser l’horloge n’est absolument pas optimisée. Pour faire bien il faudrait pipeliner le compteur mais ça n’est pas le sujet ici. Ces mauvais résultats sont cohérent avec ce qu’on pourrait obtenir avec un autre FPGA «mainstream».
  • Ces performances sont «conservatrice» c’est le pire cas quand le FPGA est très chaud.

Bref, pour faire clignoter une LED, on peut raisonnablement doubler cette fréquence d’horloge si on veut 🙂 Mais comme nous n’utilisons pas de PLL ici, la fréquence d’entrée de 10Mhz rentre dans la specification.

Les statistiques d’utilisation du FPGA sont données à la fin de la synthèse :

CPE_USAGE_INPUT - CPE_COMBSEQ         1/8 :     0 /     21   (  0.0%)
CPE_USAGE_INPUT - CPE_COMBSEQ         2/8 :    11 /     21   ( 52.4%)
CPE_USAGE_INPUT - CPE_COMBSEQ         3/8 :     0 /     21   (  0.0%)
CPE_USAGE_INPUT - CPE_COMBSEQ         4/8 :     0 /     21   (  0.0%)
CPE_USAGE_INPUT - CPE_COMBSEQ         5/8 :     0 /     21   (  0.0%)
CPE_USAGE_INPUT - CPE_COMBSEQ         6/8 :    10 /     21   ( 47.6%)
CPE_USAGE_INPUT - CPE_COMBSEQ         7/8 :     0 /     21   (  0.0%)
CPE_USAGE_INPUT - CPE_COMBSEQ         8/8 :     0 /     21   (  0.0%)

CPE_USAGE_INPUT - CPE_COMB            1/8 :     3 /      3   ( 100.0%)
CPE_USAGE_INPUT - CPE_COMB            2/8 :     0 /      3   (  0.0%)
CPE_USAGE_INPUT - CPE_COMB            3/8 :     0 /      3   (  0.0%)
CPE_USAGE_INPUT - CPE_COMB            4/8 :     0 /      3   (  0.0%)
CPE_USAGE_INPUT - CPE_COMB            5/8 :     0 /      3   (  0.0%)
CPE_USAGE_INPUT - CPE_COMB            6/8 :     0 /      3   (  0.0%)
CPE_USAGE_INPUT - CPE_COMB            7/8 :     0 /      3   (  0.0%)
CPE_USAGE_INPUT - CPE_COMB            8/8 :     0 /      3   (  0.0%)

CPE_USAGE_INPUT - CPE COMBSEQ+COMB    1/8 :     3 /     24   ( 12.5%)
CPE_USAGE_INPUT - CPE COMBSEQ+COMB    2/8 :    11 /     24   ( 45.8%)
CPE_USAGE_INPUT - CPE COMBSEQ+COMB    3/8 :     0 /     24   (  0.0%)
CPE_USAGE_INPUT - CPE COMBSEQ+COMB    4/8 :     0 /     24   (  0.0%)
CPE_USAGE_INPUT - CPE COMBSEQ+COMB    5/8 :     0 /     24   (  0.0%)
CPE_USAGE_INPUT - CPE COMBSEQ+COMB    6/8 :    10 /     24   ( 41.7%)
CPE_USAGE_INPUT - CPE COMBSEQ+COMB    7/8 :     0 /     24   (  0.0%)
CPE_USAGE_INPUT - CPE COMBSEQ+COMB    8/8 :     0 /     24   (  0.0%)

IO_USAGE                         :      3 /   144    (  2.1%) of all IOs
IO_USAGE_TYPE - IBF              :      2 /   144    (  1.4%) of all IOs    ( 66.7%) of used IOs
IO_USAGE_TYPE - OBF              :      1 /   144    (  0.7%) of all IOs    ( 33.3%) of used IOs
IO_USAGE_TYPE - TOBF             :      0 /   144    (  0.0%) of all IOs    (  0.0%) of used IOs
IO_USAGE_TYPE - IOBF             :      0 /   144    (  0.0%) of all IOs    (  0.0%) of used IOs

CPE_USAGE_PHYS - CPE_COMB_ONLY   :     73 / 20480    (  0.4%) of all CPEs   ( 60.3%) of occupied CPEs
CPE_USAGE_PHYS - CPE_SEQ_ONLY    :      5 / 20480    (  0.0%) of all CPEs   (  4.1%) of occupied CPEs
CPE_USAGE_PHYS - CPE_BRIDGE_ONLY :      0 / 20480    (  0.0%) of all CPEs   (  0.0%) of occupied CPEs
CPE_USAGE_PHYS - CPE_CARRY_ONLY  :      0 / 20480    (  0.0%) of all CPEs   (  0.0%) of occupied CPEs
CPE_USAGE_PHYS - CPE_COMB+SEQ    :     10 / 20480    (  0.0%) of all CPEs   (  8.3%) of occupied CPEs
CPE_USAGE_PHYS - CPE_COMB+BRIDGE :      0 / 20480    (  0.0%) of all CPEs   (  0.0%) of occupied CPEs
CPE_USAGE_PHYS - CPE_COMBSEQ     :     21 / 20480    (  0.1%) of all CPEs   ( 17.4%) of occupied CPEs

CPE_USAGE_LOGIC - CPE_COMB       :      8 / 20480    (  0.0%) of all CPEs   (  6.6%) of occupied CPEs
CPE_USAGE_LOGIC - CPE_SEQ        :     15 / 20480    (  0.1%) of all CPEs   ( 12.4%) of occupied CPEs
CPE_USAGE_LOGIC - CPE_COMBSEQ    :     21 / 20480    (  0.1%) of all CPEs   ( 17.4%) of occupied CPEs
CPE_USAGE_LOGIC - CPE_BRIDGE     :      0 / 20480    (  0.0%) of all CPEs   (  0.0%) of occupied CPEs

CPE_USAGE_OVERALL                :    121 / 20480    (  0.6%) of all CPEs occupied
CPE_USAGE_LOGIC                  :     94 / 20480    (  0.5%) of all CPEs used for customer logic

Component Statistics:
         AND        32        19%
        ADDF         2         1%
       ADDF2        60        37%
        C_OR        48        29%
      Route1         4         2%
    CP_route        15         9%
              --------
Sum of COMB:       161

           D        25        92%
       C_0_1         2         7%
              --------
Sum of SEQ:         27

Sum of all:        188

Et le bitstream généré est au format *.cfg (ascii) ou *.cfg.bit (binaire).

$ ls -lha blink_00.*
-rw-rw-r-- 1 oem oem 121K May  1 08:38 blink_00.cdf
-rw-rw-r-- 1 oem oem 1.4M May  1 08:38 blink_00.cfg
-rw-rw-r-- 1 oem oem  48K May  1 08:38 blink_00.cfg.bit
-rw-rw-r-- 1 oem oem  465 May  1 08:38 blink_00.pin
-rw-rw-r-- 1 oem oem 6.0K May  1 08:38 blink_00.place
-rw-rw-r-- 1 oem oem  65K May  1 08:38 blink_00.SDF
-rw-rw-r-- 1 oem oem  42K May  1 08:38 blink_00.used
-rw-rw-r-- 1 oem oem  79K May  1 08:38 blink_00.V

Pour configurer le FPGA nous utiliserons openFPGALoader en «natif» :

$ openFPGALoader -b gatemate_evb_jtag blink_00.cfg.bit
Jtag frequency : requested 6.00MHz   -> real 6.00MHz  
Load SRAM via JTAG: [==================================================] 100.00%
Done
Wait for CFG_DONE DONE

Et la LED clignote :

Ressources