Tous les articles par Fabien Marteau

Prise en main de la GateMateA1-EVB

En 2023, OLIMEX sortait une carte de développement à base de FPGA GateMate (CologneChip):

La GateMateA1-EVB est une carte bien moins cher que le kit de développement officiel et propose tout un tas d’interfaces intéressantes.

Vue de la carte GateMateA1-EVB

Elle était dans mes cartons depuis un certain temps et je n’avais pas encore pris le temps de la tester.

Le site officiel donne la liste de caractéristiques complètes:

  • CCGM1A1 FPGA with 20480 logic cells
  • PSRAM 64Mbit
  • RP2040 processor for programing and debugging
  • 2MB configuration Flash for RP2040
  • 4 buttons
  • USB-C for power supply and programming
  • PS2 connector
  • VGA connector
  • 4 Banks with signals with selectable levels 1.2V 1.8V 2.5V
  • PMOD with level shifters
  • UEXT with level shifters
  • Power LED
  • User LED
  • 4 sections configuration slide switch
  • Dimensions: 120 x 80 mm

Et le pilotage (communication, programmation alimentation debug) se fait via un connecteur USB-C connecté sur un microcontrôleur RP2040.

La plupart des signaux qui sortent sur les connecteurs sont branchés directement sur les bank du FPGA. Ils sont donc à la tension du bank : 1v2, 1v8 ou 2v5. Se sont des tensions assez faible dans les montages. Si l’on veut du 3v3 il faudra se rabattre sur les connecteurs Uext1 et Pmod1 qui possèdent des transformateurs de niveaux de tension bidirectionnels.

Les fichiers de développement de la carte (Kicad) ainsi que le code source d’exemple sont fournis sur un dépot git.

Bref, une belle carte libérée en perspective.

Mise en route

Sous Linux, au branchement de l’usb le message noyau suivant s’affiche:

[fabien:~/projets] $ sudo dmesg -ce
[janv.17 20:57] usb 1-1.3.3: new full-speed USB device number 38 using ehci-pci
[  +0,111290] usb 1-1.3.3: New USB device found, idVendor=1209, idProduct=c0ca, bcdDevice= 1.10
[  +0,000005] usb 1-1.3.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  +0,000002] usb 1-1.3.3: Product: DirtyJTAG
[  +0,000001] usb 1-1.3.3: Manufacturer: Jean THOMAS
[  +0,000001] usb 1-1.3.3: SerialNumber: 2600942311111956
[  +0,018771] cdc_acm 1-1.3.3:1.1: ttyACM0: USB ACM device
[  +0,000018] usbcore: registered new interface driver cdc_acm
[  +0,000002] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters

Nous voyons que le RP2040 nous expose un firmware DirtyJTAG ainsi qu’une UART ttyACM0.

Exemple : un analyseur logique

L’exemple qui est donné dans le manuel de référence de la carte est un analyseur logique open source développé par CologneChip : Gatemate ILA (Integrated Logic Analyser).

On va commencer par installer gatemate ILA :

cd /opt/gatemate/
git clone https://github.com/colognechip/gatemate_ila.git
cd gatemate_ila/app
python3 -m pip install -r requirements.txt 

Il faut bien sur installer également la chaîne de développement de cologne chip. Et modifier le fichier app/config.py pour y inscrir les paths complet des utilitaires suivants:

  • yosys
  • p_r
  • openFPGALoader
  • gtkwave

S’ils ne se trouvent pas dans le path général du projet. Pour ma part il n’y a que p_r qui est spécifique au gatemate et que je n’ai pas installé globalement. J’ai donc téléchargé le kit de dev sur le site de colognechip (10.01.2025) et modifié la ligne suivante dans app/config.py

PR = '/opt/gatemate/cc-toolchain-linux/bin/p_r/p_r'

Les modes de programmation du gatemate avec openFPGALoader sont donnés dans la doc.

Dans le même fichier, on modifie également les flags pour utiliser la sonde DirtyJTAG flashée dans le RP2040 :

UPLOAD_FLAGS = ' -b olimex_gatemateevb '        
CON_DEVICE = 'oli' # O.L.I. France inter, je suis pas petit ...

Dans un premier temps on va rester sur le bug du firmware qui oblige à appuyer sur le bouton reset à chaque fois qu’on configure le FPGA.

Le script qui contrôle l’ILA se nomme ILAcop pour ILA COntrol Program:

python3 ILAcop.py --help
usage: ILAcop.py [-h] [--version] [--clean] [--showdev] [-wd WORK_DIR] {config,start,reconfig} ...

GateMate ILA control program. With this script, you can configure and execute the ILA with a design under test (DUT).

options:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  --clean               Deletes all output files created by the program.
  --showdev             Outputs all found FTDI ports.
  -wd WORK_DIR          Folder from which Yosys should be started for the synthesis of the Design Under Test.

main_actions:
  {config,start,reconfig}

example usage:
python3 ILAcop.py [Commands]

Commands:
  config:   Configure the ILA.
             -vlog SOURCE    Paths to the Verilog source code files.
             -vhd SOURCE     Paths to the VHDL source code files.
             -t NAME         Top level entity of the design under test.
             -ccf SOURCE     Folder containing the .ccf file of the design under test. 
             -s SPEED        Configure ILA for best performance. Max Sample Width = 40, the number of samples depends on the sample width. 
             -f MHz          Defines the external clock frequency in MHz (default is 10.0 MHz).
             -sync LEVEL     Number of register levels via which the SUT are synchronised (default: 2)
             -d DELAY        ILA PLL Phase shift of sampling frequency. 0=0°, 1=90°, 2=180°, 3=270° (default: 2).
             -opt            Optimizes the design by deleting all unused signals before design evaluation.
          (optional) Subcommands config: 
                -create_json: Creates a JSON file in which the logic analyzer can be configured.
            NOTE: Without the subcommand the configurations are requested step by step via the terminal.
  
  reconfig: Configures the ILA based on a JSON file. With this option you have to specify a JSON file with -l [filename].json.
  
  start     Starts the communication to the ILA with the last uploaded config
    -s  The -s parameter prevents the FPGA from being reconfigured on restart.

