Tous les articles par Fabien Marteau

Chisel Tips

This page lists some tips for Chisel that I could glean here and there.

Bidirectional signal

Bidirectionnal signals are not possible inside an FPGA or an ASIC. But it can be usefull on the boundary to drive signal like tristate buffer.

To use Bidirectionnal signal use Analog() in conjonction with RawModule or BlackBox :

class TopDesign extends RawModule {
  val tristatebuf = Analog(1.W)
...
}

Connexion is made with bulk connector ‘<>’ :

tristatebuf <> myblackbox.io.tristate

dontTouch : keep register names in verilog

Tip from stackoverflow.

Sometimes, we have to keep register in verilog emitted code. But Chisel obtimize it and it often disapear. To keep it, use dontTouch() :

  val version = dontTouch(RegInit(1.U(8.W)))

Get following in verilog module:

  reg [7:0] version; // @[wbgpio.scala 20:34]
...
    if (reset) begin
      version <= 8'h1;
    end

DontCare output signals

All module output must be defined to avoid this kind of warning :

[error] (run-main-0) firrtl.passes.CheckInitialization$RefNotInitializedException:  : [module ChisNesPad]  Reference io is not fully initialized.
[error]    : io.data.valid <= VOID
[error] firrtl.passes.CheckInitialization$RefNotInitializedException:  : [module ChisNesPad]  Reference io is not fully initialized.
[error]    : io.data.valid <= VOID
[error] Nonzero exit code: 1
[error] (Compile / runMain) Nonzero exit code: 1
[error] Total time: 12 s, completed 10 déc. 2019 13:25:11

But at the begining of a design, we don’t know what to write. To avoid this error we can use DontCare object :

  io.data.valid := DontCare

Keep signal and variables names in Verilog

See the good response from Jack Koening on stackoverflow.

UInt() to Vec()

An UInt() can be converted to a Vec of Bool() with asBools:

val foo = Vec(5, Bool())
val bar = UInt(5.W)

foo := bar.asBools
Initialize Vec() of Reg()

Split an UInt() in a Vec() of «sub» UInt()

Question asked on stackoverflow.

If we have a 16 bits register declared like that.

val counterReg = RegInit(0.U(16.W))

And we want to do indexed dibit assignment on module output like that :

//..
  val io = IO(new Bundle {
     val dibit = Output(UInt(2.W))
  })
//..
var indexReg = RegInit(0.U(4.W))
//..
io.dibit = vectorizedCounter(indexReg) //xxx doesn't work

We could do it like that:

io.dibit := (counterReg >> indexReg)(1, 0)

Initialize Vec() of Reg()

 val initRegOfVec = RegInit(VecInit(Seq.fill(4)(0.U(32.W))))

Concatenate value in one UInt()

Of course we can use Cat(), but it take only 2 parameters. With ‘##’ we can chain more signals:

val a = Reg(UInt(1.W))
val b = Reg(UInt(1.W))
val c = Reg(UInt(1.W))
val y = Reg(UInt(3.W))

y := a ## b ## c

With a Vec() declared like it :

