Maître Wishbone générique

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:

            WbMasterFsm (
                  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 wb_read_at  (
                  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:

            void     wb_write_at (
                  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:

            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
                  );
  • 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:

            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
                  );
  • 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:
DummyWbMaster (sc_module_name name ) : ...
      master0(p_clk,p_wb)
  • Faire des requêtes dans un SC_THREAD du module SystemC:
// É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.