Tous les articles par Fabien Marteau

2018, l’année de la libération des processeurs ?

2018 aura été l’année du Risc-V. Ce jeux d’instructions libre existait bien sûr avant 2018 puisqu’il a été fondé en 2010, mais c’est véritablement en 2018 qu’il aura pris son envol.

Entendons nous bien, le Risc-V pour Reduced Instructions Set Computing version V n’est pas un microprocesseur. C’est une définition du jeux d’instructions ainsi que des registres internes du processeur. Bref cela doit être vu comme une standardisation open-source du langage d’un processeur. Libre aux fondeurs de développer leurs architectures de processeur compatible Risc-V. Il définit les instructions assembleur et leurs formats (encodage) mais il ne définit pas le nombre d’étages de pipelines, comment est géré la prédiction de branche ni le format de bus de données et d’instructions. Tout cela relève de l’implémentation.

Cette standardisation du jeux d’instructions intéresse beaucoup de créateurs de microprocesseurs. En effet, plus besoin d’adapter ou d’écrire les outils logiciels pour son processeur; comme c’est un standard il suffit d’utiliser les «toolchains» classique comme GCC OpenOCD ou LLVM qui bien sûr l’intègre désormais, mais également toutes une série d’outils non libres. Linux n’est pas en reste puisqu’il intègre complètement l’architecture dans ses versions récente. C’est également le cas des petits OS temps réel comme Zephyr .

C’est, entre autre, cette disponibilité des outils qui a poussé de nombreux labo à basculer leurs processeurs sur ce jeux d’instructions. On pense notamment à :

  • PULP (Parallel Ultra Low Power ): Une architecture multi-core pour l’embarqué développé par l’université de Zurich. Utilisé par les processeur GAP8.
  • Patmos: le processeur temps réel
  • Shakti: De l’université indienne de madras
  • …: certainement plein d’autre

Il existe une tripotée de processeur Risc-V «soft» que l’on peut synthétiser dans des FPGA. Mais, à ma connaissance, le premier composant silicium sortie des chaînes de fabrication de fondeurs est le E310 de la société SiFive. Ce composant est sorti en 2017 et il est possible d’acheter un kit de développement «compatible arduino» pour se faire la main dessus.
Le E310 est un microcontrôleur 32bits, qui a fait un peu parler de lui quand il est sorti mais qui reste un démonstrateur. La société SiFive souhaitant rester une entreprise «fabless».

Mais c’est véritablement en 2018 que les choses se sont accélérées avec le ralliement de grands noms de l’industrie électronique à la fondation Risc-V et la sortie de nombreux processeurs «en silicium» bien concret.

On pensera notamment à:

  • U540: Hifive Unleashed de la société SiFive (encore ;). Un quad core RV64G plus un core RV64I pour la supervision temps réel. SiFive à sortie un kit de développement permettant d’y faire tourner un Linux compatible desktop.
  • GAP8: de greenwave technologie, un processeur PULP de 8 cores pour l’IoT.
  • K210: de Kendryte, un microcontrôleur chinois dual core RV64I
  • RV32M1: de NXP (hé oui ! j’en suis le premier étonné) un microcontrôleur très spécial puisqu’il contient un core RV32I mais également deux cores ARM cortex-M0 et M4. Il ne manque plus que le MIPS pour avoir un beau pot-pourri des proc RISC du marché 😉

Toutes ces sorties ont commencées à faire très peur aux concurrents, et notamment à son concurrent principale : ARM. Qui a tenté une campagne de dénigrement de Risc-V avant de très vite se raviser et de lancer une timide «riposte» avec un partenariat Xilinx pour fournir gratuitement des cortex-Mx dans les FPGA de Xilinx.

Mais Risc-V a également fait bouger l’autre concurrent beaucoup moins connu : MIPS qui lui a … libéré son set d’instructions !

