« SE4Binome2025-2 » : différence entre les versions
(→Annexe) |
(→Annexe) |
||
| Ligne 513 : | Ligne 513 : | ||
* <code>σ₁<sup>{256}</sup>(x) = ''ROTR<sup>17</sup>''(x) ⊕ ''ROTR<sup>19</sup>''(x) ⊕ SHR<sup>10</sup>(x)</code> | * <code>σ₁<sup>{256}</sup>(x) = ''ROTR<sup>17</sup>''(x) ⊕ ''ROTR<sup>19</sup>''(x) ⊕ SHR<sup>10</sup>(x)</code> | ||
'''Simulation''' | '''Simulation''' | ||
[[Fichier:Message.png|gauche|vignette|Message]] | |||
[[Fichier:Message hash.png|vignette|869x869px|SHA256 du message]] | [[Fichier:Message hash.png|vignette|869x869px|SHA256 du message]] | ||
Version du 23 décembre 2025 à 23:22
Objectif
L'objectif du projet est de concevoir un pico-ordinateur complet, intégrant :
- Une carte mère basée sue le microcontrôleur AT90USB1286
Une partie logicielle permettant l'éxecution de de commandes telles que ls, cp ou mv
Shield Arduino
Une première étape du projet a consisté à développer un shield pour Aduino uno, servant de plateforme de test et de développement pour les cartes filles SPI.
Fonctionalités:
- Connexion de 5 périphériques SPI via des cartes filles.
- Gestion des signaux Reset et Interruption.
- Ajout d'une mémoire externe carte micro-SD via un connecteur Molex 10431.
- Adaptation des niveaux logiques (5V a 3,3V) grâce à la puce 74LV125.
Ce shield joue le rôle de plateforme de développement temporaire, en attendant la carte mère du pico-ordinateur.
Schématique et routage
Objectif
Carte mère
Schématique
Routage
Vue 3D
Firmware — Pico-OS (RTOS Préemptif)
Modèle d'Ordonnancement
Vue d'ensemble du système
Le firmware implémente un système d'exploitation temps réel (RTOS) préemptif complet pour l'ATmega328P. Contrairement à la version coopérative précédente, ce noyau utilise des interruptions matérielles pour forcer le changement de contexte entre les tâches, garantissant qu'une tâche lourde (comme lister des fichiers SD) ne bloque jamais les tâches critiques (comme clignoter une LED).
Caractéristiques principales :
- Ordonnancement Préemptif : Commutation de contexte basée sur le Timer1 (100 Hz).
- Priorités : Ordonnanceur Round-Robin avec niveaux de priorité (IDLE, LOW, MEDIUM, HIGH).
- Système de Fichiers FAT16 : Lecture/Écriture complète, création/suppression de fichiers, support des scripts.
- Shell Interactif : Interface ligne de commande via UART (115200 bauds).
- Optimisation Extrême : Conçu pour fonctionner dans les 2 Ko de RAM de l'ATmega328p.
Architecture Logicielle
L'arborescence du projet est structurée pour séparer le noyau, les pilotes et le système de fichiers.
src/
├─ main.c # Point d'entrée et définition des tâches utilisateur
├─ Makefile # Système de compilation
├─ kernel/ # Cœur de l'OS
│ ├─ kernel.c/h # Initialisation et boucles principales
│ ├─ scheduler.c/h # Gestionnaire de tâches et ISR
│ ├─ task.c/h # Création de tâches et gestion de la pile
│ └─ config.h # Paramètres globaux (Fréquence, Taille piles)
├─ drivers/ # Pilotes Matériels
│ ├─ uart.c/h # Gestion du port série (Interruption RX)
│ ├─ spi_bitbang.c/h # SPI logiciel atomique
│ └─ sd_card.c/h # Protocole SD bas niveau (CMD/Response)
├─ fs/ # Système de fichiers
│ └─ fat16.c/h # Implémentation FAT16 complète
└─ shell/ # Interface Utilisateur
└─ shell_core.c/h # Interpréteur de commandes
Le Noyau (Kernel)
Commutation de Contexte (Context Switching)
Le cœur du système repose sur l'interruption du Timer 1. Nous utilisons une fonction `ISR_NAKED` pour avoir un contrôle total sur la pile (Stack).
Le mécanisme de préemption :
- **Interruption :** Le Timer 1 se déclenche toutes les 10ms.
- **Sauvegarde (Push) :** L'ISR empile manuellement les 32 registres généraux (`r0` à `r31`) et le registre d'état (`SREG`).
- **Sauvegarde du SP :** Le pointeur de pile matériel (`SP`) est sauvegardé dans la structure de la tâche courante (`task->stack_ptr`).
- **Ordonnancement :** La fonction C `scheduler_tick_preemptive()` choisit la prochaine tâche.
- **Restauration (Pop) :** Le `SP` de la nouvelle tâche est chargé, puis ses registres sont dépilés.
- **RETI :** L'instruction de retour restaure le compteur ordinal (PC), reprenant l'exécution de la nouvelle tâche exactement là où elle s'était arrêtée.
ISR(TIMER1_COMPA_vect, ISR_NAKED) {
// 1. Sauvegarde du contexte (Assembleur inline)
asm volatile(
"push r0 \n in r0, __SREG__ \n push r0 \n" // Sauve SREG
"push r1 \n push r2 \n ... \n push r31 \n" // Sauve R1-R31
);
// 2. Sauvegarde du Pointeur de Pile (SP) vers la Tâche Courante
asm volatile(
"lds r28, current_task_ptr \n" // Charge l'adresse du TCB
"in r30, 0x3d \n" // Lit SPL
"std Y+4, r30 \n" // Stocke dans TCB->stack_ptr
);
// 3. Appel de l'Ordonnanceur C
asm volatile("call scheduler_tick_preemptive");
// 4. Restauration du Pointeur de Pile depuis la Nouvelle Tâche
// 5. Restauration du contexte (Pop)
asm volatile("reti");
}
Gestion des Tâches et Ordonnanceur
Le cœur de Pico-OS repose sur un système multitâche préemptif conçu pour fonctionner efficacement sur des microcontrôleurs à ressources limitées comme l'ATmega328P. Cette section détaille les mécanismes de création de tâches, leurs états, et le fonctionnement de l'ordonnanceur.
Les Tâches (Tasks)
Une tâche dans Pico-OS est une unité d'exécution indépendante, représentée par une fonction C standard. Chaque tâche possède son propre contexte d'exécution (registres CPU, pointeur de pile) et sa propre pile (stack).
Structure de Contrôle de Tâche (TCB)
Chaque tâche est décrite par une structure `task_t` (Task Control Block), définie dans `kernel/task.h`. Cette structure contient toutes les informations nécessaires à la gestion de la tâche par le noyau.
typedef struct task_control_block {
void (*function)(void*); // Pointeur vers la fonction de la tâche
void* arg; // Argument passé à la tâche
uint8_t* stack_ptr; // Pointeur de pile courant (sauvegardé lors d'un changement de contexte)
uint8_t* stack_base; // Adresse de base de la pile allouée
uint16_t stack_size; // Taille de la pile en octets
task_state_t state; // État actuel de la tâche (READY, RUNNING, SLEEPING...)
uint16_t sleep_ticks; // Compteur pour le sommeil (en ticks système)
uint8_t priority; // Priorité de la tâche (0 = IDLE, 1 = LOW, ..., 3 = HIGH)
char name[TASK_NAME_LENGTH]; // Nom de la tâche (pour le débogage et l'affichage 'ps')
} task_t;
États d'une Tâche
Une tâche peut se trouver dans l'un des états suivants, définis par l'énumération `task_state_t` :
- TASK_READY (0) : La tâche est prête à être exécutée mais attend que l'ordonnanceur lui alloue le processeur.
- TASK_RUNNING (1) : La tâche est actuellement en cours d'exécution sur le processeur.
- TASK_SLEEPING (2) : La tâche est en attente pour une durée déterminée (appel à `task_sleep()`). Elle ne sera pas sélectionnée par l'ordonnanceur tant que son délai n'est pas écoulé.
- TASK_BLOCKED (5) : La tâche est bloquée en attente d'un événement (non temporel), comme la disponibilité d'une ressource (par ex. sémaphore, non implémenté dans la version de base).
- TASK_COMPLETED (6) : La tâche a terminé son exécution (retour de la fonction ou appel à `task_exit()`). Elle ne sera plus jamais planifiée.
Création d'une Tâche
La création d'une tâche se fait via la fonction `task_create()`. Cette fonction initialise le TCB et prépare la pile de la tâche pour qu'elle puisse démarrer correctement lors de son premier ordonnancement.
Processus de création :
- Allocation du TCB : Le noyau recherche un emplacement libre dans le tableau global `task_table`.
- Initialisation du TCB : Les champs du TCB (fonction, argument, priorité, état, nom) sont remplis. Le nom est copié depuis la mémoire Flash (PROGMEM) vers la RAM du TCB.
- Préparation de la Pile (Stack Frame) : C'est l'étape critique. La fonction `task_create_context()` simule l'état de la pile tel qu'il serait après une interruption. Elle empile :
- L'adresse de retour (PC) pointant vers le début de la fonction de la tâche.
- Le registre d'état `SREG` avec le bit d'interruption globale (I) activé, pour que les interruptions soient autorisées dès le lancement de la tâche.
- Des valeurs initiales (souvent 0) pour tous les registres généraux (R0-R31), afin d'assurer un état connu.
- Enregistrement : La tâche est marquée comme `TASK_READY` et le compteur de tâches `task_count` est incrémenté.
// Exemple de création de tâche dans main.c
task_create(name_blink, blink_task, NULL, 2, blink_task_stack, sizeof(blink_task_stack));
L'Ordonnanceur (Scheduler)
L'ordonnanceur est le composant du noyau responsable de distribuer le temps processeur entre les différentes tâches prêtes (`TASK_READY`). Pico-OS utilise un ordonnanceur préemptif à priorités fixes avec round-robin.
Fonctionnement Préemptif
La préemption est assurée par le Timer 1 de l'ATmega328P, configuré pour générer une interruption périodique (tick système) à une fréquence définie (par défaut 100 Hz, soit toutes les 10 ms).
L'interruption Timer1 déclenche la routine de service d'interruption (ISR) `TIMER1_COMPA_vect`, déclarée avec l'attribut `ISR_NAKED`. Cet attribut indique au compilateur de ne générer aucun code de sauvegarde/restauration automatique (prologue/épilogue), laissant cette responsabilité entièrement au code assembleur intégré dans l'ISR.
Déroulement d'une commutation de contexte (Context Switch) :
- Interruption : Le Timer1 expire, l'exécution courante est suspendue, et le CPU saute au vecteur d'interruption.
- Sauvegarde du Contexte : L'ISR empile manuellement tous les registres (R0-R31) et le registre d'état (SREG) sur la pile de la tâche en cours.
- Sauvegarde du Pointeur de Pile : La valeur actuelle du pointeur de pile matériel (SP) est lue et sauvegardée dans le champ `stack_ptr` du TCB de la tâche courante.
- Appel de l'Ordonnanceur C : La fonction `scheduler_tick_preemptive()` est appelée. Elle :
- Incrémente le temps système (`system_ticks`).
- Met à jour les compteurs de sommeil des tâches `TASK_SLEEPING`. Si un compteur atteint 0, la tâche passe à `TASK_READY`.
- Sélectionne la prochaine tâche à exécuter (`next_task`) en utilisant l'algorithme de choix.
- Met à jour le pointeur global `current_task_ptr` vers le TCB de la nouvelle tâche.
- Restauration du Pointeur de Pile : L'ISR lit la valeur de `stack_ptr` depuis le TCB de la nouvelle tâche et met à jour le pointeur de pile matériel (SP).
- Restauration du Contexte : Les registres (R0-R31, SREG) sont dépilés depuis la pile de la nouvelle tâche.
- Retour d'Interruption (RETI) : L'instruction `reti` dépile le compteur ordinal (PC), transférant ainsi le contrôle à la nouvelle tâche, exactement là où elle s'était arrêtée (ou au début de sa fonction si c'est sa première exécution).
Algorithme de Sélection (Scheduling Policy)
La fonction `get_next_ready_task()` implémente la politique de choix de la prochaine tâche :
- Elle parcourt le tableau des tâches `task_table` de manière circulaire (Round-Robin), en commençant après la tâche courante.
- Elle cherche la première tâche valide (fonction non nulle) dont l'état est `TASK_READY`.
- Si aucune autre tâche n'est prête, elle sélectionne la tâche "Idle" (toujours prête, priorité 0).
- Gestion des Priorités : Bien que l'implémentation actuelle soit un Round-Robin simple, la structure permet d'évoluer vers une sélection stricte par priorité (exécuter la tâche prête de plus haute priorité). Dans la version actuelle, l'ordre dans le tableau et le parcours séquentiel offrent un partage du temps simple.
Tâche Idle
Le système crée toujours une tâche spéciale nommée "idle" au démarrage. Cette tâche a la priorité la plus basse et ne fait rien (boucle infinie `while(1);`). Elle garantit qu'il y a toujours au moins une tâche prête à exécuter, évitant ainsi un plantage de l'ordonnanceur si toutes les tâches utilisateur sont endormies ou bloquées.
Gestion de la Mémoire et PROGMEM
L'ATmega328p ne dispose que de **2048 octets de RAM**. Avec un système de fichiers et un shell, la saturation mémoire est le principal danger.
Stratégies d'optimisation :
- **Chaînes en Flash (PROGMEM) :** Tous les noms de tâches et les chaînes de caractères du Shell sont stockés en mémoire programme (Flash) pour épargner la RAM. Les fonctions comme `pgm_read_word` sont utilisées pour y accéder.
- **Buffer Partagé :** Le pilote FAT16 utilise un unique buffer de 512 octets (`shared_buffer`) pour toutes les opérations (lecture MBR, FAT, Répertoire, Données), au lieu d'allouer plusieurs tampons.
- **Piles Ajustées :** Chaque tâche possède une taille de pile spécifique définie à la création (`blink`: 64o, `shell`: 384o).
Système de Fichiers (FAT16)
Le pilote FAT16 a été écrit à la main pour supporter les opérations de lecture et d'écriture tout en minimisant l'empreinte mémoire.
Fonctionnalités
- **Montage Dynamique :** Détection automatique du Master Boot Record (MBR) ou du format Superfloppy.
- **Allocation Réelle :** Recherche de clusters libres dans la FAT pour l'écriture.
- **Mise à jour Miroir :** Écriture simultanée dans `FAT1` et `FAT2` pour assurer la compatibilité avec Linux/Windows (évite les erreurs "Read-only file system").
- **Noms 8.3 :** Conversion automatique des noms de fichiers (ex: `test.txt` → `TEST TXT`).
Écriture de Fichier (Create)
La fonction `fat16_create_file` effectue les opérations suivantes :
- Scanne la FAT pour trouver un cluster libre (marqué `0x0000`).
- Scanne le répertoire racine pour trouver une entrée libre.
- Écrit les métadonnées du fichier (Nom, Taille, Cluster de départ) dans le répertoire.
- Écrit le contenu du fichier dans le secteur de données correspondant.
- Met à jour la FAT pour marquer le cluster comme "Fin de fichier" (`0xFFFF`).
Pilotes Matériels (Drivers)
SPI Atomique
Le pilote SPI (`spi_bitbang.c`) est critique dans un système préemptif.
- **Problème :** Si l'ordonnanceur interrompt l'envoi d'un octet SPI, l'horloge (SCK) peut rester à l'état haut/bas pendant 10ms. Certaines cartes SD interprètent cela comme un timeout ou une erreur.
- **Solution :** Utilisation de blocs atomiques. Les interruptions sont désactivées (`cli()`) juste avant d'envoyer les 8 bits d'un octet, et réactivées (`SREG = sreg`) immédiatement après.
uint8_t spi_transfer(uint8_t data) {
uint8_t sreg = SREG;
cli(); // DÉBUT SECTION CRITIQUE
// Bit-banging rapide (quelques microsecondes)
for (int i=7; i>=0; i--) { ... }
SREG = sreg; // FIN SECTION CRITIQUE
return received;
}
Shell et Scripting
Le Shell (`shell_core.c`) permet l'interaction utilisateur. Il supporte l'exécution de scripts via la commande `exec`.
Commande EXEC : La commande `exec SCRIPT.TXT` :
- Utilise `fat16_read_to_buffer` pour charger le contenu du fichier texte dans la RAM.
- Passe ce buffer à l'interpréteur de commandes `shell_process_line`.
- Cela permet d'automatiser des séquences de démarrage ou de test.
Guide d'utilisation
Commandes disponibles
| Commande | Description |
|---|---|
| `ps` | Affiche la liste des tâches, leur état et l'utilisation CPU. |
| `list` | Affiche les fichiers présents sur la carte SD avec leur taille. |
| `type <fichier>` | Affiche le contenu d'un fichier texte. |
| `create <nom> <txt>` | Crée un nouveau fichier contenant le texte spécifié. |
| `del <nom>` | Supprime un fichier (marque comme supprimé). |
| `exec <script>` | Exécute le contenu d'un fichier comme une commande. |
| `free` | Affiche une estimation de la RAM libre. |
| `reboot` | Redémarre le microcontrôleur. |
Exemple de Session
Pico> create auto.bat version Fichier cree. Pico> exec auto.bat Exec: auto.bat Run: version Pico-OS v1.2 (Dual FAT + Exec)
FPGA
Controleur bus SPI
Cette partie consiste à réaliser une interface SPI en mode 1 sur une carte FPGA Basys 3, configurée en tant qu’esclave. La communication est gérée à l’aide d’une machine à états finis (FSM) en VHDL, permettant de synchroniser et traiter correctement les signaux du protocole SPI.
Le maître SPI est un microcontrôleur ATmega328p, configuré pour transmettre en mode 1. Les données envoyées au microcontrôleur via l’UART (à partir d’un terminal Minicom) sont ensuite transférées vers la Basys 3 par le bus SPI.
Pour la visualisation, chaque octet reçu par l’esclave FPGA est affiché directement sur 8 LED de la carte. Les LED se mettent automatiquement à jour à chaque réception d’un nouvel octet.
Fonctionnement global du bus SPI
Le protocole SPI repose sur 4 signaux :
- MOSI : Master Out Slave In
- MISO : Master In Slave Out
- SCK : Serial Clock
- SS : Slave Slect
Déroulement d’une communication SPI
- Le maître active l'esclave en mettant la ligne SS à l'état bas.
- L'horloge SCK se met à osciller et chaque front d'horloge permet la transmission d'un bit.
- Envoie des données :
- Le maître envoie un bit sur MOSI
- L'esclave repond sur MISO
- Une fois la communication terminée, le maître désactive l'esclave en mettant SS à l'état haut.
Modes SPI
SPI comporte 4 modes, définis par la polarité et la phase de l’horloge (CPOL et CPHA). Ces paramètres déterminent les instants où les données sont valides.
En mode 1, la configuration du bus SPI est la suivante :
- CPOL = 0 : horloge au niveau bas au repos
- CPHA = 1 :
- Setup sur le front montant
- Sample sur le front descendant
Programmation VHDL
La conception du bus SPI repose sur une machine a états finis (FSM) qui gère les différentes phases de la communication :
- Idle : Attente de l'activation de la ligne SS
- Load : Détecte des fronts montants d'horloge et valide l'octet reçu
- Read : Recopie l'état du MOSI dans le registre de data reçu
- Write : Recopie l'état du MOSI sur le MISO (Pour débuger via minicom)
- Wait_next : Réinitialise le compteur de bit à 0 et attend le prochain frond montant d'horloge ou la fin de la communication SS a l'état bas
Démonstration & Code
https://gitea.plil.fr/bcheklat/SE4-Pico-B2/src/branch/main/SPI_BUS
Contrôleur d'écran VGA
Le contrôleur d’écran VGA a pour objectif d’assurer l’affichage graphique des données reçues via le bus SPI sur un écran VGA connecté à la carte FPGA Basys 3.
Les caractères envoyés par le microcontrôleur (via UART puis SPI) sont interprétés, convertis en bitmaps et stockés dans une mémoire vidéo interne, dont le contenu est balayé en continu par le contrôleur VGA.
L’architecture permet l’affichage de texte en temps réel, avec gestion de l’écriture, de l’effacement et du nettoyage complet de l’écran.
Architecture globale
Le contrôleur VGA est composé des blocs suivants :
- Générateur d’horloge vidéo
- Contrôleur de timing VGA
- Mémoire vidéo (RAM)
- ROM de caractères
- Décodeur de commandes ASCII
- Interface SPI esclave
Génération de l’horloge vidéo
La carte Basys 3 fournit une horloge principale à 100 MHz.
Un bloc Clock Wizard est utilisé afin de générer une horloge adaptée au timing VGA (65Mhz).
Timing VGA et balayage de l’écran
Le contrôleur VGA repose sur deux compteurs :
- Compteur horizontal
x_pixel_counter - Compteur vertical
y_pixel_counter
Ces compteurs définissent la position courante du pixel à afficher.
Le timing est conforme à une résolution 1024 × 768 à 60 Hz, incluant :
- zone visible
- front porch
- impulsions de synchronisation
- back porch
Les signaux :
- HS (Horizontal Sync)
- VS (Vertical Sync)
sont générés directement à partir des valeurs des compteurs, conformément aux spécifications VGA.
Zone d’affichage utile
L’affichage du contenu graphique est centré à l’écran grâce à l’utilisation d’offsets
offset_x = 352offset_y = 272
La zone utile correspond à une surface de 320 × 224 pixels, utilisée pour l’affichage du texte.
En dehors de cette zone, les signaux RGB sont forcés à zéro afin d’obtenir un fond noir.
Mémoire vidéo (RAM)
La mémoire vidéo est implémentée sous forme d’une RAM interne de 8960 octets (40 × 224), chaque octet représentant 8 pixels horizontaux.
- Écriture : pilotée par le décodeur de commandes
- Lecture : réalisée en continu par le contrôleur VGA
L’adresse de lecture est calculée à partir de la position du pixel courant :
adresse = (y_pixel × 40) + (x_pixel / 8)
Chaque bit de l’octet lu correspond à l’état d’un pixel (1 = pixel allumé, 0 = pixel éteint).
ROM de caractères
La ROM contient les bitmaps des caractères ASCII sous forme de matrices 8 × 8 pixels.
Chaque caractère est défini par :
- un index ASCII
- un sous-index correspondant à la ligne du caractère (0 à 7)
Cette ROM permet de convertir les caractères reçus via SPI en données graphiques exploitables par la RAM vidéo.
Décodeur de commandes
Le décodeur reçoit les caractères ASCII transmis par le bus SPI et gère leur affichage à l’écran. Fonctionnalités prises en charge :
- écriture séquentielle des caractères
- retour à la ligne automatique
- suppression du dernier caractère (Backspace)
- effacement complet de l’écran (Delete)
Le décodeur traduit chaque caractère en :
- adresses mémoire
- indices de caractères
- signaux de contrôle d’écriture
Chaque caractère est converti en 8 lignes de pixels, stockées consécutivement en mémoire vidéo.
Génération des signaux RGB
Pour chaque pixel situé dans la zone visible :
- le bit correspondant est extrait de l’octet lu en mémoire
- ce bit est appliqué simultanément aux sorties R, G et B
L’affichage est donc réalisé en monochrome, avec des pixels blancs sur fond noir.
Synchronisation avec le bus SPI
Le contrôleur VGA fonctionne indépendamment du bus SPI.
Les données reçues via SPI sont traitées par le décodeur, qui met à jour la mémoire vidéo sans interrompre le balayage de l’écran.
Démonstration & Code
Démonstration contrôleur d’écran VGA
https://gitea.plil.fr/bcheklat/SE4-Pico-B2/src/branch/main/vga
Bitcoin Miner
Objectif du projet : Développer un système complet de minage Bitcoin sur carte FPGA Zybo Z7-10 en exploitant l'architecture (Processeur + FPGA).
Architecture du système
Partie Processeur (ARM Cortex-A9) :
- Implémentation d'un "Mining client" en C
- Connexion réseau aux serveurs de minage
- Récupération et décodage des "jobs" de minage
- Configuration des registres FPGA via le bus AXI
- Transmission des résultats valides au serveur
Partie FPGA :
- Accélérateur matériel SHA-256 optimisé
- Calcul massivement parallèle des nonces
- Interface de contrôle via registres mémoire-mappés
- Signalisation par interruption au processeur
Fonctionnement :
- Le processeur se connecte au "Mining pool server" et reçoit un bloc de travail
- Le processeur extrait l'en-tête de bloc (80 octets) et le prépare pour le FPGA
- Transfert des données vers le FPGA via le bus AXI et démarrage du calcul
- Le FPGA signale immédiatement toute solution valide (hash < cible)
- Le processeur soumet la solution au réseau Bitcoin
Première implémentation d'un coeur SHA256
dans un premier temps j'ai conçu et implémenté un accélérateur matériel SHA-256 en VHDL pour optimiser les calculs de hachage nécessaires au minage de Bitcoin.
Architecture du coeur SHA-256 :
- Signal
startpour lancer le calcul,donepour indiquer la fin, et bus de sortie 256 bits pour le hash. - Exécute les 64 tours de compression SHA-256 en 64 cycles d'horloge
- Utilise des opérations bit-à-bit parallèles pour maximiser la vitesse
Fonctionnement algorithmique :
- Charge les constantes initiales H₀ à H₇, K0{256} à K63{256} définies par la norme SHA-256.
- Génère les 64 mots W[t] à partir du bloc de message de 512 bits
- Applique les fonctions logiques SHA-256 (Ch, Maj, Σ₀, Σ₁) sur 64 tours
- Additionne les valeurs intermédiaires pour produire le hash final
Fonctions cryptographiques implémentées :
Ch(x, y, z) = (x ∧ y) ⊕ (¬x ∧ z)Maj(x, y, z) = (x ∧ y) ⊕ (x ∧ z) ⊕ (y ∧ z)Σ₀{256}(x) = ROTR2(x) ⊕ ROTR13(x) ⊕ ROTR22(x)Σ₁{256}(x)= ROTR6(x) ⊕ ROTR11(x) ⊕ ROTR25(x)σ₀{256}(x) = ROTR7(x) ⊕ ROTR18(x) ⊕ SHR3(x)σ₁{256}(x) = ROTR17(x) ⊕ ROTR19(x) ⊕ SHR10(x)
Simulation
On obtient bien le SHA-256 correspondant au message en 645 ns, ce qui correspond à 64 cycles d’horloge, en démarrant avec une période de 5 ns.

