RAM avec simulation de cache à mappage direct simple sur FPGA dans Verilog

Simulation de cache à mappage direct simple sur FPGA




Cet article fait partie d'un cours destiné aux étudiants de première année du baccalauréat de l'Université Innopolis. Tout le travail se fait en équipe. Le but de cet article est de montrer une compréhension du sujet, ou d'aider à le comprendre à l'aide de la simulation.




Lien vers le référentiel Git




Le principe de travail mais du côté de l'utilisateur devrait ressembler à:


  • Pour écrire des données en mémoire, vous devez accéder à la RAM avec les données et l'adresse dans lesquelles nous voulons écrire.
  • Pour accéder aux données, nous devons nous adresser au cache. Si le cache ne peut pas trouver les données nécessaires, il accède à la RAM en copiant les données à partir de là.

Lorsque vous travaillez avec Verilog, il faut comprendre que chaque bloc individuel du programme est représenté comme un module. Comme vous le savez, le cache n'est pas une partie indépendante de la mémoire rapide, et pour son bon fonctionnement, il doit prendre des données d'un autre bloc de mémoire - RAM. Par conséquent, afin de simuler le travail du cache au FPGA, nous devons simuler tout le module RAM qui inclut également le cache, mais le point principal est la simulation du cache.


L'implémentation se compose de ces modules:


  • ram.v - module de mémoire RAM
  • cache.v - Module de mémoire cache
  • cache_and_ram.v - module qui fonctionne avec les données et la mémoire.
  • testbench.v et testbench2.v - module pour montrer que les modules principaux fonctionnent parfaitement.

Module RAM:


Code
module ram(); parameter size = 4096; //size of a ram in bits reg [31:0] ram [0:size-1]; //data matrix for ram endmodule 

La description

Le module représente la mémoire utilisée comme RAM. Il dispose de 4096 cellules adressables 32 bits pour stocker certaines données.





Module de cache:


Code
 module cache(); parameter size = 64; // cache size parameter index_size = 6; // index size reg [31:0] cache [0:size - 1]; //registers for the data in cache reg [11 - index_size:0] tag_array [0:size - 1]; // for all tags in cache reg valid_array [0:size - 1]; //0 - there is no data 1 - there is data initial begin: initialization integer i; for (i = 0; i < size; i = i + 1) begin valid_array[i] = 6'b000000; tag_array[i] = 6'b000000; end end endmodule 

La description

Ainsi, le cache contient plus que de simples copies des données
mémoire il a également des bits pour nous aider à trouver des données dans le cache et
vérifier sa validité.





Module cache et RAM:


Code
 module cache_and_ram( input [31:0] address, input [31:0] data, input clk, input mode, //mode equal to 1 when we write and equal to 0 when we read output [31:0] out ); //previous values reg [31:0] prev_address, prev_data; reg prev_mode; reg [31:0] temp_out; reg [cache.index_size - 1:0] index; // for keeping index of current address reg [11 - cache.index_size:0] tag; // for keeping tag of ceurrent address ram ram(); cache cache(); initial begin index = 0; tag = 0; prev_address = 0; prev_data = 0; prev_mode = 0; end always @(posedge clk) begin //check if the new input is updated if (prev_address != address || prev_data != data || prev_mode != mode) begin prev_address = address % ram.size; prev_data = data; prev_mode = mode; tag = prev_address >> cache.index_size; // tag = first bits of address except index ones (In our particular case - 6) index = address % cache.size; // index value = last n (n = size of cache) bits of address if (mode == 1) begin ram.ram[prev_address] = data; //write new data to the relevant cache block if there is such one if (cache.valid_array[index] == 1 && cache.tag_array[index] == tag) cache.cache[index] = data; end else begin //write new data to the relevant cache's block, because the one we addressing to will be possibly addressed one more time soon if (cache.valid_array[index] != 1 || cache.tag_array[index] != tag) begin cache.valid_array[index] = 1; cache.tag_array[index] = tag; cache.cache[index] = ram.ram[prev_address]; end temp_out = cache.cache[index]; end end end assign out = temp_out; endmodule 

La description

Représente les opérations de travail avec les données dans les modules de mémoire. Obtient une entrée sur chaque front positif d'horloge. Vérifie s'il y a de nouvelles entrées - selon le mode (1 pour l'écriture / 0 pour la lecture) exécute les opérations pertinentes. Si le mode est 1 (écriture):
• Écrivez les données à l'adresse puis vérifiez si l'adresse d'entrée existe dans le cache, si c'est le cas - remplacez les données, sinon arrêtez.
Si le mode est 0 (lecture):
• Vérifiez si l'adresse d'entrée existe dans le cache. Si c'est le cas - renvoyez les données, sinon récupérez les données de ram. Actualisez l'adresse dans le cache avec de nouvelles données.


Bancs d'essai:


Code1
 module testbench; reg [31:0] address, data; reg mode, clk; wire [31:0] out; cache_and_ram tb( .address(address), .data(data), .mode(mode), .clk(clk), .out(out) ); initial begin clk = 1'b1; address = 32'b00000000000000000000000000000000; // 0 data = 32'b00000000000000000011100011000000; // 14528 mode = 1'b1; #200 address = 32'b10100111111001011111101111011100; // 2816867292 % size = 3036 data = 32'b00000000000010000000100001010101; // 526421 mode = 1'b1; #200 address = 32'b00000000000011110100011111010001; // 1001425 % size = 2001 data = 32'b00000001100000110001101100010110; // 25369366 mode = 1'b1; #200 address = 32'b10100111111001011111101111011100; // 2816867292 % size = 3036 data = 32'b00000000000000000011100011000000; // 14528 mode = 1'b1; #200 address = 32'b00000000000011110100011111010001; // 1001425 % size = 2001 data = 32'b00000000000000000011100011000000; // 14528 mode = 1'b1; #200 address = 32'b00000000000011110100011111010001; // 1001425 % size = 2001 data = 32'b00000000000000000000000000000000; // 0 mode = 1'b0; #200 address = 32'b10100111111001011111101111011100; // 2816867292 % size = 3036 data = 32'b00000000000000000000000000000000; // 0 mode = 1'b0; #200 address = 32'b00000000000000000000000000000000; // 0 data = 32'b00000000000000000011100011000000; // 14528 mode = 1'b0; end initial $monitor("address = %d data = %d mode = %d out = %d", address % 4096, data, mode, out); always #25 clk = ~clk; endmodule 

Code2
 module testbench2; reg [31:0] address, data; reg mode, clk; wire [31:0] out; cache_and_ram tb( .address(address), .data(data), .mode(mode), .clk(clk), .out(out) ); initial begin clk = 1'b1; address = 32'b00000000000000000000000000000000; // 0 data = 32'b00000000000000000011100011000000; // 14528 mode = 1'b1; #200 address = 32'b10100111111001011111101111011100; // 2816867292 % size = 3036 data = 32'b00000000000010000000100001010101; // 526421 mode = 1'b1; #200 address = 32'b00000000000000000000000000000000; // 0 data = 32'b00000000000000000011100011000000; // 14528 mode = 1'b0; #200 address = 32'b10100111111001011111101111011100; // 2816867292 % size = 3036 data = 32'b00000000000010000000100001010101; // 526421 mode = 1'b0; #200 address = 32'b00000000000011110100011111010001; // 1001425 % size = 2001 data = 32'b00000001100000110001101100010110; // 25369366 mode = 1'b1; #200 address = 32'b00000000000011110100011111010001; // 1001425 % size = 2001 data = 32'b00000001100000110001101100010110; // 25369366 mode = 1'b0; #200 address = 32'b10100111111001011111101111011100; // 2816867292 % size = 3036 data = 32'b00000000000000000011100011000000; // 14528 mode = 1'b1; #200 address = 32'b00000000000011110100011111010001; // 1001425 % size = 2001 data = 32'b00000000000000000011100011000000; // 14528 mode = 1'b1; #200 address = 32'b00000000000011110100011111010001; // 1001425 % size = 2001 data = 32'b00000000000000000000000000000000; // 0 mode = 1'b0; #200 address = 32'b10100111111001011111101111011100; // 2816867292 % size = 3036 data = 32'b00000000000000000000000000000000; // 0 mode = 1'b0; end initial $monitor("address = %d data = %d mode = %d out = %d", address % 4096, data, mode, out); always #25 clk = ~clk; endmodule 

La description

Pour exécuter un banc de test, chargez tous les fichiers dans le projet ModelSim et exécutez une simulation de l'un des fichiers de banc de test.


Source: https://habr.com/ru/post/fr432320/


All Articles