val outputReg = RegInit(0.U((dibitCount*2).W)
val valueVecReg = RegInit(VecInit(Seq.fill(dibitCount)(0.U(2.W))))

ouptutReg := valueVecReg.reduce(_ ## _)

Initialize Bundle

Question asked on stackoverflow. Same question on stackoverflow but with ‘1’ initialization.

If we have a Bundle declared like that :

class RValue (val cSize: Int = 16) extends Bundle {
  val rvalue = Output(UInt(cSize.W))
  val er     = Output(UInt((cSize/2).W))
  val part   = Output(Bool()) /* set if value is partial */
}

And we want to make a register with initialized value we can use the new interface named BundleLiterals:

import chisel3.experimental.BundleLiterals._
...
val valueReg = RegInit((new RValue(cSize)).Lit(
          _.rvalue -> 1.U,
          _.er -> 2.U,
          _.part -> true.B)

Or if we just want to initialize to all 0 values we can do that :

val valueReg = RegInit(0.U.asTypeOf(new RValue(cSize))

Test some chisel code in live

Question asked on stackoverflow.

It can be usefull to be able to test code in console before launching the big compilation. It’s possible in directory where your project build.sbt is :

$ cd myproject/
$ sbt
sbt:myproject> console
scala>

And once in the scala console chisel import can be done :

scala> import chisel3._
import chisel3._
scala> val plop = "b0010101010001".U(13.W)
plop: chisel3.UInt = UInt<13>(1361)

Type Ctrl+D to quit.

For more simplicity it’s also possible to use the Scaties website in live.

For more Chisel Cookbook

See :

Réception du kit AnalogMax-01

Arrow propose un kit de développement nommé AnalogMax pour 80$ environ. L’entreprise qui fabrique la carte est Trenz Electronic qui réalise également le kit gowin.

Cette fois la carte est arrivée par lettre, et non par gros colis.

Le FPGA est relativement gros et la carte possède un certain nombre de périphérique analogiques sympathique comme un détecteur de fumée, un capteur de température, quelque canaux ADC et DAC ainsi que des GPIO.

Au branchement du kit sur l’usb on a juste la led verte allumée. L’appuie sur le bouton à droite allume une des huit leds de la rangée, et l’appui sur l’autre bouton allume l’autre led rouge et inscrit un message sur l’uart (115200):

UHSA R1.0

[TO BE EDITED]

Liste de projets basés sur Chisel

Voici une liste de projets open-sources basés sur le langage de description matériel Chisel.

Processeurs

  • sodor: Un microprocesseur RISC-V pour l’éducation
  • rocket-chip: le générateur de processeurs RISC-V utilisé par SiFive
  • BOOM: The Berkeley Out-of-Order RISC-V Processor
  • leros: Un microcontrôleur microscopique optimisé pour les FPGA

Interfaces

  • spi2wb: Un maître Wishbone piloté par SPI
  • mdio: un maître MDIO (pour les Phy ethernet)
  • FastVDMA: une DMA rapide

Accélérateurs

  • Edge TPU : Il semblerait que cet accélérateur matériel développé par Google ait été conçu avec chisel3 d’après cette conférence.

Register size in bits

How to calculate register size in bits N

Chisel3 : log2Ceil()

import chisel3.util.log2Ceil

val Nsize = log2Ceil(N)

Verilog : $clog2()

 parameter NSIZE = $clog2(N);

VHDL : ceil(log2()

use IEEE.math_real."ceil";
use IEEE.math_real."log2";

Nsize := integer(ceil(log2(real(N))));

Python: math.ceil(math.log(N+1, 2))

import math
Nsize = math.ceil(math.log(N, 2))

CλaSH: ?

SystemC/C++: ceil(log2())

#include <math.h>       /* ceil and log */
Nsize = ceil(log2(N));

Le point Gowin

Oui je sais c’est nul 😉

Arrivée dans un énorme carton, la carte électronique se trouve dans le tout petit «tube» blanc.

Je viens donc de recevoir ma carte petite abeille (littlebee) munie d’un FPGA du chinois GOWIN.

La carte «LittleBee» munie d’un FPGA de chez Gowin

La carte produite et vendue par la société allemande Trenz Electronic permet de se faire la main avec le composant pour moins de 40€ (un peu plus avec les frais de ports UPS …).

Branchement

Au branchement à la sortie du carton les huit leds rouge s’allument ainsi qu’une led verte que je suppose de «power».

Les messages noyau nous donnent deux ports séries ttyUSBx :

$ dmesg
[630417.919258] usb 3-1: new high-speed USB device number 35 using xhci_hcd
[630418.059577] usb 3-1: New USB device found, idVendor=0403, idProduct=6010
[630418.059581] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[630418.059583] usb 3-1: Product: Dual RS232-HS
[630418.059584] usb 3-1: Manufacturer: FTDI
[630418.060116] ftdi_sio 3-1:1.0: FTDI USB Serial Device converter detected
[630418.060155] usb 3-1: Detected FT2232H
[630418.060352] usb 3-1: FTDI USB Serial Device converter now attached to ttyUSB0
[630418.060499] ftdi_sio 3-1:1.1: FTDI USB Serial Device converter detected
[630418.060528] usb 3-1: Detected FT2232H
[630418.060648] usb 3-1: FTDI USB Serial Device converter now attached to ttyUSB1

Si on se connecte au port série ttyUSB1 on obtient un affichage de la résolution du problème des philosophes.

Philosopher 0 [P: 3] THINKING [ 750 ms ]
Philosopher 1 [P: 2] HOLDING ONE FORK
Philosopher 2 [P: 1] EATING [ 450 ms ]
Philosopher 3 [P: 0] STARVING nabled
Philosopher 4 [C:-1] HOLDING ONE FORK get back,
Philosopher 5 [C:-2] EATING [ 375 ms ]

Il est probable que nous ayons ici un RISC-V dans le tiroir.

La connexion d’un terminal sur le port ttyUSB0 ne donne rien par contre.

IDE

Voila pour le déballage, maintenant il va falloir installer les outils pour faire clignoter ces leds !

[To Be Edited …]

Digital Design with Chisel

«Digital Design with Chisel» n’est pas un manuel d’utilisation des ciseaux à bois.

Le livre de Martin Schoerberl «Digital Design with Chisel» est à ma connaissance le premier livre papier concernant le langage de description matériel Chisel.

Le livre — en anglais mais on s’en doute — est une excellente introduction au langage de description matériel Chisel. Avec lui il est même possible de commencer la conception numérique (digital design) en Chisel sans avoir à mettre les mains dans le VHDL ou le Verilog.

Ce manuel se veut un guide pratique de démarrage, on commence avec la description de l’installation des outils pour faire tourner Chisel tout en faisant une (très) rapide introduction à Scala. Scala est le langage utilisé pour Chisel.

Après avoir décrit les composants de bases du langage, l’auteur s’attaque à la description d’un projet Chisel avec l’architecture des sources, testbench et autres makefile et built.sbt . On attaque ensuite les différentes structures un peu plus avancées de la construction numérique comme les machines d’états, les FIFO, ports séries pour aller jusqu’à la conception d’un processeur simple.

Le livre se termine par un chapitre expliquant comment contribuer au projet initié à Berkeley.

C’est un excellent manuel pour mettre le pied à l’étrier de la conception numérique avec un langage moderne (SSHDL). Bien sûr ça n’est pas en 130 pages que l’on fera le tour du langage, ça n’est pas non plus un manuel de référence exhaustif. Pour le manuel de référence on se référera au site officiel, et pour se souvenir des mots clefs on ira télécharger la «cheat sheet».

Le livre est disponible en impression amazon pour ~10$. Comme c’est un livre «libre» il est également disponible avec ses sources sur le github de l’auteur.

Lancement de l’OpenHW group

L’OpenHW group a été lancé en juin dans la foulée du workshop RISC-V qui se tenait à Zurich.

L’OpenHW group est une organisation à but non lucratif ayant pour objectif de promouvoir le développement de composants électroniques libres (ASIC, FPGA, …).

C’est dans cette optique de l’OpenHW développe une série de microprocesseurs RISC-V nommés sobrement Core-V.

On en saura certainement plus sur cette organisation cet automne à l’occasion du forum OSDForum qui se tiendra à Ottawa.

  • Présentation de l’OpenHW à Zurich (slide/vidéo)
  • Présentation de l’OpenHW sur HPCWire.

FireAnt: Un petit nouveau dans le monde du FPGA à bas coût

FireAnt est un kit de développement «de la taille d’un pouce» concu par la société Xips Technology et permettant de se faire la main sur le FPGA Trion T8 de la société Efinix.

Le kit est en crowdsourcing sur la plate-forme crowdsupply pour $30.

Vue du kit FireAnt muni d’un Trion T8 de chez Efinix

Pour ce prix on a le droit à :

  • Un Trion T8F81C2 (dispo chez digikey) muni de
    • 7384 Éléments logiques (LE)
    • 123kb de RAM
    • 8 multi-plieurs 18×18 bits
  • Un FTDI pour piloter le kit en USB
  • Une mémoire flash SPI à 104Mhz de 8Mo
  • Et bien sûr un LDO pour l’alimentation 3v3 à partir de l’USB

Efinix est une toute nouvelle société qui propose des petits FPGA gravés en 40nm. Pour les tout petits FPGA de leur gamme, la société propose ce qu’elle appelle un MPM pour «Mask Programmable Memory» -> la possibilité de figer le design en usine et de ne plus avoir à configurer le FPGA à chaque démarrage.

Un IDE permettant de faire la synthèse, le placement-routage et le bitstream est fourni «gratuitement». À condition de posséder un kit de développement (J’ai beau négocier, ils ne veulent pas me le donner tant que je n’aurais pas reçu le kit 😉 ).

Bref, il n’est pas encore question d’outils libres pour ces FPGA pour l’instant. Cependant, ça fait du bien de voir de nouveaux acteurs dans le domaine des FPGA «physique».

Un hack pour intégrer Wavedrom dans LibreOffice

Wavedrom est un outils magique pour générer de très beaux chronogrammes à partir d’une base texte (JSON). Il existe un outils en ligne de commande pour générer des rendu en SVG ou PNG. Cependant, Wavedrom reste très lié au web, pas facile de l’intégrer dans un document wysiwyg comme libreoffice.

On peut bien sûr générer l’image puis l’intégrer à son document, mais cela éparpille très vite le nombre de fichiers source à gérer. Or, un des intérêt d’un document libreoffice est d’inclure toute les sources permettant de générer et modifier le document.

L’idéal serait d’avoir un plugin Libreoffice pour wavedrom, mais pour l’instant cela n’existe pas.

Krispy propose une solution/hack sur la mailing list de wavedrom.

Cette solution nécessite d’avoir un accès web et de faire son chronograme avec l’éditeur en ligne de wavedrom. Cet éditeur permet de «stocker» la description du chronograme dans l’URL. Il suffit pour cela de cliquer sur le menu sandwich en bas à droite et de sélectionner «expand url» pour avoir le contenu du chronogramme dans l’url comme ceci.

Il n’est pas utile de comprendre ce qui est écrit dans l’url, il suffit de cliquer dessus pour avoir le texte «lisible».

Pour l’intégrer à son document libreoffice il suffit de:

  • générer l’image dans le format de son choix avec l’éditeur en ligne
  • de l’intégrer à son document libreoffice
  • Puis de faire un lien web sur l’image avec l’url complète contenant le source du chronograme.

De cette manière, le source du chronogramme est bien embarqué dans le document. Il faudra certe refaire une manip légèrement fastidieuse à chaque modification, mais nous avons tout de même une solution viable.


C’est évident quand on y pense, mais très piégeux :

        if(state == OPU_RSC || (state == OPU_WSTR))
            if(timetick_pulse) begin
                pwr_counter <= pwr_counter + 1;
            end
        else
            pwr_counter <= 0;

On pense que le else se rapporte au premier if … et bien non !

Il faut écrire :

        if(state == OPU_RSC || (state == OPU_WSTR)) begin
            if(timetick_pulse) begin
                pwr_counter <= pwr_counter + 1;
            end
        end else
            pwr_counter <= 0;

Voila voila, si on peut vous éviter des heures de déverminage inutiles c’est cadeaux 😉