Pour configurer le FPGA il semble devoir lancer la commande suivante (dans app/):

$ python3 ILAcop.py config -vlog ../example_dut/blink/src/ -t blink

#################################################################################################
#                   Cologne Chip GateMate ILA control program (ILAcop)                          #
# ********************************************************************************************* #
#    Copyright (C) 2023 Cologne Chip AG <support@colognechip.com>                               #
#    Developed by Dave Fohrn                                                                    #
#                                                                                               #
#    This program is free software: you can redistribute it and/or modify                       #
#    it under the terms of the GNU General Public License as published by                       #
#    the Free Software Foundation, either version 3 of the License, or                          #
#    (at your option) any later version.                                                        #
#                                                                                               #
#    This program is distributed in the hope that it will be useful,                            #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of                             #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                              #
#    GNU General Public License for more details.                                               #
#                                                                                               #
#    You should have received a copy of the GNU General Public License                          #
#    along with this program.  If not, see <https://www.gnu.org/licenses/>.                     #
#                                                                                               #
# ********************************************************************************************* #
#################################################################################################


################# ccf File ##################
#                                           #
# blink.ccf                                 #
#                                           #
#############################################


############### verilog Files ###############
#                                           #
# blink.v                                   #
#                                           #
#############################################

Examine DUT ...

An error has occurred:
ERROR: Module `\CC_USR_RSTN' referenced in module `\blink' in cell `\usr_rstn_inst' is not part of the design.

yosys cmd: 
yosys -l /opt/gatemate/gatemate_ila/log/yosys_DUT.log -p " read -sv /opt/gatemate/gatemate_ila/example_dut/blink/src/blink.v; read_verilog -lib -specify +/gatemate/cells_sim.v +/gatemate/cells_bb.v; hierarchy -check -top blink; proc; flatten; tribuf -logic; deminout; write_verilog /opt/gatemate/gatemate_ila/app/config_design/blink_25-01-17_22-08-52_flat.v ; check;  alumacc; opt; memory -nomap; opt_clean; memory_libmap -lib +/gatemate/brams.txt; techmap -map +/gatemate/brams_map.v;  stat -width"

Mais pour le moment ça ne marche pas. Un mysterieux module CC_USR_RSTN n’est pas référencé.

Si on essais l’exemple en VHDL c’est pas beaucoup mieux, même si l’erreur est différente (pourtant j’ai bien ghdl installé sur ma machine):

$ python3 ILAcop.py config -vhd ../example_dut/blink/src/ -t blink

#################################################################################################
#                   Cologne Chip GateMate ILA control program (ILAcop)                          #
# ********************************************************************************************* #
#    Copyright (C) 2023 Cologne Chip AG <support@colognechip.com>                               #
#    Developed by Dave Fohrn                                                                    #
#                                                                                               #
#    This program is free software: you can redistribute it and/or modify                       #
#    it under the terms of the GNU General Public License as published by                       #
#    the Free Software Foundation, either version 3 of the License, or                          #
#    (at your option) any later version.                                                        #
#                                                                                               #
#    This program is distributed in the hope that it will be useful,                            #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of                             #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                              #
#    GNU General Public License for more details.                                               #
#                                                                                               #
#    You should have received a copy of the GNU General Public License                          #
#    along with this program.  If not, see <https://www.gnu.org/licenses/>.                     #
#                                                                                               #
# ********************************************************************************************* #
#################################################################################################


################# ccf File ##################
#                                           #
# blink.ccf                                 #
#                                           #
#############################################


################ vhdl Files #################
#                                           #
# blink.vhd                                 #
#                                           #
#############################################

Examine DUT ...

An error has occurred:
ERROR: No such command: ghdl (type 'help' for a command overview)

yosys cmd: 
yosys -l /opt/gatemate/gatemate_ila/log/yosys_DUT.log -p " ghdl --warn-no-binding -C --ieee=synopsys /opt/gatemate/gatemate_ila/example_dut/blink/src/blink.vhd  -e blink; hierarchy -check -top blink; proc; flatten; tribuf -logic; deminout; write_verilog /opt/gatemate/gatemate_ila/app/config_design/blink_25-01-17_22-12-24_flat.v ; check;  alumacc; opt; memory -nomap; opt_clean; memory_libmap -lib +/gatemate/brams.txt; techmap -map +/gatemate/brams_map.v;  stat -width"

Dans le cas de verilog, le problème vient de la version de yosys utilisé. Si on modifie le fichier config.py pour pointer vers le yosys fourni par CologneChip ça fonctionne :

YOSYS = '/opt/gatemate/cc-toolchain-linux/bin/yosys/yosys'

On peut lancer la commande :

$ python3 ILAcop.py config -vlog ../example_dut/blink/src/ -t blink