Risc-V reste pour l’instant dans le domaine de l’embarqué et du microcontrôleur, mais la fondation a clairement l’intention de couvrir les domaines des calculateurs et autres mainframes. Domaine où MIPS est déjà un peu plus installé.

Risc-V arrivera-t-il à gagner la bataille des supercalculateurs ? ARM adoptera-t-elle le set d’instructions Risc-V ? Intel sentira-t-il le roussi quand Risc-V viendra le titiller sur ses plate-bandes ? MIPS reviendra-t-il dans la course avec son ouverture en open-source ? Des questions auxquels nous pourrons peut-être répondre en 2019. Un combat qui promet d’être passionnant.

Mais une chose est sûr, en 2018 l’opensource a fait une grande avancée dans le domaine des processeurs grâce à ce set d’instruction de l’université de Berkeley !

Comme j’aimerai voir ça dans le domaine des FPGA 😉



Installing Libero on Debian 9

This is just an install success story of Libero on Debian 9 (stretch).  For the Risc-V contest, I recently acquired the Microsemi IGLOO2 development kit named FUTUREM2GL-EVB  distributed by Futur-Electronic.

The development software for the IGLOO2 is named Libero and according to Microsemi, should works on Linux. But officially support only RedHat, CentOS and SuSE … not Debian. Microsemi provide a Linux installation guide to install it. It’s useful but should be adapted for Debian.

Download and install Libero

The first thinks to do is to download the installing file for Linux (and not the SP1 file which is only an update).  Once downloaded we just have to launch it, if it’s not executable we can change rights with chmod command.

$ chmod 666 Libero_SoC_v11.9_Linux.bin
$ ./Libero_SoC_v11.9_Linux.bin

An install windows will raise and we can follow directives.

Licensing

Once installed, we need to install the license. For that, we need to know our mac address :

$ ip addr show dev eth0
[...]
link/ether 12:34:56:78:9a:bc [...]

The key that should be given to Microsemi is in upper case without ‘:’ :

$ ipython

In [1]: "12:34:56:78:9a:bc".replace(':','').upper()                                                                                                                                                             
Out[1]: '123456789ABC'

With this key we can then ask for a license file on microsemi website. The official Linux guide talk about license.dat file, but for me it was license.zip … Both are zip file in fact. We can then unflat it with unzip command:

$ unzip License.zip 
Archive:  License.zip
  inflating: License.dat

The unflated file is a text file that should be edited with you text edito as explained in guide (page 6).

License server

The license server deamon must be downoaded on official microsemi website. Choose «Linux deamon» in table. It’s an archive of several binaries that should be unflated :

$ cd
$ tar -zxvf Linux_Licensing_Daemon.tar.gz
Linux_Licensing_Daemon/
Linux_Licensing_Daemon/actlmgrd
Linux_Licensing_Daemon/lmgrd
Linux_Licensing_Daemon/lmhostid
Linux_Licensing_Daemon/lmutil
Linux_Licensing_Daemon/mgcld
Linux_Licensing_Daemon/snpslmd
Linux_Licensing_Daemon/syncad
Linux_Licensing_Daemon/synplctyd

Export shell variables

Before launching software, we have to export some paths in our .bashrc :

#Libero 
LIBERO_LICENSE_FOLDER=/home/giselle/flexlm
LD_LIBRARY_PATH=/usr/lib/i386-linux-gnu/:/usr/lib/x86_64-linux-gnu/
# For Floating License from a License Server
export LM_LICENSE_FILE=1702@gisellelaptop:$LM_LICENSE_FILE
export SNPSLMD_LICENSE_FILE=1702@gisellelaptop:$SNPSLMD_LICENSE_FILE
# <1702> is the port number
# martonilp is the license server host name
#For Node-Locked License
export LM_LICENSE_FILE=$LIBERO_LICENSE_FOLDER/license.dat:$LM_LICENSE_FILE
export SNPSLMD_LICENSE_FILE=$LIBERO_LICENSE_FOLDER/license.dat:$SNPSLMD_LICENSE_FILE
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib
export DISPLAY=:0
export PATH=/opt/microsemi/Libero_SoC_v11.9/Libero/bin:$PATH

