两路组相联cache

cache代码

`timescale 1ns / 1ps

//cache共32块,分为16组,每组2块,即两路组相联,1块=4字,1字=4字节
//主存共1024块,4096个字
//主存地址共12位,[1:0]为块内偏移,[5:2]为组地址,[11:6]为Tag
//V、D、Tag、Data=1+1+6+128=136

module cache(
input clk,
input rst,
//cpu<->cache
input [11:0]cpu_req_addr,
input cpu_req_valid,
input cpu_req_rw,
input [31:0]cpu_data_write,
output reg [31:0]cpu_data_read,
output reg cpu_ready,
//cache<->main memory
output reg [11:0]mem_req_addr,
output reg mem_req_rw,
output reg mem_req_valid,
output reg [127:0]mem_data_write,
input [127:0]mem_data_read,
input mem_ready
    );

parameter IDLE=0;
parameter CompareTag=1;
parameter Allocate=2;
parameter WriteBack=3;

parameter V=135;
parameter D=134;
parameter TagMSB=133;
parameter TagLSB=128;
parameter BlockMSB=127;
parameter BlockLSB=0;

reg [135:0] cache_data [0:31];
reg [1:0]state,next_state;
reg hit;
reg hit1,hit2;
reg way;                               //若hit,则way无意义,若miss,则way表示分配的那一路

wire [3:0]cpu_req_index;
wire [5:0]cpu_req_tag;
wire [1:0]cpu_req_offset;

assign cpu_req_offset=cpu_req_addr[1:0];
assign cpu_req_index=cpu_req_addr[5:2];
assign cpu_req_tag=cpu_req_addr[11:6];

integer i;
//初始化cache
initial
begin
    for(i=0;i<32;i=i+1)
        cache_data[i]=136'd0;
end
//
always@(posedge clk,posedge rst)
if(rst)
    state<=IDLE;
else
    state<=next_state;
//state change
always@(*)
case(state)
    IDLE:if(cpu_req_valid)
            next_state=CompareTag;
         else
            next_state=IDLE;
    CompareTag:if(hit)                     //若hit
                  next_state=IDLE;
               else if(cache_data[2*cpu_req_index+way][V:D]==2'b11) //被分配的块有效且脏,则先写回主存
                  next_state=WriteBack;
               else
                  next_state=Allocate;
    Allocate:if(mem_ready)
                  next_state=CompareTag;
             else
                  next_state=Allocate;
    WriteBack:if(mem_ready)
                  next_state=Allocate;
              else
                  next_state=WriteBack;
    default:next_state=IDLE;
endcase
//hit1
always@(*)
if(state==CompareTag)
    if(cache_data[2*cpu_req_index][V]==1'b1&&cache_data[2*cpu_req_index][TagMSB:TagLSB]==cpu_req_tag)
        hit1=1'b1;
    else
        hit1=1'b0;
else
    hit1=1'b0;
//hit2
always@(*)
if(state==CompareTag)
    if(cache_data[2*cpu_req_index+1][V]==1'b1&&cache_data[2*cpu_req_index+1][TagMSB:TagLSB]==cpu_req_tag)
        hit2=1'b1;
    else
        hit2=1'b0;
else
    hit2=1'b0;
//hit
always@(*)
if(state==CompareTag)
    hit=hit1||hit2;
else
    hit=1'b0;
//way       cache miss 时分配的块在组内的位置
always@(*)
if((state==CompareTag)&&(hit==1'b0))   //未命中
    case({
     cache_data[2*cpu_req_index][V],cache_data[2*cpu_req_index+1][V]})
        2'b01:way=1'b0;                    //第0路可用
        2'b10:way=1'b1;                    //第1路可用
        2'b00:way=1'b0;                    //第0、1路均可用
        2'b11:way=1'b0;                    //第0、1路均不可用,默认替换第0路
        default:way=1'b0;
    endcase

//CompareTag
always@(posedge clk)
if(state==CompareTag&&hit)
    if(cpu_req_rw==1'b0)                        //read hit
    begin
        cpu_ready<=1'b1;
        if(hit1)
            cpu_data_read<=cache_data[2*cpu_req_index][32*cpu_req_offset +:32];
        else
            cpu_data_read<=cache_data[2*cpu_req_index+1][32*cpu_req_offset +:32];
    end
    else                                       //write hit
    begin
        cpu_ready<=1'b1;
        if(hit1) 
        begin                                
            cache_data[2*cpu_req_index][32*cpu_req_offset +:32]<=cpu_data_write;
            cache_data[2*cpu_req_index][D]<=1'b1;
        end
        else
        begin
            cache_data[2*cpu_req_index+1][32*cpu_req_offset +:32]<=cpu_data_write;
            cache_data[2*cpu_req_index+1][D]<=1'b1;
        end
    end
else
    cpu_ready<=1'b0;
//Allocate and WriteBack
always@(posedge clk)
if(state==Allocate)                            //load new block from memory to cache
    if(!mem_ready)
    begin
        mem_req_valid<=1'b1;
        mem_req_addr<={
     cpu_req_addr[11:2],2'b00};
        mem_req_rw<=1'b0;
    end
    else
    begin
        mem_req_valid<=1'b0;
        cache_data[2*cpu_req_index+way]<={
     2'b10,cpu_req_tag,mem_data_read};
    end
else if(state==WriteBack)                    //write dirty old block to memory
    if(!mem_ready)
    begin
        mem_req_valid<=1'b1;
        mem_req_addr<={
     cache_data[2*cpu_req_index+way][TagMSB:TagLSB],cpu_req_index,2'b00};
        mem_data_write<=cache_data[2*cpu_req_index+way][BlockMSB:BlockLSB];
        mem_req_rw<=1'b1;                 
    end
    else
    begin
        mem_req_valid<=1'b0;
    end
else
   mem_req_valid<=1'b0;

endmodule

mem代码

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/08/20 14:24:27
// Design Name: 
// Module Name: mem
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module mem(
input clk,
input rst,
input [11:0]mem_req_addr,                        //[1:0]块内地址
input mem_req_rw,
input mem_req_valid,
input [127:0]mem_data_write,
output reg [127:0]mem_data_read,
output reg mem_ready
    );

reg [31:0] mem [0:4095];                 //4096个字,1024个块

integer i;
initial
begin
    for(i=0;i<4096;i=i+1)
        mem[i]=32'd0;
end

always@(posedge clk,posedge rst)
if(rst)
    mem_ready<=1'b0;
else if(mem_req_valid&&mem_req_rw==1'b1&&!mem_ready)                      //write
begin
    mem[mem_req_addr+3]=mem_data_write[127:96];
    mem[mem_req_addr+2]=mem_data_write[95:64];
    mem[mem_req_addr+1]=mem_data_write[63:32];
    mem[mem_req_addr]=mem_data_write[31:0];
    mem_ready<=1'b1;
end
else if(mem_req_valid&&mem_req_rw==1'b0&&!mem_ready)                      //read
begin
    mem_data_read={
     mem[mem_req_addr+3],mem[mem_req_addr+2],mem[mem_req_addr+1],mem[mem_req_addr]};
    mem_ready<=1'b1;
end
else if(mem_req_valid&&mem_ready)
    mem_ready<=1'b0;

endmodule


仿真文件

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/08/20 15:25:17
// Design Name: 
// Module Name: test
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module test(

    );

parameter Write1=0;
parameter Write2=1;
parameter Write3=2;
parameter Write4=3;
parameter Read1=4;
parameter Read2=5;
parameter Read3=6;
parameter Read4=7;

reg clk;
reg rst;

reg [3:0]state,next_state;

reg [11:0]cpu_req_addr;
reg cpu_req_rw;
reg cpu_req_valid;
reg [31:0]cpu_data_write;
wire [31:0]cpu_data_read;
wire cpu_ready;

wire [11:0]mem_req_addr;
wire mem_req_rw;
wire mem_req_valid;
wire [127:0]mem_data_write;
wire [127:0]mem_data_read;
wire mem_ready;

initial
begin
    clk=0;
    forever
    #5 clk=~clk;
end
initial
begin
    rst=1;
    #10
    rst=0;
end

always@(posedge clk,posedge rst)
if(rst)
   state<=Write1;
else
   state<=next_state;

always@(*)
case(state)
    Write1:if(cpu_ready)
           begin
               next_state=Write2;
               cpu_req_valid=1'b0;
           end
           else
               next_state=Write1;
    Write2:if(cpu_ready)
           begin
                next_state=Write3;
                cpu_req_valid=1'b0;
           end
           else
                next_state=Write2;
    Write3:if(cpu_ready)
           begin
                next_state=Write4;
                cpu_req_valid=1'b0;
           end
           else
                next_state=Write3;
    Write4:if(cpu_ready)
           begin
                next_state=Read1;
                cpu_req_valid=1'b0;
           end
            else
                next_state=Write4;
    Read1:if(cpu_ready)
          begin
              next_state=Read2;
              cpu_req_valid=1'b0;
          end
          else
              next_state=Read1;
    Read2:if(cpu_ready)
          begin
              next_state=Read3;
              cpu_req_valid=1'b0;
          end
          else
              next_state=Read2;
    Read3:if(cpu_ready)
          begin
              next_state=Read4;
              cpu_req_valid=1'b0;
          end
          else
              next_state=Read3;
    Read4:next_state=Read4;
    default:next_state=Write1;
endcase

always@(posedge clk,posedge rst)
if(rst)
begin
    cpu_req_valid<=1'b0;
    cpu_req_rw<=1'b0;
    cpu_req_addr<=12'd0;
    cpu_data_write<=32'd0;
end
else 
case(state)
    Write1:begin
        cpu_req_valid<=1'b1;
        cpu_req_rw<=1'b1;
        cpu_req_addr<=12'd0;
        cpu_data_write<=32'd8;
    end
    Write2:begin
        cpu_req_valid<=1'b1;
        cpu_req_rw<=1'b1;
        cpu_req_addr<=12'd64;
        cpu_data_write<=32'd9;
    end
    Write3:begin
        cpu_req_valid<=1'b1;
        cpu_req_rw<=1'b1;
        cpu_req_addr<=12'd128;
        cpu_data_write<=32'd6;
    end
    Write4:begin
        cpu_req_valid<=1'b1;
        cpu_req_rw<=1'b1;
        cpu_req_addr<=12'd65;
        cpu_data_write<=32'd7;
    end
    Read1:begin
        cpu_req_valid<=1'b1;
        cpu_req_rw<=1'b0;
        cpu_req_addr<=12'd0;
    end
    Read2:begin
        cpu_req_valid<=1'b1;
        cpu_req_rw<=1'b0;
        cpu_req_addr<=12'd4;
    end
    Read3:begin
        cpu_req_valid<=1'b1;
        cpu_req_rw<=1'b0;
        cpu_req_addr<=12'd68;
    end
    Read4:begin
        cpu_req_valid<=1'b1;
        cpu_req_rw<=1'b0;
        cpu_req_addr<=12'd65;
    end
    default:begin
        cpu_req_valid<=1'b0;
    end
endcase



cache U1(.clk(clk),
.rst(rst),
.cpu_req_addr(cpu_req_addr),
.cpu_req_rw(cpu_req_rw),
.cpu_req_valid(cpu_req_valid),
.cpu_data_write(cpu_data_write),
.cpu_data_read(cpu_data_read),
.cpu_ready(cpu_ready),
//***********************//
.mem_req_addr(mem_req_addr),
.mem_req_rw(mem_req_rw),
.mem_req_valid(mem_req_valid),
.mem_data_write(mem_data_write),
.mem_data_read(mem_data_read),
.mem_ready(mem_ready));

mem U2(.clk(clk),
.rst(rst),
.mem_req_addr(mem_req_addr),
.mem_req_rw(mem_req_rw),
.mem_req_valid(mem_req_valid),
.mem_data_write(mem_data_write),
.mem_data_read(mem_data_read),
.mem_ready(mem_ready));

endmodule


你可能感兴趣的:(FPGA)