#################################################################################################
#                   Cologne Chip GateMate ILA control program (ILAcop)                          #
# ********************************************************************************************* #
#    Copyright (C) 2023 Cologne Chip AG <support@colognechip.com>                               #
#    Developed by Dave Fohrn                                                                    #
#                                                                                               #
#    This program is free software: you can redistribute it and/or modify                       #
#    it under the terms of the GNU General Public License as published by                       #
#    the Free Software Foundation, either version 3 of the License, or                          #
#    (at your option) any later version.                                                        #
#                                                                                               #
#    This program is distributed in the hope that it will be useful,                            #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of                             #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                              #
#    GNU General Public License for more details.                                               #
#                                                                                               #
#    You should have received a copy of the GNU General Public License                          #
#    along with this program.  If not, see <https://www.gnu.org/licenses/>.                     #
#                                                                                               #
# ********************************************************************************************* #
#################################################################################################


################# ccf File ##################
#                                           #
# blink.ccf                                 #
#                                           #
#############################################


############### verilog Files ###############
#                                           #
# blink.v                                   #
#                                           #
#############################################

Examine DUT ...


############# Block RAM in use ##############
#                                           #
# CC_BRAM_20K in use: 0                     #
# CC_BRAM_40K in use: 0                     #
#                                           #
#############################################


############ Found PLL instance #############
#                                           #
# Pll name  = pll_inst                      #
# Frequency = 25 MHz                        #
#                                           #
#############################################

########### Found CC_USR_RSTN ###########

!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!                                                              !
! Now you will be guided through the configuration of the ILA. !
! Entering 'e' exits the process and generates a configurable  !
! JSON file for the given DUT.                                 !
! Enter 'p' for 'previous' to backtrack a step.                !
!                                                              !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!                                                                       !
! In the following, a clock source for the ILA should be selected.      !
! Usually, the same clk signal that clocks the tested signals suffices. !
!                                                                       !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


Here are the possible ways to provide a clock to the ILA:

 1 = Use an external clk input signal.
 2 = Use an additional PLL with a freely selectable frequency (additional net of the global Mesh are required).
 3 = Use a signal generated by a PLL from your design.

Please choose between 1 and 3: 3

########### PLL instances signals ###########
#                                           #
# pll_inst : 25 Mhz                         #
#                                           #
#  0 = CLK0                                 #
#  1 = CLK180                               #
#  2 = CLK270                               #
#  3 = CLK90                                #
#                                           #
#                                           #
#############################################


Attention! If you choose an output signal of a PLL that you will not use in your design, an additional net of Global Mesh is required! 

Choose a clock signal: 0

!!!!!!!!!!!!!!!!!!!!! User controllable reset !!!!!!!!!!!!!!!!!!!!!
!                                                                 !
! The ILA can hold the DUT in reset until capture starts.         !
! This makes it possible to capture the start process of the DUT. !
! Attention, the ila treats the signal as active LOW.             !
!                                                                 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

The following options are available:

 1 = Use an external reset input signal.
 2 = Deactivate this function.
 3 = Use the ouput signal from the CC_USR_RSTN primitive in your design. (The functionality of the CC_USR_RSTN primitive is still given).

Please choose between 1 and 3: 2

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!                                                                                                 !
! You will be prompted to select signals for analysis from those found in your design under test. !
!                                                                                                 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


------------------------- blink --------------------------
+----+-------------------+--------+----------+-----------+
|  # | name              | range  | selected | hierarchy |
+----+-------------------+--------+----------+-----------+
|  1 | LED_ctrl          |   1    |    []    |           |
|  2 | clk               |   1    |    []    |           |
|  3 | clk0              |   1    |    []    |           |
|  4 | clk180            |   1    |    []    |           |
|  5 | clk270            |   1    |    []    |           |
|  6 | clk90             |   1    |    []    |           |
|  7 | counter           | [24:0] |    []    |           |
|  8 | led               | [7:0]  |    []    |           |
|  9 | rst               |   1    |    []    |           |
| 10 | usr_pll_lock      |   1    |    []    |           |
| 11 | usr_pll_lock_stdy |   1    |    []    |           |
| 12 | usr_ref_out       |   1    |    []    |           |
+----+-------------------+--------+----------+-----------+

## Number of selected bits to be analysed ###
#                                           #
# 0 (max. 2400)                             #
#                                           #
#############################################

Select signals to be analyzed (0 = finish): 7

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!                                                                                  !
! Define a range for the vector to be analyzed.                                    !
!  you can do this in the following ways:                                          !
!   1) Press enter to analyze the entire vector                                    !
!   2) Define an area of the vector. (The area should be within the vector area):  !
!        e.g.: '[1:0]'                                                             !
!   3) Individual signals:                                                         !
!        e.g.: '1'                                                                 !
!   4) Any combination of areas and individual signals                             !
!        e.g.: '9, [7:5], 3, [1:0]'                                                !
! define Signals in descending order!                                              !
!                                                                                  !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

reg [24:0] counter: 


------------------------- blink --------------------------
+----+-------------------+--------+----------+-----------+
|  # | name              | range  | selected | hierarchy |
+----+-------------------+--------+----------+-----------+
|  1 | LED_ctrl          |   1    |    []    |           |
|  2 | clk               |   1    |    []    |           |
|  3 | clk0              |   1    |    []    |           |
|  4 | clk180            |   1    |    []    |           |
|  5 | clk270            |   1    |    []    |           |
|  6 | clk90             |   1    |    []    |           |
|  7 | counter           | [24:0] |  ['A']   |           |
|  8 | led               | [7:0]  |    []    |           |
|  9 | rst               |   1    |    []    |           |
| 10 | usr_pll_lock      |   1    |    []    |           |
| 11 | usr_pll_lock_stdy |   1    |    []    |           |
| 12 | usr_ref_out       |   1    |    []    |           |
+----+-------------------+--------+----------+-----------+