On my computer, Microsemi softwares are installed in /opt/ directory.

Launching Libero

First launch license server :

$ cd
$./flexlm/lmgrd -c ~/flexlm/License.dat -log /tmp/lmgrd.log

Once license server launched we can run Libero :

$ libero
/opt/microsemi/Libero_SoC_v11.9/Libero/bin/libero_bin: /opt/microsemi/Libero_SoC_v11.9/Libero/lib/libz.so.1: no version information available (required by /usr/lib/i386-linux-gnu/libpng16.so.16)

I had a little problem with libz provided with libero package, then I removed it and linked libz of my distribution :

$ apt-file search libz.so
lib32z1: /usr/lib32/libz.so.1
lib32z1: /usr/lib32/libz.so.1.2.8
lib32z1-dev: /usr/lib32/libz.so
zlib1g: /lib/x86_64-linux-gnu/libz.so.1
zlib1g: /lib/x86_64-linux-gnu/libz.so.1.2.8
zlib1g-dev: /usr/lib/x86_64-linux-gnu/libz.so
...
$ cd /opt/microsemi/Libero_SoC_v11.9/Libero/lib
$ mv libz.so.1 oldlibz.so.1
$ ln -s /lib/x86_64-linux-gnu/libz.so.1 libz.so.1

And then managed to launch it :

$ libero

Hurrah \o/ that works

But it’s unfortunately not finished.

First, when I tryied to synthesize I had this message in error window :

