# FPGA ULX3S (EPC5-85F)

Un FPGA est un océan de portes reprogrammable. Plus puissant qu'un microcontrôlleur,
on peut installer dessus un CPU ou du hardware spécialisé.

Pour un example d'utilisation voir:
- https://ulx3s.github.io/
- https://github.com/ulx3s/blink/tree/main
- https://blog.dave.tf/post/getting-started-fpga/

Le board d'HackENS est un terrain de jeu avec plein d'IO :
- de la SDRAM
- une carte SD
- un ESP32
- des boutons
- des leds
- un port jack
- un port hdmi
- ...

## Génération des fichiers verilog à partir de Bluespec

```make
PACKAGES = ./src/:+
bsc \
	-verilog \
	-vdir $(RTL) -bdir $(BUILD) -info-dir $(BUILD) \
	-no-warn-action-shadowing  -check-assert \
	-keep-fires -aggressive-conditions -show-schedule \
	-cpp +RTS -K128M -RTS  -show-range-conflict \
	-p $(PACKAGES) -g mkTop -u $(TOP)
```

- ``` PACKAGES``` liste des dossiers dont les fichiers .bs et .bsv sont importés, le + représente la lib standard
- ``` Top``` est le fichier principale
- ``` mkTop``` est le module principale
- ``` keep-fires``` utilise le sceduling intuitif: active chaque règne dés que possible (moins les conflits)
- ``` aggressive-conditions``` je pense que c'est: si $e_1$ est gardé par la condition $c_1$ et $e_2$ est gardé par la condition $c_2$ alors $(c ? e_1 : e_2)$ a pour condition de garde $(c ? c_1 : c_2)$ plutot que $c_1 \lor c_2$, les conditions sont plus difficile à calculer mais c'est plus intuitif et ne demande pas de faire deux règles pour scheduler $e_1$ et $e_2$

## Génération des LUT (look-up-table) avec yosys

```make
yosys -DULX3S -q -p "synth_ecp5 -abc9 -top mkTop -json mkTop.json" $(LIB)

```
- ``` LIB``` est la liste des fichiers verilog
- ``` mkTop``` est le module verilog principale
- ``` mkTop.json``` est la sortie de yosys
- ``` -abc9``` est l'algorithme de génération des LUT par défault, parfois il crash (je pense à cause des inout qui ne sont pas entièrement supporter), dans ce cas utiliser ``` -noabc9``` semble marcher

## Rooting avec nextpnr

```make
nextpnr-ecp5 --85k --json mkTop.json \
	--lpf ulx3s.lpf \
	--textcfg mkTop.config
```

- ``` ulx3s.lpf``` fichier qui map les variables verilog sur les pins
- ``` --85k``` nombre de LUT du FPGA
- on peut ajouter ``` -gui``` pour avoir une interface graphique et voir le placement sur le FPGA

## Génération du bitstream avec ecppack

```make
ecppack mkTop.config mkTop.bit
```


## Flash du fpga avec fujprog

```make
fujprog mkTop.bit
```

Il faut que le tty du fpga soit accessible par l'utilisateur courant!

## Nix
On peut tout installer avec ce nix-shell:
```
{ pkgs ? import <nixpkgs> {} }:

pkgs.mkShell {
  buildInputs = [
    pkgs.bluespec
    pkgs.verilator
    pkgs.verilog
    pkgs.gtkwave
    pkgs.openfpgaloader

    pkgs.yosys
    pkgs.nextpnrWithGui
    pkgs.trellis
  ];

  shellHook = ''
    export BLUESPECDIR=${pkgs.bluespec}/lib
    '';
}
```
