📄 leg_dcache.v
字号:
/////////////////////////////////////////////////////////////////////
//// ////
//// LEG cpu core ////
//// ////
//// This file is part of the LEG FPGA SOC project ////
//// ////
//// ////
//// To Do: ////
//// - make it smaller and faster ////
//// - rewrite the register file and data path ////
//// Author(s): ////
//// - Alex Li, Alexli8055@hotmail.com ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2006-2007 Li datou ////
//// Alexli8055@hotmail.com ////
//// ////
//// ////
//// This source file may be used and distributed freely without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and any derivative work contains the ////
//// original copyright notice and the associated disclaimer. ////
//// ////
//// ARM, the ARM Powered logo, Thumb, and StrongARM are ////
//// registerd trademarks of ARM Limited, this core is simply ////
//// build for fun, please do not use for commerical propose ////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Date of Creation: 2006.11.28 ////
//// ////
//// Version: 0.0.1 ////
//// ////
//// Description ////
//// leg core data cache module. ////
//// ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Change log: ////
//// ////
/////////////////////////////////////////////////////////////////////
`include "leg_define.v"
//very simple instruction cache, need to be refined further
module leg_dcache(
//to cpu
d_address,
d_wait,
d_re,
d_we,
d_datain,
d_dataout,
d_be,
//to coprocessor
dc_control,
//to mem bus
ADR_O,
DAT_I,
DAT_O,
STB_O,
CYC_O,
ACK_I,
SEL_O,
TGD_I,
TGD_O,
WE_O,
//system
clk,
rst
);
parameter IDLE = 4'b0001;
parameter HIT_DETECT = 4'b0010;
parameter RELOAD_1 = 4'b0100;
parameter RELOAD_2 = 4'b1000;
//total 4kB inst cache, implemented in 8 m4k
input [31:0] d_address;
output [31:0] d_dataout;
output d_wait;
input d_re;
input d_we;
input [31:0] d_datain;
input [3:0] d_be;
input dc_control;
//wishbone master interface
output [31:0] ADR_O;
input [31:0] DAT_I; //system data bus is 32 bit
output [31:0] DAT_O;
output [3:0] SEL_O;
output STB_O;
output CYC_O;
input ACK_I;
input [3:0] TGD_I; //DQM IN
output [3:0] TGD_O; //DQM OUT
output WE_O;
input clk;
input rst;
reg d_read_d;
reg [3:0] d_cache_state;
reg [31:0] d_addr_d;
reg [8:0] d_mem_waddr;
wire d_tag_read_hit;
wire d_tag_write_hit;
reg [1:0] send_counter;
reg [1:0] receive_counter;
reg mem_read;
wire receive_valid;
wire d_wait;
reg d_we_d;
reg d_re_d;
reg [03:0] d_be_d;
//
wire [09:0] d_cache_mem_raddr;
wire [31:0] d_cache_mem_rdata;
wire [09:0] d_cache_mem_waddr;
wire [31:0] d_cache_mem_wdata;
wire [3:0] d_cache_mem_we;
wire [07:0] d_cache_tag_raddr;
wire [23:0] d_cache_tag_rdata;
wire [07:0] d_cache_tag_waddr;
wire [23:0] d_cache_tag_wdata;
wire d_cache_tag_we;
wire [03:0] d_cache_line_valid;
wire [03:0] d_cache_tag_word_valid_in;
reg [03:0] write_word_decode;
reg [31:0] d_datain_r;
//total 4k d cache memory
//32 bit address
//31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
//---------------------tag field-----------------------------|--------tag addr--------|line addr|------
//hit or miss
assign d_tag_read_hit = (d_addr_d[31:12] == d_cache_tag_rdata[23:04] && d_cache_line_valid) ? 1'b1 : 1'b0;
assign d_tag_write_hit = (d_addr_d[31:12] == d_cache_tag_rdata[23:04]) ? 1'b1 : 1'b0;
assign d_cache_mem_wdata = (d_we_d)? d_datain_r : DAT_I;
//write through and update the cache memory
assign d_cache_mem_waddr = (d_we_d)? d_addr_d[11:02] : {d_addr_d[11:04],receive_counter};
assign d_cache_mem_raddr = (d_cache_state == HIT_DETECT)? d_address[11:02] : d_addr_d[11:02];
assign d_cache_mem_we = (d_we_d)? d_be_d[3:0] : TGD_I[3:0];
assign receive_valid = (TGD_I)? 1'b1 : 1'b0; //byte write is enable
//for the tag, a write op always update the tag, nomatter it hit or not
//if a write hit, then update the tag (the same) and set the valid flag to cache line
//if a write not hit, then update the tag field and set the valid flag to cache line and disable other three word
assign d_cache_tag_raddr = d_address[11:04];
assign d_cache_tag_waddr = d_addr_d[11:04];
assign d_cache_tag_we = (d_we_d ||(d_cache_state == RELOAD_2))? 1'b1 : 1'b0;
assign d_cache_tag_word_valid_in = (d_cache_state == RELOAD_2)? 4'b1111 : (d_tag_write_hit)? {d_cache_tag_rdata[3:0] | write_word_decode[3:0]} : {write_word_decode}; //if write not hit, then invalid all this cache line except the hit one
assign d_cache_tag_wdata = {d_addr_d[31:12],d_cache_tag_word_valid_in};
assign d_cache_line_valid = (d_addr_d[3:2] == 2'b00 && d_cache_tag_rdata[00] || //first word valid
d_addr_d[3:2] == 2'b01 && d_cache_tag_rdata[01] ||
d_addr_d[3:2] == 2'b10 && d_cache_tag_rdata[02] ||
d_addr_d[3:2] == 2'b11 && d_cache_tag_rdata[03])? 1'b1 : 1'b0;
assign d_dataout = (receive_valid && (receive_counter == d_addr_d[3:2]))? DAT_I : d_cache_mem_rdata;
assign d_wait = ((!d_tag_read_hit && d_cache_state == HIT_DETECT && d_re_d) || d_cache_state == RELOAD_1 || (d_cache_state == RELOAD_2 && receive_counter != 2'b11))? 1'b1 : 1'b0;
//wishbone if
//what if it is a not aligned memory access?
//use the be signal as the byte indicator
assign ADR_O = (d_we)? d_address : {d_addr_d[31:04],send_counter,2'b00};
assign CYC_O = (d_cache_state == RELOAD_1 || d_we)? 1'b1 : 1'b0; //write through op
assign STB_O = (d_cache_state == RELOAD_1 || d_we)? 1'b1 : 1'b0; //write through op
assign SEL_O = d_be; //byte write or word write
assign WE_O = d_we; //write operation
always@(posedge clk or posedge rst)
begin
if (rst) begin
d_read_d <= 1'h0;
d_datain_r <= 32'h0;
end
else begin
d_read_d <= d_re;
d_datain_r <= d_datain;
end
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -