在Verilog中的FPGA上具有简单直接映射缓存仿真的RAM

在FPGA上进行简单的直接映射缓存仿真




本文是Innopolis大学第一年学士课程课程的一部分。 所有工作都在一个团队中完成。 本文的目的是显示对该主题的理解,或通过模拟帮助理解它。




Git存储库链接




但从用户方面来说,工作原理应类似于:


  • 要将任何数据写入内存,您需要使用我们要写入的数据和地址访问RAM。
  • 要访问数据,我们必须要缓存。 如果高速缓存找不到所需的数据,则它通过从那里复制数据来访问RAM。

使用Verilog时,应该理解,程序的每个单独块都表示为一个模块。 如您所知,高速缓存不是快速内存的独立部分,为了使其正常运行,它需要从另一个内存块-RAM中获取数据。 因此,为了在FPGA上模拟缓存的工作,我们必须模拟包括缓存在内的整个RAM模块,但是要点是缓存模拟。


该实现包含以下模块:


  • ram.v-RAM内存模块
  • cache.v-缓存模块
  • cache_and_ram.v-用于数据和内存的模块。
  • testbench.v和testbench2.v-模块,显示主要模块工作正常。

RAM模块:


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

内容描述

模块代表用作RAM的内存。 它具有4096个32位可寻址单元来存储一些数据。





缓存模块:


代号
 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 

内容描述

因此,缓存不仅包含以下数据的副本:
记忆力 它还具有一些位来帮助我们在缓存中查找数据,
验证其有效性。





缓存和RAM模块:


代号
 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 

内容描述

表示处理内存模块中数据的操作。 在每个时钟上升沿获取输入。 检查是否有新的输入-根据模式(写1为读/ 0为读模式)执行相关操作。 如果mode为1(写):
•将数据写入地址,然后检查高速缓存中是否存在输入地址,如果存在-替换数据,否则停止。
如果mode为0(读取):
•检查高速缓存中是否存在输入地址,如果存在-返回数据,否则从ram获取数据。 用新数据刷新缓存中的地址。


测试平台:


代码1
 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 

代码2
 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 

内容描述

要运行测试平台,请将所有文件加载到ModelSim项目中,并运行其中一个测试平台文件的模拟。


Source: https://habr.com/ru/post/zh-CN432320/


All Articles