Il s'agit d'un pont Wishbone à SPI qui convertit les transactions Wishbone d'un hôte en transactions SPI-Memory. Il peut être utilisé pour cartographier un flash SPI, une EEPROM ou un RAM dans l'espace d'adressage d'un processeur. Le pont fonctionne de manière transparente , donc elle se comporte comme une mémoire de lecture / écriture mappée par la mémoire car elle cache le protocole SPI - au prix de la latence supplémentaire. Par conséquent, le pont prend en charge l'exécution en place (XIP) permettant à un processeur d'accéder directement aux instructions (et à exécuter) des instructions et des données situées dans la mémoire SPI.
Il s'agit d'un autre projet "spin-off" du processeur RISC-V NEORV32. Le pont pourrait être ajouté comme module XIP au processeur un jour.
Caractéristiques clés
Todos / Idées / Aide
Le pont est basé sur un seul fichier VHDL rtl/wb_spi_bridge.vhd . L'entité supérieure est wb_spi_bridge , qui peut être instanciée directement sans avoir besoin de bibliothèques spéciales.
entity wb_spi_bridge is
generic (
SPI_CLK_DIV : positive ; -- clock divider: f(spi_clk_o) = f(clk_i) / 2*SPI_CLK_DIV, min 2
SPI_ABYTES : positive ; -- number of address bytes in SPI protocol, 1..4
SPI_CPHA : std_ulogic ; -- clock phase
SPI_CPOL : std_ulogic ; -- idle polarity
WB_ADDR_BASE : std_ulogic_vector ( 31 downto 0 ); -- module base address, size-aligned
WB_ADDR_SIZE : positive -- module address space in bytes
);
port (
-- wishbone host interface --
wb_clk_i : in std_ulogic ; -- clock
wb_rstn_i : in std_ulogic ; -- reset, async, low-active
wb_srstn_i : in std_ulogic ; -- reset, SYNC, low-active
wb_adr_i : in std_ulogic_vector ( 31 downto 0 ); -- address
wb_dat_i : in std_ulogic_vector ( 31 downto 0 ); -- read data
wb_dat_o : out std_ulogic_vector ( 31 downto 0 ); -- write data
wb_we_i : in std_ulogic ; -- read/write
wb_sel_i : in std_ulogic_vector ( 03 downto 0 ); -- byte enable
wb_stb_i : in std_ulogic ; -- strobe
wb_cyc_i : in std_ulogic ; -- valid cycle
wb_ack_o : out std_ulogic ; -- transfer acknowledge
wb_err_o : out std_ulogic ; -- transfer error
-- SPI device interface --
spi_csn_o : out std_ulogic ; -- chip-select, low-active
spi_clk_o : out std_ulogic ; -- serial clock
spi_data_i : in std_ulogic ; -- device data output
spi_data_o : out std_ulogic -- controller data output
);
end wb_spi_bridge ;L'entité supérieure instancie deux entités en fichier :
wb_spi_bridge_link gère le protocole de mémoire SPI (lire, écrire, enrichir)wb_spi_bridge_phy gère le protocole d'interface périphérique en série réelwb_rstn_i ) et un synchrone ( wb_srstn_i ), qui sont tous deux faibles. La réinitialisation asynchrone est nécessaire pour amener le pont dans un état défini. La réinitialisation synchrone est facultative et peut être utilisée pour réinitialiser le pont à partir de la logique d'application. Attachez cette réinitialisation à 1 si elle n'est pas utilisée.
La configuration spécifique à l'application du pont Wishbone-to-SPI est effectuée en utilisant les génériques de l'entité supérieure.
La fréquence d'horloge SPI est configurée à l'aide du générique SPI_CLK_DIV . Il définit un scalmer qui s'applique à l'entrée d'horloge clk_i pour obtenir l'horloge SPI réelle. L'horloge SPI est définie par f_spi = f_main / (2 * SPI_CLK_DIV) . La valeur minimale autorisée pour l'échelle de l'horloge est 2, ce qui entraîne une vitesse maximale d'horloge SPI de 1/4 de la vitesse d'horloge d'entrée.
Le mode d'horloge réel est configuré via SPI_CPHA et SPI_CPOL . La combinaison de ces deux génériques permet de configurer l'un des quatre modes d'horloge SPI standard. Pour plus d'informations sur les modes d'horloge, consultez l'article SPI Wikipedia.
La taille d'adresse de la mémoire SPI, définie par sa capacité, est configurée par le générique SPI_ABYTES . Les valeurs autorisées sont 1, 2, 3 et 4. La plupart des EEPROM SPI utilisent une taille d'adresse de 16 bits, ce qui résulte en SPI_ABYTES = 2 . De nombreuses souvenirs SPI Flash standard utilisent 24 bits pour l'adresse qui résulte en SPI_ABYTES = 3 .
Le pont utilise seulement trois commandes de mémoire standard. Si les commandes d'une mémoire SPI spécifique sont différentes, vous pouvez les adapter dans le fichier source VHDL:
-- spi memory opcodes -----------------------------------------------------------
constant cmd_write_c : std_ulogic_vector ( 7 downto 0 ) := x"02" ; -- write data
constant cmd_read_c : std_ulogic_vector ( 7 downto 0 ) := x"03" ; -- read data
constant cmd_wren_c : std_ulogic_vector ( 7 downto 0 ) := x"06" ; -- write enable
-- ------------------------------------------------------------------------------ L'adresse de base 32 bits du pont est définie par le générique WB_ADDR_BASE . La taille de l'espace d'adressage occupé, qui est définie la capacité de la mémoire SPI, est configurée par le générique WB_ADDR_SIZE . La taille de l'espace d'adresse doit être une puissance de deux et l'adresse de base doit être naturellement alignée sur cette taille.
Exemple: SPI Flash avec 64KB (64 * 1024 octets):
WB_ADDR_BASE => 0 x"FFFF0000" ,
WB_ADDR_SIZE => 64 * 1024 Dans ce cas, une adresse de base de 0xFFFF8000 serait invalide car elle n'est pas naturellement alignée sur une limite de 64 Ko.
L'interface hôte est basée sur la spécification Wishbone B4. Il prend en charge les transferts à accès unique classiques et pipelins . Le transfert de rafale n'est pas encore pris en charge.
| Exemple d'accès à lecture en mode classique | Exemple d'accès à l'écriture en mode pipeliné |
|---|---|
stb et cyc restent tous les deux affirmés jusqu'à la fin du transfert.cyc reste affirmé jusqu'à la fin du transfert. stb n'est affirmé que pour un cycle juste au début du transfert. | Un transfert est terminé lorsque l' ack du signal de reconnaissance est défini (actif pour un cycle). Cela indique une résiliation réussie. Un transfert est également terminé lorsque l' err du signal d'erreur est définie (active pour un cycle) indiquant une terminaison erronée. Le pont ne soulèvera le signal d'erreur que si un masque d'octet non pris en charge est défini (voir ci-dessous).
Le pont prend en charge les accès en écriture 32 bits, 16 bits et 8 bits. Les accès à lire renvoient toujours un mot complet 32 bits. Notez que le pont accède aux données de mémoire dans l'ordre d'octets Little-Endan . Le signal du masque d'octet sel définit la quantité de données de l'accès selon. Les masques d'octets suivants sont pris en charge:
sel | r / w | Quantité de données |
|---|---|---|
1111 | lire | Mot complet 32 bits |
1111 | écrire | Mot complet 32 bits |
1100 | écrire | demi-mot supérieur |
0011 | écrire | demi-mot inférieur |
0001 | écrire | octet 0 |
0010 | écrire | octet 1 |
0100 | écrire | octet 2 |
1000 | écrire | octet 3 |
Toute la combinaison du masque d'octets restantes augmentera une erreur de transfert ( err est défini pour un cycle au lieu de ack ).
Le pont envoie toujours une séquence de commandes complète à la mémoire SPI pour tout type de transfert de souhaits (les rafales ne sont pas encore prises en charge). Cela signifie que l'opcode de mémoire, les bits d'adresse et les données réelles sont transférées pour chaque transaction. Le tableau suivant montre le nombre de bit à transférer via SPI pour chaque type de transaction. Chaque bit nécessite une horloge de l'horloge SPI.
| r / w | Taille des données | Bits cmd | Adresses Bits | Bits de données | Total des bits |
|---|---|---|---|---|---|
| lire | Word (32 bits) | 8 | 8*SPI_ABYTES | 32 | 8 + 8*SPI_ABYTES + 32 |
| écrire | Word (32 bits) | 8 + 8 | 8*SPI_ABYTES | 32 | 8 + 8 + 8*SPI_ABYTES + 32 |
| écrire | demi-mot (16 bits) | 8 + 8 | 8*SPI_ABYTES | 16 | 8 + 8 + 8*SPI_ABYTES + 16 |
| écrire | octet (8 bits) | 8 + 8 | 8*SPI_ABYTES | 8 | 8 + 8 + 8*SPI_ABYTES + 8 |
Par exemple, un accès en écriture à l'échelle du mot à un flash SPI qui utilise une adresse 24 bits nécessite 8 + 8 + 8*3 + 32 = 72 cycles d'horloge SPI. Un cycle d'horloge SPI équivaut à 2 * SPI_CLK_DIV de l'horloge principale clk_i .
Tout type d'accès en écriture nécessite de définir le verrou d'activation de la mémoire, qui est fait d'envoi d'une seule commande 8 bits.
Les projets fournissent un test simple sim/wb_spi_bridge_tb.vhd , qui peut être simulé par GHDL via le script fourni:
wb_spi_bridge/sim$ sh ghdl.sh La simulation fonctionnera sur 1 ms à l'aide d'une horloge de 100 MHz. Pendant ce temps, tous les accès aux triangles pris en charge (et un illégaux) sont déclenchés. Notez que ce banc d'essai est destiné à l'inspection manuelle des formes d'onde - il ne s'agit pas d'auto-vérification! Les données de forme d'onde sont stockées sur sim/wb_spi_bridge.vcd , qui peuvent être visualisées à l'aide de gtkwave :
wb_spi_bridge/sim$ gtkwave wb_spi_bridge.vcdLe pont est prouvé par le FPGA . Il a été testé en le connectant directement au port d'interface Wishbone du processeur RISC-V NEORV32 (pas d'interconnexion Wishbone) interfaçant une EEPROM SPI 25LC512.
Les exemples de logiciels NEORV32 fournissent un programme "Explorateur de bus" qui permet d'effectuer des accès arbitraires à Wismbone via un terminal UART. Le pont peut gérer avec succès toutes les opérations de lecture et d'écriture. De plus, le NEORV32 peut exécuter avec succès les programmes en place du module SPI.
Résultats de cartographie exemplaire pour la configuration suivante:
SPI_CLK_DIV => 32 ,
SPI_ABYTES => 2 , -- 16-bit addressing
SPI_CPHA => '0' ,
SPI_CPOL => '0' , -- clock mode 0
WB_ADDR_BASE => x"F0000000" ,
WB_ADDR_SIZE => 64 * 1024 EP4CE22F17C6N @ 100MHz Hierarchy Logic Cells Logic Registers
----------------------------------------------------------------------------
wb_spi_bridge:wb_spi_bridge_inst 233 (115) 174 (88)
wb_spi_bridge_link:wb_spi_bridge_link_inst 118 (16) 86 (8)
wb_spi_bridge_phy:wb_spi_bridge_phy_inst 102 (102) 78 (78)