## Number of selected bits to be analysed ###
#                                           #
# 25 (max. 2400)                            #
#                                           #
#############################################

Select signals to be analyzed (0 = finish): 1

------------------------- blink --------------------------
+----+-------------------+--------+----------+-----------+
|  # | name              | range  | selected | hierarchy |
+----+-------------------+--------+----------+-----------+
|  1 | LED_ctrl          |   1    |  ['A']   |           |
|  2 | clk               |   1    |    []    |           |
|  3 | clk0              |   1    |    []    |           |
|  4 | clk180            |   1    |    []    |           |
|  5 | clk270            |   1    |    []    |           |
|  6 | clk90             |   1    |    []    |           |
|  7 | counter           | [24:0] |  ['A']   |           |
|  8 | led               | [7:0]  |    []    |           |
|  9 | rst               |   1    |    []    |           |
| 10 | usr_pll_lock      |   1    |    []    |           |
| 11 | usr_pll_lock_stdy |   1    |    []    |           |
| 12 | usr_ref_out       |   1    |    []    |           |
+----+-------------------+--------+----------+-----------+

## Number of selected bits to be analysed ###
#                                           #
# 26 (max. 2400)                            #
#                                           #
#############################################

Select signals to be analyzed (0 = finish): 8

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!                                                                                  !
! Define a range for the vector to be analyzed.                                    !
!  you can do this in the following ways:                                          !
!   1) Press enter to analyze the entire vector                                    !
!   2) Define an area of the vector. (The area should be within the vector area):  !
!        e.g.: '[1:0]'                                                             !
!   3) Individual signals:                                                         !
!        e.g.: '1'                                                                 !
!   4) Any combination of areas and individual signals                             !
!        e.g.: '9, [7:5], 3, [1:0]'                                                !
! define Signals in descending order!                                              !
!                                                                                  !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

wire [7:0] led: 


------------------------- blink --------------------------
+----+-------------------+--------+----------+-----------+
|  # | name              | range  | selected | hierarchy |
+----+-------------------+--------+----------+-----------+
|  1 | LED_ctrl          |   1    |  ['A']   |           |
|  2 | clk               |   1    |    []    |           |
|  3 | clk0              |   1    |    []    |           |
|  4 | clk180            |   1    |    []    |           |
|  5 | clk270            |   1    |    []    |           |
|  6 | clk90             |   1    |    []    |           |
|  7 | counter           | [24:0] |  ['A']   |           |
|  8 | led               | [7:0]  |  ['A']   |           |
|  9 | rst               |   1    |    []    |           |
| 10 | usr_pll_lock      |   1    |    []    |           |
| 11 | usr_pll_lock_stdy |   1    |    []    |           |
| 12 | usr_ref_out       |   1    |    []    |           |
+----+-------------------+--------+----------+-----------+

## Number of selected bits to be analysed ###
#                                           #
# 34 (max. 2400)                            #
#                                           #
#############################################

Select signals to be analyzed (0 = finish): 0

!!!!!!!!!!!!!!!!!!! Note !!!!!!!!!!!!!!!!!!!!
!                                           !
! The capture duration must be defined.     !
! The maximum duration depends on:          !
!  - available ram                          !
!  - width of the sample                    !
!  - sampling frequency                     !
! FIFO Cascade (Width x Depth)              !
! FIFO (Input Width x Depth)                !
!                                           !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

------Please choose one of the following durations: -------
+----+---------+---------------+--------------+-----------+
|  # | smp_cnt | duration [us] | FIFO Cascade |      FIFO |
+----+---------+---------------+--------------+-----------+
|  1 |    1024 |         40.96 |        1 x 1 | 40 x 1024 |
|  2 |    2048 |         81.92 |        1 x 2 | 40 x 1024 |
|  3 |    3072 |        122.88 |        1 x 3 | 40 x 1024 |
|  4 |    4096 |        163.84 |        4 x 1 | 10 x 4096 |
|  5 |    5120 |         204.8 |        1 x 5 | 40 x 1024 |
|  6 |    6144 |        245.76 |        1 x 6 | 40 x 1024 |
|  7 |    8192 |        327.68 |        4 x 2 | 10 x 4096 |
|  8 |   12288 |        491.52 |        4 x 3 | 10 x 4096 |
|  9 |   16384 |        655.36 |        4 x 4 | 10 x 4096 |
| 10 |   20480 |         819.2 |        4 x 5 | 10 x 4096 |
| 11 |   24576 |        983.04 |        4 x 6 | 10 x 4096 |
+----+---------+---------------+--------------+-----------+

Total Capture duration (choose between 1 and 11): 1

############# Capture duration ##############
#                                           #
# Sample count = 1024                       #
# Capture duration = 40.96 us               #
#                                           #
#############################################


Enter the number of capture samples before trigger activation (between 0 and 250): 10

###### Capture duration before Trigger ######
#                                           #
# Sample count = 10                         #
# Capture duration = 0.52 us                #
#                                           #
#############################################


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Note !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!                                                                                   !
! You can override an input or input-vector of your top-level entity using the ILA. !
! Please note that the input will no longer be connected to the FPGA's IO pins.     !
!                                                                                   !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


