RAM con simulación de caché de mapeo directo simple en FPGA en Verilog

Simulación de caché de mapeo directo simple en FPGA




Este artículo es parte de un trabajo de curso para estudiantes de primer año de licenciatura de la Universidad de Innopolis. Todo el trabajo se realiza en equipo. El propósito de este artículo es mostrar una comprensión del tema o ayudar a comprenderlo mediante la simulación.




Enlace al repositorio de Git




Principio de trabajo pero desde el lado del usuario debe verse así:


  • Para escribir cualquier dato en la memoria, debe acceder a la RAM con los datos y la dirección en la que queremos escribir.
  • Para acceder a los datos, debemos dirigirnos al caché. Si el caché no puede encontrar los datos necesarios, accede a la RAM copiando los datos desde allí.

Al trabajar con Verilog, debe entenderse que cada bloque individual del programa se representa como un módulo. Como sabe, el caché no es una parte independiente de la memoria rápida, y para su correcto funcionamiento necesita tomar datos de otro bloque de memoria: la RAM. Por lo tanto, para simular el trabajo de la memoria caché en el FPGA, tenemos que simular todo el módulo RAM que también incluye la memoria caché, pero el punto principal es la simulación de la memoria caché.


La implementación consta de tales módulos:


  • ram.v - módulo de memoria RAM
  • cache.v - Módulo de memoria caché
  • cache_and_ram.v: módulo que funciona con datos y memoria.
  • testbench.v y testbench2.v: módulo para mostrar que los módulos principales funcionan perfectamente.

Módulo RAM:


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

Descripción

El módulo representa la memoria que se usa como RAM. Tiene 4096 celdas direccionables de 32 bits para almacenar algunos datos.





Módulo de caché:


Código
 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 

Descripción

Por lo tanto, el caché contiene más que solo copias de los datos en
memoria También tiene bits para ayudarnos a encontrar datos dentro del caché y
verificar su validez





Caché y módulo RAM:


Código
 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 

Descripción

Representa operaciones para trabajar con datos en módulos de memoria. Obtiene la entrada en cada borde positivo del reloj. Comprueba si hay nuevas entradas; según el modo (1 para escritura / 0 para lectura) ejecuta operaciones relevantes. Si el modo es 1 (escribir):
• Escriba los datos en la dirección y luego verifique si la dirección de entrada existe en la memoria caché; en caso afirmativo, reemplace los datos, de lo contrario, deténgase.
Si el modo es 0 (leer):
• Compruebe si la dirección de entrada existe en la memoria caché. Si es así, devuelva los datos, de lo contrario, obtenga los datos de la memoria RAM. Actualice la dirección en el caché con nuevos datos.


Bancos de pruebas:


Código1
 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 

Descripción

Para ejecutar un banco de pruebas, cargue todos los archivos en el proyecto ModelSim y ejecute una simulación de uno de los archivos del banco de pruebas.


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


All Articles