Pour faciliter le développement du modèle de votre SoC, nous vous proposons un module réutilisable permettant de générer des requêtes maitre sur le bus Wishbone.
Ce module peut être ajouté à un module SystemC pour contrôler une interface maitre Wishbone. Il contient ainsi la machine à état permettant de générer des requêtes unitaires ou par bloc de lecture et d'écriture.
Attention vous n'êtes pas obligés d'utiliser systématiquement ce module. Il est parfois plus simple de réécrire la séquence d'une requête Wishbone.
De plus ce module fait appel à des fonction bloquante de SystemC et ne peut donc être utilisé que dans des SC_THREAD
.
Le code de ce module se trouve dans le dossier:
IPs/wb_master_fsm
Constructeur du module:
sc_in<bool> &p_clk,
WbMaster<wb_param> &p_wb
);
Les arguments passés au constructeur sont:
- Un port Wishbone maitre
p_wb
- Un port d'entrée de type booléen
p_clk
correspondant ç l'horloge
Ce module module va manipuler les signaux connectés à un port Wishbone maitre, les arguments sont passé par référence pour pouvoir y accéder directement.
Ce module n'est pas un module SystemC, pour être utilisé, doit d'abord être instancié dans un module SystemC.
Utilisation du module:
Une instancié, vous pouvez initier des requêtes sur le bus en utilisant les méthode suivantes. Les Requêtes se font sur des mots de 32 bits.
Requête de lecture unitaire:
uint32_t addr // 32-bit address
);
- Prend en entrée l'adresse 32 bits du mot à lire
- Retourne un mot de 32 bits non signé
Requête d'écriture unitaire:
uint32_t addr, // 32-bit address
uint8_t mask, // 4-bit mask
uint32_t data // 32-bit data
);
- Prend en entrée:
- l'adresse 32 bits de l'emplacement mémoire à modifier
- le masque correspondant aux octets à modifier (seul les 4 bits de poids faible sont utilisés)
- la donnée à écrire
- La méthode ne retourne rien
Requête de lecture par bloc:
uint32_t saddr, // 32-bit start address
uint32_t num , // number of 32-bit transactions
uint8_t *dest // pointer to the destination byte buffer
);
- Prend en entrée:
- l'adresse 32 bits du début de l'emplacement du bloc à lire
- le nombre de requêtes 32 bits consécutives qui seront faites
- un pointeur vers un tampon pour stocker les données lues
- La méthode ne retourne rien
ATTENTION: dest
doit pointer vers une zone allouée au préalable. La taille de la zone allouée doit être de 4 fois le nombre de requêtes.
Pour être compatible avec l'endianness du LM32, les octets sont stockés dans l'ordre big-endian.
Requête d'écriture par bloc:
uint32_t saddr, // 32-bit start address
uint8_t *mask, // pointer to the data masks
uint8_t *data, // pointer data byte buffer
uint32_t num // number of 32-bit transactions
);
- Prend en entrée:
- l'adresse 32 bits du début de l'emplacement mémoire où le bloc sera écrit
- un pointeur vers un tampon contenant le masque des octets à modifier
- un pointeur vers un tampon contenant les données à écrire
- le nombre de requêtes 32 bits consécutives qui seront faites.
- La méthode ne retourne rien
Remarque Si le pointeur de masque mask
est égal NULL
, tous les masques sont mis à 0xF
. Tous les octets sont donc modifiés.
Exemple d'utilisation:
Un exemple d'utilisation est disponible dans le dossier:
IPs/dummy_wb_master
Voici les principales étapes pour utiliser le module dans l'exemple:
Dans le fichier d'en-tête dummy_wb_master.h
nous avons:
- Déclarer dans le module SystemC:
WbMasterFsm<wb_param> master0;
Dans le fichier d'implémentation dummy_wb_master.cpp
nous avons:
- Lier le module au port Wishbone et au port d'horloge:
master0(p_clk,p_wb)
- Faire des requêtes dans un SC_THREAD du module SystemC:
master0.wb_write_at(0x40000000,0xf,0xC01dCafe);
// Lire la donnée se trouvant à l'adresse 0x40000000
val = master0.wb_read_at(0x40000000);
// Écrire consécutivement 20 mots de 32bits
// DATA pointe vers un buffer contenant au minimum 20x4 octets
// MASK pointe vers les 20 masques correspondants
master0.wb_write_blk(0x40000000,MASK,DATA,20);
// Écrire consécutivement 20 mots de 32bits avec un masque égale à 0xF
master0.wb_write_blk(0x40000000,NULL,DATA,20);
// Lire 20 mots de 32 bits
// Le résultat est stocké dans la zone pointée par RDATA
// RDATA pointe vers une zone pré-allouée pouvant contenir 4x20 octets
// Les octets sont organisés dans l'ordre big-endian
master0.wb_read_blk(0x40000000,20,RDATA)
Pour tester l'ensemble, vous pouvez instancier le module DummyWbMaster
dans votre modèle de SoC et observer, par exemple, les différences entre les requêtes simples et les requêtes par bloc.