Would you like to implement the input control feature? (y/N): 

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Note !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!                                                                         !
! There are two default triggers that can be set for exactly one signal:  !
!  'rising edge' and 'falling edge'                                       !
! There is also an optional trigger: pattern compare                      !
! With this option, a pattern can be set across the entire bit width,     !
!  determining for each bit whether it should be '1', '0', or 'dc'        !
!  (don't care) to activate the trigger.                                  !
! If this function is activated, more hardware is required for the ILA    !
!  and the maximum possible sampling frequency may be reduced.            !
!                                                                         !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


Would you like to implement the function for comparing bit patterns? (y/N): 

############ Signals under test #############
#                                           #
# LED_ctrl                                  #
# [24:0] counter                            #
# [7:0] led                                 #
#                                           #
#############################################

Execute Synthesis...
Output permanently saved to: /opt/gatemate/gatemate_ila/log/yosys.log

Execute Implementation...
Output permanently saved to: /opt/gatemate/gatemate_ila/log/impl.log

################# Configuration File ##################
#                                                     #
# save_config/ila_config_blink_25-01-18_07-19-48.json #
#                                                     #
#######################################################

Error configuring the device
Traceback (most recent call last):
  File "/opt/gatemate/gatemate_ila/app/ILAConfig.py", line 1721, in upload
    dev.set_configuration()
  File "/usr/lib/python3/dist-packages/usb/core.py", line 915, in set_configuration
    self._ctx.managed_set_configuration(self, configuration)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 113, in wrapper
    return f(self, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 158, in managed_set_configuration
    self.managed_open()
  File "/usr/lib/python3/dist-packages/usb/core.py", line 113, in wrapper
    return f(self, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 131, in managed_open
    self.handle = self.backend.open_device(self.dev)
  File "/usr/lib/python3/dist-packages/usb/backend/libusb1.py", line 804, in open_device
    return _DeviceHandle(dev)
  File "/usr/lib/python3/dist-packages/usb/backend/libusb1.py", line 652, in __init__
    _check(_lib.libusb_open(self.devid, byref(self.handle)))
  File "/usr/lib/python3/dist-packages/usb/backend/libusb1.py", line 604, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 13] Access denied (insufficient permissions)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/opt/gatemate/gatemate_ila/app/ILAcop.py", line 277, in <module>
    if not ILA_config_instance.upload():
  File "/opt/gatemate/gatemate_ila/app/ILAConfig.py", line 1726, in upload
    if dev.is_kernel_driver_active(intf.bInterfaceNumber):
  File "/usr/lib/python3/dist-packages/usb/core.py", line 1107, in is_kernel_driver_active
    self._ctx.managed_open()
  File "/usr/lib/python3/dist-packages/usb/core.py", line 113, in wrapper
    return f(self, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/usb/core.py", line 131, in managed_open
    self.handle = self.backend.open_device(self.dev)
  File "/usr/lib/python3/dist-packages/usb/backend/libusb1.py", line 804, in open_device
    return _DeviceHandle(dev)
  File "/usr/lib/python3/dist-packages/usb/backend/libusb1.py", line 652, in __init__
    _check(_lib.libusb_open(self.devid, byref(self.handle)))
  File "/usr/lib/python3/dist-packages/usb/backend/libusb1.py", line 604, in _check
    raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 13] Access denied (insufficient permissions)

Il semble que je n’ai pas configuré correctement l’usb. Il faut ajouter une règle udev pour le DirtyJtag :

$ lsusb
...
Bus 001 Device 043: ID 1209:c0ca Generic Jean THOMAS DirtyJTAG
...

On ouvre ajoute un fichier de règle :

sudo vim /etc/udev/rules.d/99-usb-serial.rules

SUBSYSTEM=="usb", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="c0ca", MODE="0666"

Puis on recharge udev:

sudo udevadm control --reload-rules
sudo udevadm trigger

Le câble est maintenant accessible sans être en sudo :

openFPGALoader --cable dirtyJtag --detect
Jtag frequency : requested 6000000Hz -> real 6000000Hz
index 0:
	idcode 0x20000001
	manufacturer colognechip
	family GateMate Series
	model  GM1Ax
	irlength 6

On va plus loin cette fois, mais il ne trouve pas la carte :

...
################# Configuration File ##################
#                                                     #
# save_config/ila_config_blink_25-01-18_07-47-38.json #
#                                                     #
#######################################################


Upload to FPGA Board...
Execute openFPGALoader command:
openFPGALoader  -b olimex_gatemateevb /opt/gatemate/gatemate_ila/p_r_out/ila_top_25-01-18_07-47-38_00.cfg


Error: 

Error: cannot find board 'olimex_gatemateevb'

Il semble que ma version d’openFPGALoader soit trop vieille, et une sombre histoire de libstdc++ m’empêche d’utiliser correctement le binaire fourni par CologneChip.

Mettons donc à jour les sources officielles:

$ cd /opt/openFPGALoader
$ git pull -r
$ rm -rf build
$ mkdir build
$ cd build/
$ cmake ..
$ cmake --build .
$ make -j10
$ sudo make install

Cette fois le fichier de dump vcd est créé et une fenête gtkwave s’ouvre sur les chronogrammes saisis !

$ python3 ILAcop.py start

#################################################################################################
#                   Cologne Chip GateMate ILA control program (ILAcop)                          #
# ********************************************************************************************* #
#    Copyright (C) 2023 Cologne Chip AG <support@colognechip.com>                               #
#    Developed by Dave Fohrn                                                                    #
#                                                                                               #
#    This program is free software: you can redistribute it and/or modify                       #
#    it under the terms of the GNU General Public License as published by                       #
#    the Free Software Foundation, either version 3 of the License, or                          #
#    (at your option) any later version.                                                        #
#                                                                                               #
#    This program is distributed in the hope that it will be useful,                            #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of                             #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                              #
#    GNU General Public License for more details.                                               #
#                                                                                               #
#    You should have received a copy of the GNU General Public License                          #
#    along with this program.  If not, see <https://www.gnu.org/licenses/>.                     #
#                                                                                               #
# ********************************************************************************************* #
#################################################################################################


Upload to FPGA Board...
writeTDI: read: usb bulk read failed [Errno 110] Operation timed out

############ CONFIGURATION NOTE #############
#                                           #
# Trigger at sample no.: 10                 #
# Defined analysis frequency: 25000000 Hz   #
#                                           #
#############################################


--- All Signals ----
+----+-------------+
|  # |        Name |
+----+-------------+
|  0 |      led[0] |
|  1 |      led[1] |
|  2 |      led[2] |
|  3 |      led[3] |
|  4 |      led[4] |
|  5 |      led[5] |
|  6 |      led[6] |
|  7 |      led[7] |
|  8 |  counter[0] |
|  9 |  counter[1] |
| 10 |  counter[2] |
| 11 |  counter[3] |
| 12 |  counter[4] |
| 13 |  counter[5] |
| 14 |  counter[6] |
| 15 |  counter[7] |
| 16 |  counter[8] |
| 17 |  counter[9] |
| 18 | counter[10] |
| 19 | counter[11] |
| 20 | counter[12] |
| 21 | counter[13] |
| 22 | counter[14] |
| 23 | counter[15] |
| 24 | counter[16] |
| 25 | counter[17] |
| 26 | counter[18] |
| 27 | counter[19] |
| 28 | counter[20] |
| 29 | counter[21] |
| 30 | counter[22] |
| 31 | counter[23] |
| 32 | counter[24] |
| 33 |    LED_ctrl |
+----+-------------+

##### current ILA runtime configuration #####
#                                           #
# Number of sequences: 1                    #
#                                           #
#  Sequences Number: 1                      #
#     trigger activation: falling edge      #
#     trigger signal:     led[0]            #
#                                           #
#############################################



0 -- exit
1 -- change Trigger
2 -- start capture
3 -- reset ILA (resets the config of the ILA)

Enter your choice: 2

################# start Capture #################
#                                               #
# Waiting for device. Press Enter to interrupt. #
#                                               #
#################################################


############### Duration between captures ##############
#                                                      #
# Duration between start and first trigger: 0.009355 s #
#                                                      #
########################################################


############### create vcd file ###############
#                                             #
# vcd_files/ila_blink_25-01-18_20-54-13_0.vcd #
#                                             #
###############################################


Press Enter to continue

Pas mal !

Par contre plus aucune LED ne s’allument hormis la rouge de l’alimentation. Il est possible que le fichier de contraintes ne soit par correct. Le fichier se trouve dans le répertoire source de l’exemple :

Fichier /opt/gatemate/gatemate_ila/example_dut/blink/src/blink.ccf:

Pin_in   "clk"  Loc = "IO_SB_A8" | SCHMITT_TRIGGER=true;
Pin_out  "led[0]"                   Loc = "IO_EB_B1";                           # LED D1
Pin_out  "led[1]"                   Loc = "IO_EB_B2";                           # LED D2
Pin_out  "led[2]"                   Loc = "IO_EB_B3";                           # LED D1
Pin_out  "led[3]"                   Loc = "IO_EB_B4";                           # LED D2
Pin_out  "led[4]"                   Loc = "IO_EB_B5";                           # LED D1
Pin_out  "led[5]"                   Loc = "IO_EB_B6";                           # LED D2
Pin_out  "led[6]"                   Loc = "IO_EB_B7";                           # LED D1
Pin_out  "led[7]"                   Loc = "IO_EB_B8";                           # LED D2

Si l’on regarde la carte, les IO_EB_Bx se trouvent sur le bank BANK_EB1 qui ne sont pas connecté à des leds.

Notez que pour ouvrir les schéma de la carte, kicad 6 ne suffit pas. Sur Linux Mint on peut installer kicad 8 avec les commandes suivante:

$  sudo add-apt-repository ppa:kicad/kicad-8.0-releases
$  sudo apt update
$  sudo apt install kicad

La led sur le schema:

Se trouve sur le port IO_SB_B6 du gatemate:

Il faut donc en changer pour le pin de la LED FPGA_LED1 histoire d’en voir au moins une clignoter.

Pin_in   "clk"  Loc = "IO_SB_A8" | SCHMITT_TRIGGER=true;
Pin_out  "led[0]"                   Loc = "IO_EB_B1";                           # LED D1
Pin_out  "led[1]"                   Loc = "IO_EB_B2";                           # LED D2
Pin_out  "led[2]"                   Loc = "IO_EB_B3";                           # LED D1
Pin_out  "led[3]"                   Loc = "IO_EB_B4";                           # LED D2
#Pin_out  "led[4]"                   Loc = "IO_EB_B5";                           # LED D1
Pin_out  "led[4]"                   Loc = "IO_SB_B6";                           # FPGA_LED1 
Pin_out  "led[5]"                   Loc = "IO_EB_B6";                           # LED D2
Pin_out  "led[6]"                   Loc = "IO_EB_B7";                           # LED D1
Pin_out  "led[7]"                   Loc = "IO_EB_B8";                           # LED D2 

On modifie le fichier ccf puis on clean le projet pour le relancer:

$ python3 ILAcop.py  --clean
$ python3 ILAcop.py config -vlog ../example_dut/blink/src/ -t blink
$ python3 ILAcop.py start

Bon pour le coup j’ai été un peu vite et j’ai du relancer toute la config. Mais on peut faire un clean sans avoir à tout reconfigurer et relancer la dernière configuration:

$ python3 ILAcop.py reconfig -l save_config/ila_config_blink_25-01-18_21-31-30.json

Cette fois la LED verte du FPGA_LED1 clignote.

It’s blinking \o/

CLEAR: Le FPGA libéré

On en parlait il y a deux ans sur ce blog, mais ça y est, c’est arrivé !

Ce soir dans ma boite aux lettres j’ai eu le plaisir d’y découvrir un kit de développement du premier eFPGA opensource : le CLEAR.

Voici le kit de développement du CLEAR fraîchement sortie de son emballage

Attention, on ne parle pas ici d’un simple FPGA qui aurait sa chaîne de développement libérée comme nous commençons à en trouver quelques un sur le marché aujourd’hui.

Non, ici c’est le silicium même qui a été conçu au moyen d’outils open sources. La gravure même des transistors.

Alors certes, il ne possède que 64 CLB et est gravé en 130 nm. Mais cela valide tout de même le sérieux du projet openFPGA.

Maintenant que le FPGA est libéré, une question se pose à propos de ce blog : Doit il continuer ? 😉

Couleur des log dans (neo)vim

La synthèse et le placement routage génère de grande quantité de texte de «log». Dans ces logs, les problèmes s’étagent avec 3 niveaux de «danger» :

  • INFO: juste une information
  • WARNING: Un problème qu’il faut lire mais qui peut souvent être ignoré
  • ERROR: Je ne dirais pas que c’est un échec, mais ça n’a pas marché

Si on utilise Vim (ou neovim) pour lire les logs on aimerait avoir de la surbrillance de couleurs différentes en fonction de la gravité du message.

Un truc comme ça :

Saisie d'écran de vim avec un fichier de log fictif ouvert. On y voit le texte INFO en blanc sur bleu, le texte Warning en blanc sur jaune et le texte ERROR en blanc sur rouge

C’est quelques chose qui est relativement facile à mettre en place dans neovim. Il faut tout d’abord créer un fichier de syntaxe dans le répertoire ~/.config/nvim/syntax que l’on nommera log.vim et qui contiendra ceci :

" my highlight rules for fpga logs
syntax match fpgaloginfo /INFO\c/
syntax match fpgalogwarn /WARNING\c/
syntax match fpgalogerr  /ERROR\c/
highlight fpgaloginfo  ctermbg=blue guibg=blue
highlight fpgalogwarn  ctermbg=3 guibg=orange
highlight fpgalogerr   ctermbg=red guibg=red

Puis il faut dire à vim que les fichiers terminant par .log sont de type log en ajoutant la ligne suivante dans son fichier de configuration ~/.config/nvim/init.vim :

autocmd! BufRead,BufNewFile *.log     set syntax=log
autocmd! BufRead,BufNewFile *.rpt     set syntax=log

De cette manière, à chaque fois que nvim ouvrira un fichier nommé monfichier.log, il chargera la coloration syntaxique que nous avons configuré.

Comment générer du SystemVerilog et/ou du Verilog avec Chisel 6

Avec les dernières version de chisel le «backend» de génération du verilog a changé.

SystemVerilog

Avec circt on peut générer en systemVerilog avec la méthode emitSystemVerilogFile() inclue dans le package:

import circt.stage.ChiselStage

//...

class MonModule extends Module {
 //...
}

object MonModule extends App {
    ChiselStage.emitSystemVerilogFile( new MonModule(),
      firtoolOpts = Array("-disable-all-randomization",
                          "--lowering-options=disallowLocalVariables",
                          "-strip-debug-info"))

}

Le fichier généré se nommera MonModule.sv

Verilog

Pour générer du Verilog il faut utiliser l’ancienne méthode que l’on trouve dans le package chisel3.

object MonModule extends App {
    val filename = "MonModule.v"
    println("Generate verilog source for ChisNesPad Module")
    val verilog_src = chisel3.emitVerilog(new MonModule)
    val filepath = os.pwd / filename
    if (os.exists(file)) os.remove(file)
    os.write(filepath, verilog_src)
}

Le choix

Et l’on peut s’ajouter une option à la ligne de commande si l’on veut avoir le choix.

import circt.stage.ChiselStage

//...

class MonModule extends Module {
 //...
}

object MonModule extends App {
  if (args.length == 0) {
  } else if (args(0) == "--systemVerilog") {
    ChiselStage.emitSystemVerilogFile( new MonModule(),
      firtoolOpts = Array("-disable-all-randomization",
                          "--lowering-options=disallowLocalVariables",
                          "-strip-debug-info"))
  }
}

On lancera les commandes suivantes pour générer l’un ou l’autre :

# générer le verilog
sbt "runMain MonModule"
# générer le systemVerilog
sbt "runMain MonModule --systemVerilog"

Quickfeather eos s3 logic cell (pp3)

Quand on utilise la suite symbiflow pour synthétiser un projet sur le eFPGA (pp3) de la quickfeather on tombe sur des nom étranges de cellule logique.

Circuit Statistics:
  Blocks: 65
    .output   :       3
    ASSP      :       1
    BIDIR_CELL:       3
    C_FRAG    :       7
    F_FRAG    :       1
    GND       :       1
    Q_FRAG    :      22
    T_FRAG    :      26
    VCC       :       1

À quoi correspondent les blocks C_FRAG, T_FRAG, ASSP, … ?

Et il est assez compliqué de trouver la documentation correspondante. On retrouve une description en Verilog de ces blocs dans le répertoire suivant du SDK :

$ ls qorc-sdk/fpga_toolchain_install/v1.3.1/quicklogic-arch-defs/share/techmaps/quicklogic/pp3/techmap/
cells_map.v  cells_sim.v  lut2tomux2.v  lut2tomux4.v  lut3tomux2.v  mux4tomux2.v  mux8tomux2.v

Et plus particulièrement dans le fichier source cells_map.v qui semble décrire au moyen de plusieurs «FRAG»ment de module le schéma de la figure 36 de la datasheet (page 60).

Le schéma d’une «Logic Cell Block» trouvé dans la datasheet

En lisant le code du fichier cells_sim.v on trouve les relations suivantes dans le schéma.

Annotation du schéma de cellule logique à partir du fichier cells_sim.v

Les nom de signaux QDI et QDS ne se trouvent pas dans le fichier source, ils sont liés au multiplexeur situé devant la bascule D Q_FRAG et semble correspondre aux constantes CONST0 et CONST1 que l’on trouve dans les sources.

Pour les fragments T_FRAG et B_FRAG c’est moins clair en se servant du nom des signaux mais ils semblent liés à des bits de configuration que l’on trouve à gauche du schéma (BAS, BBS, TAS, …)

On imagine aisément que le FRAG correspond à Fragment mais les lettres préfixes sont moins claires.

Si on fait la liste des noms de block donnés au début on a

  • ASSP: celui là est plus clair. C’est le bloc qui assure la communication avec le microcontrolleur, avec les différents signaux de bus (Wishbone, SPI, …) ainsi que l’horloge, et autres signaux de contrôles.
  • BIDIR_CELL: Ça c’est un buffer d’entrée sortie `iopad`
  • C_FRAG: Cet enchevêtrement de multiplexeurs ressemble fort à une LUT avec une sortie retenue (C pour Carry).
  • F_FRAG: Là on a affaire à un simple multiplexeur deux entrées, pour faciliter le routage (routage rapide ?)
  • GND: bon bin … la masse quoi (mais qu’est-ce que ça vient faire là ?)
  • Q_FRAG: Q pour la sortie de la bascule D Flip flop.
  • T_FRAG: ?
  • VCC: L’alim, …
  • B_FRAG: celui là n’est pas dans le rapport de routage mais se trouve dans le code verilog, il ressemble à T_FRAG.

Tout cela n’est pas parfaitement claire.

Et surtout on aurait aimé avoir un schéma d’architecture du eFPGA comme on peut le voir dans les datasheet des autres constructeur. Avec l’alignement des différentes cellule et une description graphique des entrées sorties.

C’était juste une prise de note (susceptible d’évoluer comme d’habitude) pour tenter de comprendre ce FPGA à la documentation pas très claire.

[Edit 2024/01/19]

J’ai eu des réponses sur le site officiel \o/ Il y a plus de détails du coup. Je vais pouvoir continuer mes investigations.

Getting started with FPGAS

Russell Merrick est un ingénieur en électronique qui travail sur des FPGA depuis plus de 15 ans. C’est l’auteur du site internet Nandland qui propose toute une série de tutoriels pour débuter et s’amuser avec des FPGA.

Russell vient de sortir un livre chez No Starch Press pour débuter avec un FPGA.

En seulement 280 pages, on peut dire que l’auteur couvre bien le sujet. Les deux langages HDL du «marché» sont décrits et tous les exemples sont donnés en Verilog ainsi qu’en VHDL.

C’est la première fois que, dans un livre, je vois un vrai comparatif des deux HDL. En effet, l’un est souvent balayé au profit de l’autre avec un «si vous connaissez l’un vous saurez vous servir de l’autre». Même si l’accent est mis sur le ICE40 de Lattice (Célèbre FPGA lowcost reversé dans le projet icestorm), on sent bien qu’il existe d’autres constructeurs et que l’auteur a travaillé avec.

Le livre n’est pas si gros et pourtant il traite vraiment de tout ce qu’il faut savoir pour bien commencer (et avancer) dans le FPGA.

Un chapitre entier est consacré aux bascule D (FlipFlop) et à la problématique de conception synchrone. La notion de domaines d’horloge et son franchissement, les machines d’états, les macro classique (RAM, PLL, DSP) ne sont pas en reste.

Et avant d’aborder les entrées sorties (I/O, LVDS, SerDes) un chapitre particulièrement intéressant sur l’arithmétique est abordé. Tout est dit pour additionner, soustraire, multiplier et diviser (enfin surtout les méthodes de contournement de la division) des entiers mais également des nombres en virgules fixe (Qn.m) dans un FPGA.

C’est un livre que j’aurais adoré avoir pour débuter en FPGA, mais qui fera tout de même un très bon livre de référence au besoin.

Cartes Gatemate

Nous avons déjà parlé du Gatemate dans les colonnes du FLF. Mais jusqu’à présent, seul le kit de développement officiel de CologneChip était disponible. Le tarif du kit officiel étant assez élevé on attendait avec impatience d’avoir des cartes développées par des tiers pour pouvoir investir.

Ce qui est chose faite avec les kits suivant. La note reste éditable au grès des sorties de kit muni du FPGA.

Evaluation board officielle par CologneChip

À tout seigneur tout honneur, citons d’abord du kit officiel qui est proposé à un prix de 226€ sur digikey.

Le kit officiel du GateMateA1 proposé par CologneChip dans sa belle boite en carton

Olimex GateMate-A1

Annoncé en décembre 2023 par Olimex, le kit GateMateA1 devrait être proposé au tarif de 50€.

La carte GateMate A1 annoncée par Olimex

TrenzMicro TEG2000-01-P001

Le SoM de TrenzMicro TEG2000-01-P001 est dans les même ordre de grandeur au niveau tarif (69€) mais nécessitera une carte d’accueil pour s’en servir.

Le SoM (System on Module) de Trenz micro avec le GatemateA1