/opt/microsemi/Libero_SoC_v11.9/Synplify/bin/synplify_pro: 137: [: unexpected operator
/opt/microsemi/Libero_SoC_v11.9/Synplify/bin/synplify_pro: 151: [: !=: argument expected
/opt/microsemi/Libero_SoC_v11.9/Synplify/bin/synplify_pro: 324: /opt/microsemi/Libero_SoC_v11.9/Synplify/bin/config/execute: Syntax error: "(" unexpected (expecting ";;")

The problem come from the shell Debian uses by default :

$ ls -lha /bin/sh
lrwxrwxrwx 1 root root 4 oct.  29 20:50 /bin/sh -> dash

This shell doesn’t work like bash and generate some error in synplify scripts. To solve it I simply changed the /bin/sh link to /bin/bash :

$ cd /bin/
$ sudo mv sh shold
$ sudo ln -s bash sh

And I managed to synthesize my design.

But it’s not finished ! Once my bitstream generated I would like to download it on the IGLOO2 on kit. For that, we have to install correctly drivers for FlashPro5.
Directives are given in the official Microsemi Linux install guide, but udev syntax is false on Debian :

BUS=="usb",SYSFS{idProduct}=="2008",SYSFS{idVendor}=="1514",MODE="0660",GROUP="",SYMLINK+="FlashPro5"
BUS=="usb",SYSFS{idProduct}=="6001",SYSFS{idVendor}=="0403",MODE="0660",GROUP="",SYMLINK+="FTDI232"

Right rules are following :

# FlashPro5
SUBSYSTEM=="usb", ATTR{idVendor}=="1514", ATTR{idProduct}=="2008", MODE="0666", GROUP="plugdev"
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6001", MODE="0666", GROUP="plugdev"

Should be written in /etc/udev/rules.d/70-microsemi.rules file.

Then fully works  and they lived happily and urged a lot of children

Sortie de Yosys Open Synthesis Suite 0.8

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.

Dans le process de développement FPGA/ASIC la synthèse est l’étape de conversion du modèle matériel simulé en « netlist RTL » d’où l’on peut dériver le circuit réel.

[La suite sur Linuxfr …  ]

Verilator 4.002

La version 4.002 de Verilator a été annoncée à la conférence ORConf2018 en Pologne.

Verilator est sans conteste le simulateur HDL open source le plus rapide du « marché ». Il permet de simuler des porte‐grammes écrits en Verilog synthétisable.

Le nouveau logo de Verilator

La suite sur la dépêche linuxfr

Computer Organization and Design RISC-V Edition

La référence en matière de livre sur l’architecture des processeurs. Tout y passe, l’arithmétique binaire, le langage assembleur, le datapath (le core d’un processeur), les pipelines et les différentes méthodes de prédiction de branches, les différentes architecture multicore, les GPU/VPU, la hiérarchie des mémoires, …

David A.Patterson est une superstar dans le milieu c’est lui qui est à l’origine de l’architecture de type «RISC». Et avec cette édition nous avons droit à une description fine du jeux d’instructions libre RISC-V très à la mode aujourd’hui. Tout en parlant principalement du RISC-V, le livre n’oublie pas les autres architectures célèbre comme x86, arm ou mips.

Le livre parait cher, mais vous en aurez pour votre argent tant le contenu est dense.

Et pourquoi pas portegramme ?

Quand on fait du code pour un FPGA/ASIC il est difficile de nommer la chose développée. On ne réalise pas un programme puisque ça n’est pas une suite d’instructions exécutées par un processeur. Au contraire même on peut réaliser un processeur avec le code que l’on est en train de développer.

Pour nommer cette chose on va souvent parler d’IP pour «Intellectual Property», ce qui est vraiment très moche comme nom en plus d’être un anglicisme. On entend aussi souvent parler de «core», mais c’est trop facilement associé à un cœur de processeur. En général je m’applique à parler d’architecture ou simplement de projet FPGA en français et de design en anglais pour parler de la chose.

Mais une «architecture» est vite associée à quelque chose de plus vaste, à une vue d’ensemble d’un projet et n’est pas nécessairement lié à du matériel.

On pourrait aussi parler de schéma puisque ce sont des portes logiques reliées entre elles. Mais comme on est en train de faire du code c’est étrange.

En anglais, j’ai pu lire sur le site de Sébastien Bourdeauducq qu’il parlait de gateware. Ce qui est assez parlant une fois que l’on a compris le sens. On parle de software pour du logiciel, de firmware pour du logiciel embarqué (profond) et de hardware pour le matériel. Pourquoi pas du gateware pour parler de fpga/asic ?

En effet, un projet/design/core fpga est une description de portes connectées ensemble ce qui colle bien au nom anglais gateware (gate=porte).

Si nous allons plus loin et que nous traduisons en français ce nouveau mot, nous pourrions parler de :

portegramme par analogie à programme.

Voila une idée à envoyer à l’académie française tiens !

Manage high impedance ‘Z’ state with Chisel

In previous (french) article, I described a technic to integrate a Chisel3 component named « TapTempo » in the APF27 board.  This board is made with an i.MX27 CPU and a Spartan3A FPGA.

To communicate with the FPGA, the i.MX27 is plugged on it with a memory bus named «WEIM». But the data signals used in WEIM are also connected on flash nand memory on the board, and this memory contain the Linux kernel and rootfs.

It’s not a problem if the FPGA « release » the data bus in high impedance when not used. Ant it’s the case when we use ctrl signal correctly (with oen signal -> output enable not)

In the first design, as tempo data are only output values read by the CPU, it was declared as « output » in chisel bundle :

class APF27TapTempo extends Module {
val io = IO(new Bundle {
val data = Output(UInt(16.W))
[...]

But with this data description, electrical value on physical data bus is continuously held by the FPGA. And when i.MX want to access nand flash memory it can’t. And we cannot start Linux as it require reading value in flash memory.

The solution is to set data bus as bidirectional signal and use WEIM signal oen to enable output on data bus, and when oen is not active the data bus is left on high impedance state ‘Z’.

In chisel, to manage bidirectional signal, we have to use the type « analog » as it :

class APF27TapTempo extends Module {
  val io = IO(new Bundle {
    val oen = Input(Bool())
    val data = Analog(16.W)
  [...]

And simply deactivate data when oen is ‘1’ ?

when(oen === '1'){
   data := "bZZZZZZZZZZZZZZZZ"
}.otherwize {
   data := taptempovalue
}

Would be so easy … But no, we can’t do that with Chisel3 🙁

In FPGA or ASIC, the high state value doesn’t exist in fact. All signals under FPGA must be input or output and set to ‘0’ or ‘1’. No other values are actually supported.

Other « high impedance » values like ‘Z’, ‘H’ or ‘L’ can’t be synthesized under the fpga. But these values (mostly ‘Z’ state in fact) can be synthesized on the boundary. If a bidirectional signal going out of FPGA, the xilinx synthesizer can instantiate an IOBUF and manage the high state.

Chisel doesn’t manage this high state. It’s a deliberate choice from chisel developers team to simplify Chisel3. But for some design, like on APF27 we need to implement it.

Verilog manage this kind of signal state, then we can write a verilog code to write ‘Z’ state and include it in our chisel design.

To do this, we use a module chisel type named BlackBox. And as we want to add directly verilog source in the chisel code we will add the Trait HasBlackBoxInline like described bellow :

// import verilog code with HasBlackBoxInline
import chisel3.util.{HasBlackBoxInline, HasBlackBoxResource}
...
// Describe blackbox with verilog code
class Apf27Bus extends BlackBox with HasBlackBoxInline {
  val io = IO(new Bundle {
    val dataout = Output(UInt(16.W))
    val dataio = Analog(16.W)
    val datain = Input(UInt(16.W))
    val oe = Input(Bool())
  })

  setInline("Apf27Bus.v",
    s"""
    |module Apf27Bus(
    |     output [15:0] dataout,
    |     inout [15:0] dataio,
    |     input [15:0] datain,
    |     input oen);
    |
    |   assign dataio = (oen == 'b0) ? datain : 'bzzzzzzzzzzzzzzzz;
    |   assign dataout = dataio;
    |endmodule
    """.stripMargin)
}
// Verilog will be written in separate file named Apf27Bus.v

...
// Then connect it in "Top" module
  val iobuf = Module(new Apf27Bus)
  io.data <> iobuf.io.dataio
  iobuf.io.datain := dataout
  iobuf.io.oen <> io.oen

As dataio is Analog type, we have to declare also analog on top bundle module :

class APF27TapTempo extends Module {
  val io = IO(new Bundle {
    val data = Analog(16.W)
    val oen = Input(Bool())
    val button = Input(Bool())
  })

With this method, we keep all our sources codes in the chisel sources and our high ‘Z’ bidirectional port is correctly synthesized with classical commercials software.

All sources of this project described in this article are available on my github project TapTempoChisel.

Intégration de TapTempo-Chisel sur APF27

Dans un premier article je décrivais le «core» de TapTempo en Chisel. Mais si nous souhaitons tester en réel il faut choisir une plate-forme sur laquelle le synthétiser. Ce choix implique nécessairement d’ajouter du code pour «packager» notre composant.

La carte APF27 et son kit de développement conçus par Armadeus Systems sont parfaitement indiqués. En effet la carte possède un FPGA de taille plutôt raisonnable de chez Xilinx : le spartan3A. Ce FPGA est couplé à un microprocesseur i.MX27 permettant de communiquer directement via un OS «évolué» (ici U-Boot). Et … comble du perfectionnement, le kit de développement est muni d’un bouton poussoir, qui nous servira de «touche tempo» !

L’idée est donc d’utiliser le bouton du kit pour la tempo et de venir lire le résultat mesuré par TapTempoChisel au moyen d’une lecture sur le bus de communication du processeur qui est connecté au FPGA.

Architecture du «packaging» de TapTempo
Architecture du «packaging» de TapTempo

On trouvera le code du packaging sur le github du projet. L’interface du Top est donc relativement simple, et se résume à deux signaux :

  • Le signal d’entrée (bouton)
  • Le signal de sortie (data)

Coté processeur,  il suffira de faire une lecture sur le bus pour pouvoir avoir la valeur en temps réel:

BIOS> md.w C8000000

Nous verrons plus tard que le design présenté ici est beaucoup trop simpliste et bloque le bus de l’apf27 ce qui entraîne une impossibilité de lancer Linux sur la carte.

Les différents éléments de notre architecture

Tout d’abord, pour éviter au maximum la métastabilité, il est nécessaire de synchroniser le signal d’entrée avec l’horloge du système. Pour cela nous devons faire passer le signal bouton par deux bascules D.

synchronization d'un signal externe par deux bascules
synchronisation d’un signal externe par deux bascules

Pour réaliser cela, dans un premier temps nous aurions tendance à déclarer deux signaux :

  • Un signal temporaire tmp
  • le signal synchronisé button_s

En chisel cela donnerait un truc dans le genre:

val tmp = RegNext(io.button)
val button_s = RegNext(tmp)

On déclare le registre en même temps que l’on connecte sa valeur d’entrée.

Pourtant à y regarder de plus près, ce montage de la double bascules n’est qu’un registre à décalage de 2 ! Et il existe une fonction pour ça dans la librairie «util» de chisel : ShiftRegister(sig, n)

Du coup nous pouvons réduire notre synchronisation en une simple ligne :

val button_s = ShiftRegister(io.button, 2)

Notre signal est maintenant synchronisé, mais nous n’avons pas filtré les rebonds. Or avec le genre de boutons que nous trouvons sur ces kits de développement c’est indispensable. Le FPGA étant cadencé à une fréquence élevé de 100Mhz nous allons «voir» tous les rebonds, et fausser par la même occasion notre mesure du tempo.

La plupart des «montages FPGA» permettant de faire de l’anti-rebond se basent sur des compteurs. Le tout étant de bien les dimensionner.

  val clk_freq_khz = 100000
  val debounce_per_ms = 20
  val MAX_COUNT = (clk_freq_khz * debounce_per_ms) + 1
  val debcounter = RegInit(MAX_COUNT.U)

La remise à zéro du compteur sera déclenchée par un front (montant ou descendant) du signal d’entrée. Nous déclarerons pour cela deux fonctions très commodes:

def risingedge(x: Bool) = x && !RegNext(x)
def fallingedge(x: Bool) = !x && RegNext(x)

Permettant de détecter respectivement le front montant et le front descendant du signal d’entrée.

Tant que le compteur debcounter n’a pas atteint sa valeur maximal, on ne fait que compter. Si le compteur est à sa valeur max et que l’on a un front sur le signal d’entrée, alors on remet le compteur à zero et on recopie la valeur du signal d’entrée.

  when(debcounter =/= MAX_COUNT.U) {
    debcounter := debcounter + 1.U
  }.otherwise {
    when(risingedge(button_s) || fallingedge(button_s)){
      debcounter := 0.U
      button_deb := button_s
    }
}

De cette manière on répercute rapidement un changement du signal d’entrée sans s’encombrer des multiples changement de valeurs rapide inhérentes aux rebonds.

Synthèse

Chisel est «vendu» à la base comme un langage HDL synthétisable, du coup nous allons le synthétiser, et avec un logiciel du marché s’il vous plaît : ISE.

Avant la synthèse nous avons besoin du code verilog généré. Pour le générer nous appellerons le ‘Driver’ déclaré dans le top:

object APF27TapTempoDriver extends App {
  chisel3.Driver.execute(args, () => new APF27TapTempo)
}

Au moyen de la commande sbt :

sbt 'runMain taptempo.APF27TapTempoDriver'

Le code verilog ainsi généré se retrouve dans le répertoire courant avec le nom APF27TapTempo.v

Notre projet comportant deux modules verilog (APF27TapTempo et TapTempo) leurs déclaration dans le fichier source se fait en partant de la fin -> le «top» est à la fin du fichier et le «core» au début:

...
module APF27TapTempo( // @[:@2517.2]
  input         clock, // @[:@2518.4]
  input         reset, // @[:@2519.4]
  output [15:0] io_data, // @[:@2520.4]
  input         io_button // @[:@2520.4]
);
...

Il ne nous reste plus qu’à intégrer ce source à un projet ISE en y ajoutant la description des signaux d’entrées sorties et leurs placement sur les pins du FPGA. Ce qui peut-être fait en intégrant le fichier de description APF27TapTempoChisel.ucf

# clock
NET "clock" LOC="N9" | IOSTANDARD=LVCMOS18;# CLK0
NET "clock" TNM_NET = "clock";
TIMESPEC "TS_clock" = PERIOD "clock" 10.4167 ns HIGH 50 %;
# data bus
NET "io_data<0>"  LOC="T5" | DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA0
NET "io_data<1>"  LOC="T6" | DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA1
NET "io_data<2>"  LOC="P7" | DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA2
NET "io_data<3>"  LOC="N8" | DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA3
NET "io_data<4>"  LOC="P12"| DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA4
NET "io_data<5>"  LOC="T13"| DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA5
NET "io_data<6>"  LOC="R13"| DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA6
NET "io_data<7>"  LOC="T14"| DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA7
NET "io_data<8>"  LOC="P5" | DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA8
NET "io_data<9>"  LOC="N6" | DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA9
NET "io_data<10>" LOC="T3" | DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA10
NET "io_data<11>" LOC="T11"| DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA11
NET "io_data<12>" LOC="T4" | DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA12
NET "io_data<13>" LOC="R5" | DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA13
NET "io_data<14>" LOC="M10"| DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA14
NET "io_data<15>" LOC="T10"| DRIVE=8 | IOSTANDARD=LVCMOS18; # DATA15
# Button
NET "io_button" LOC="C15" | DRIVE=12 | IOSTANDARD=LVCMOS33; # IO_L24N_1

Et nous pouvons lancer la synthèse/placement&routage/bitstream d’ISE. Une fois le bitstream généré il faut le transférer dans la mémoire de l’apf27 avec U-Boot :

BIOS> tftpboot ${loadaddr} APF27TapTempo.bit

Puis configurer le FPGA.

BIOS> fpga load 0 ${loadaddr}

Nous pouvons enfin lire la valeur du tempo avec la commande de lecture dans l’espace mémoire du bus fpga (WEIM) :

BIOS> md.w C8000000
c8000000: 010e 010e 010e 010e 010e 010e 010e 010e ................
c8000010: 010e 010e 010e 010e 010e 010e 010e 010e ................
c8000020: 010e 010e 010e 010e 010e 010e 010e 010e ................

La valeur est lue en hexadécimal. Et comme l’adresse n’est pas gérée, tant que ça reste dans la zone du bus FPGA, la même valeur se répète.

Ici nous avons donc un tempo de 0x10e soit 270bpm. Pour le calibrer, j’ai pris le chronomètre et tenté d’appuyer sur le bouton toutes les secondes, ce qui doit logiquement donner 60bpm -> 0x3c.

Nous n’en somme pas trop loin :
Test de la calibration de TapTempoChisel sur APF27

Il est désormais possible de l’utiliser dans le cas concret de la mesure du tempo du très mauvais «nuit de folie» du groupe «début de soirée» .

Mesure du tempo du très mauvais «nuit de folie» :

On obtient une valeur de 0x7B soit 123 coups par minute (bpm).

Ps: si vous voulez laver votre cerveau de cette horrible chanson pourquoi pas une petite guérilla ? À moins que vous soyez adepte du crou. Ne me remerciez pas, moi aussi j’ai beaucoup souffert à mesurer le tempo de cette horreur 😉