Pour faciliter le développement du modèle de votre SoC, nous vous proposons un module réutilisable permettant d’initier 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 fonctions bloquantes 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:

WbMasterFsm (
      sc_in<bool>          &p_clk,
      WbMaster<wb_param>   &p_wb
);

Les arguments passés au constructeur sont:

Ce module va manipuler les signaux connectés à un port Wishbone maitre, les arguments sont passés 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 fois instancié, vous pouvez initier des requêtes sur le bus en utilisant les méthodes suivantes. Les Requêtes se font sur des mots de 32 bits.

Requête de lecture unitaire:

uint32_t wb_read_at  (
         uint32_t addr   // 32-bit address
);

Requête d’écriture unitaire:

void  wb_write_at (
      uint32_t addr, // 32-bit address
      uint8_t  mask, // 4-bit mask
      uint32_t data  // 32-bit data
);

Requête de lecture par bloc:

void wb_read_blk (
      uint32_t saddr, // 32-bit start address
      uint32_t num ,  // number of 32-bit transactions
      uint8_t  *dest  // pointer to the destination byte buffer
);

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:

void wb_write_blk (
      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
      );

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:

WbMasterFsm master0;

Dans le fichier d’implémentation dummy_wb_master.cpp nous avons:

DummyWbMaster (sc_module_name name ) : ...
      master0(p_clk,p_wb)
// Écrire 0xC01dCafe à l'adresse 0x40000000 avec le masque d'octets 0xF
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.

Retour au sommaire