kFPGA - le futur du FPGA bientôt disponible !

Posted on Sun 09 June 2019 in kfpga

Cela fait des années que j’ai pour projet de créer un FPGA libre. Plus spécifiquement, j’aimerais créer une plateforme libre de génération de FPGA qui permettra à tout un chacun de concevoir le sien. J’ai conscience qu’à la vue des moyens financiers demandés, assez peu de ces designs seront réellement fabriqués. Mais cela devrait quand même permettre d’apporter un peu de fraîcheur dans un monde dominé par quelques entreprises (majoritairement Xilinx et Intel) et où tout est propriétaire à l’extrême.

La plateforme, à partir d’un modèle d’architecture FPGA, sera capable de générer un FPGA dont les caractéristiques sont fournis par l’utilisateur tel que nombre de blocs logiques, tailles des LUT, dispositions des colonnes de multiplieurs… ainsi que le flot d’implémentation associé.

Mais pour ça, il faut notamment un modèle d’architecture FPGA à générer. Et c’est là qu’intervient kFPGA (killruana’s FPGA. Originalité, quand tu nous tiens…). Il s’agit de la première architecture de FPGA complètement libre (à ma connaissance) ! Ok, pas encore libre parce que je n’ai pas encore choisi sa licence, mais ça sera un truc très libéral, probablement une CeCILL-B. J’ai choisi une conception extrêmement simple pour commencer : une architecture en îles, des blocs logiques constitués uniquement de LUT, et du routage. Pas de trucs extravagant tel que des carry-chains, des DSP, de la mémoire… Bref, un FPGA old-school tout droit sorti des années 80 !

Schéme de l'architecture kFPGA

Et hier, j'ai enfin atteint une étape importante me permettant de valider la réalisabilité du projet. J'ai enfin réussi à produire un bloc logique fonctionnel et autonome, qui après programmation manuelle, a réalisé des additions deux bits !

Tout d'abord, le modèle de référence :

Modèle et simulation d'un adder 2 bits

C'est un peu illisible, mais en résumé, nous pouvons voir la valeurs des entrées A et B au cours du temps ainsi que la valeur de la sortie S. Ainsi, on peut voir que là où il y a le curseur, on a 3 + 0 = 0.

Et maintenant, le chronogramme de l'additionneur implémenté par le FPGA :

Simulation d'un adder 2 bits implémenté sur une « Logic Tile »

Zoom sur la partie intéressante. On peut voir que nous avons les mêmes motifs que sur le modèle de référence. Fonctionnement validé !

Détail de la simulation précédente

Et pour les plus curieux/masochiste, voilà comment on calcule à la main la configuration d'un FPGA:

bitstream = (
    # LC
    (
        # LE0
        (
            # LUT - a ^ b
            0b0110011001100110011001100110011001100110011001100110011001100110

            # disable DFF
            | 0 << 64
        )

        # LE1
        | (
            # LUT - a ^ b
            0b0110011001100110011001100110011001100110011001100110011001100110

            # disable DFF
            | 0 << 64
        ) << 65

        # LE2
        | (
            # LUT - a & b
            0b1000100010001000100010001000100010001000100010001000100010001000

            # disable DFF
            | 0 << 64
        ) << 130

        # LE3
        | (
            # LUT - a ^ b
            0b0110011001100110011001100110011001100110011001100110011001100110

            # disable DFF
            | 0 << 64
        ) << 195

        # Clock selection
        | 0 << 260

        # Set selection
        | 0 << 262

        # Reset selection
        | 0 << 264
    )

    # SB config
    | (
        # North
        (
            0
        )

        # East
        | (
            0
        ) << 90

        # South
        | (
            0
        ) << 180

        # West
        | (
            # 0 <- LC[0]
            3 << (3 * 0)

            # 1 <- LC[1]
            | 6 << (3 * 1)
        ) << 270

        # LC
        | (
            # 0 <- W[0]
            91 << (7 * 0)

            # 1 <- W[2]
            | 93 << (7 * 1)

            # 6 <- W[1]
            | 92 << (7 * 6)

            # 7 <- W[3]
            | 94 << (7 * 7)

            # 12 <- W[0]
            | 91 << (7 * 12)

            # 13 <- W[2]
            | 93 << (7 * 13)

            # 18 <- LC[1]
            | 122 << (7 * 18)

            # 19 <- LC[2]
            | 123  << (7 * 19)
        ) << 360
    ) << 266
)