OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [branches/] [mp3_stable/] [mp3/] [rtl/] [verilog/] [or1200.xcv/] [dc.v] - Rev 317

Go to most recent revision | Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
////  OR1200's Data Cache top level                               ////
////                                                              ////
////  This file is part of the OpenRISC 1200 project              ////
////  http://www.opencores.org/cores/or1k/                        ////
////                                                              ////
////  Description                                                 ////
////  Instantiation of all DC blocks.                             ////
////                                                              ////
////  To Do:                                                      ////
////   - make it smaller and faster                               ////
////                                                              ////
////  Author(s):                                                  ////
////      - Damjan Lampret, lampret@opencores.org                 ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2000 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.1.1.1  2001/10/06 10:18:35  igorm
// no message
//
// Revision 1.4  2001/08/13 03:36:20  lampret
// Added cfg regs. Moved all defines into one defines.v file. More cleanup.
//
// Revision 1.3  2001/08/09 13:39:33  lampret
// Major clean-up.
//
// Revision 1.2  2001/07/22 03:31:53  lampret
// Fixed RAM's oen bug. Cache bypass under development.
//
// Revision 1.1  2001/07/20 00:46:03  lampret
// Development version of RTL. Libraries are missing.
//
//
 
// synopsys translate_off
`include "timescale.v"
// synopsys translate_on
`include "defines.v"
 
//
// Data cache
//
 
module dc(
	// Rst, clk and clock control
	clk, rst, clkdiv_by_2,
 
	// External i/f
	dcbiu_rdy, dcbiu_datain, dcbiu_dataout, dcbiu_addr, dcbiu_read, dcbiu_write, dcbiu_sel,
 
	// Internal i/f
	dc_en, dclsu_addr, dclsu_lsuop, dclsu_datain, dclsu_dataout, dclsu_stall, dclsu_unstall,
 
	// SPRs
	spr_cs, spr_write, spr_addr, spr_dat_i
);
 
parameter dw = `OPERAND_WIDTH;
 
//
// I/O
//
 
//
// Clock and reset
//
input				clk;
input				rst;
input				clkdiv_by_2;
 
//
// External I/F
//
input				dcbiu_rdy;
input	[dw-1:0]		dcbiu_datain;
output	[31:0]			dcbiu_addr;
output				dcbiu_read;
output				dcbiu_write;
output	[3:0]			dcbiu_sel;
 
//
// Internal I/F
//
input				dc_en;
input	[31:0]			dclsu_addr;
input	[`LSUOP_WIDTH-1:0]	dclsu_lsuop;
input	[dw-1:0]		dclsu_datain;
output	[dw-1:0]		dclsu_dataout;
output	[dw-1:0]		dcbiu_dataout;
output				dclsu_stall;
output				dclsu_unstall;
 
//
// SPR access
//
input				spr_cs;
input				spr_write;
input	[31:0]			spr_addr;
input	[31:0]			spr_dat_i;
 
//
// Internal wires and regs
//
wire				tag_v;
wire	[18:0]			tag;
wire	[dw-1:0]		to_dcram;
wire	[dw-1:0]		from_dcram;
wire	[dw-1:0]		to_mem2reg;
wire	[31:0]			saved_addr;
wire				refill;
wire	[3:0]			dcram_we;
wire				dctag_we;
wire	[dw-1:0]		lsu_datain_memaligned;
wire	[31:0]			dc_addr;
wire				refill_first;
wire				refill_prepare;
wire				refill_start;
wire				refill_rest;
wire	[`LSUOP_WIDTH-1:0]	dcfsm_lsuop;
wire				dcfsm_read;
wire				dcfsm_write;
wire	[1:0] 			mem2reg_addr;
reg				hit;
reg	[1:0]			valid_div;
reg	[3:0]			dcbiu_sel;
reg	[1:0]			bypass_wait;
wire				queue;
wire				cntrbusy;
wire				dcbiu_valid;
wire	[12:4]			dctag_addr;
wire				dctag_en;
wire				dctag_v; 
wire				dc_inv;
 
//
// Simple assignments
//
assign dcbiu_addr = dc_addr;
assign dclsu_unstall = dcbiu_rdy;
assign dc_inv = spr_cs & spr_write;
assign dctag_we = refill | dc_inv;
assign dctag_addr = dc_inv ? spr_dat_i[12:4] : dc_addr[12:4];
assign dctag_en = dc_inv | dc_en;
assign dctag_v = ~dc_inv;
 
//
// Data to BIU is from DCRAM when DC is enabled or from LSU when
// DC is disabled
//
assign dcbiu_dataout = (dc_en) ? from_dcram : lsu_datain_memaligned;
 
//
// Bypases of the DC when DC is disabled
//
assign dcfsm_lsuop = (dc_en) ? dclsu_lsuop : `LSUOP_NOP;
assign dcbiu_read = (dc_en) ? dcfsm_read : ((|dclsu_lsuop) && ~dclsu_lsuop[3]);
assign dcbiu_write = (dc_en) ? dcfsm_write : ((|dclsu_lsuop) && dclsu_lsuop[3]);
always @(dc_en or dclsu_lsuop or dclsu_addr)
	casex({dc_en, dclsu_lsuop, dclsu_addr[1:0]})
		{1'b0, `LSUOP_SB, 2'b00} : dcbiu_sel = 4'b1000;
		{1'b0, `LSUOP_SB, 2'b01} : dcbiu_sel = 4'b0100;
		{1'b0, `LSUOP_SB, 2'b10} : dcbiu_sel = 4'b0010;
		{1'b0, `LSUOP_SB, 2'b11} : dcbiu_sel = 4'b0001;
		{1'b0, `LSUOP_SH, 2'b00} : dcbiu_sel = 4'b1100;
		{1'b0, `LSUOP_SH, 2'b10} : dcbiu_sel = 4'b0011;
		{1'b0, `LSUOP_SW, 2'b00} : dcbiu_sel = 4'b1111;
		{1'b0, `LSUOP_LBZ, 2'b00}, {1'b0, `LSUOP_LBS, 2'b00} : dcbiu_sel = 4'b1000;
		{1'b0, `LSUOP_LBZ, 2'b01}, {1'b0, `LSUOP_LBS, 2'b01} : dcbiu_sel = 4'b0100;
		{1'b0, `LSUOP_LBZ, 2'b10}, {1'b0, `LSUOP_LBS, 2'b10} : dcbiu_sel = 4'b0010;
		{1'b0, `LSUOP_LBZ, 2'b11}, {1'b0, `LSUOP_LBS, 2'b11} : dcbiu_sel = 4'b0001;
		{1'b0, `LSUOP_LHZ, 2'b00}, {1'b0, `LSUOP_LHS, 2'b00} : dcbiu_sel = 4'b1100;
		{1'b0, `LSUOP_LHZ, 2'b10}, {1'b0, `LSUOP_LHS, 2'b10} : dcbiu_sel = 4'b0011;
		{1'b0, `LSUOP_LWZ, 2'b00}, {1'b0, `LSUOP_LWS, 2'b00} : dcbiu_sel = 4'b1111;
		7'b1xxxxxx : dcbiu_sel = 4'b1111;
		default : dcbiu_sel = 4'b0000;
	endcase
 
assign mem2reg_addr = (dc_en) ? saved_addr[1:0] : dclsu_addr[1:0];
 
//
// Wait for DC bypass access
//
always @(posedge rst or posedge clk)
	if (rst)
		bypass_wait <= #1 2'b00;
	else if (dcbiu_valid)
		bypass_wait <= #1 2'b00;
	else if (dcbiu_read | dcbiu_write)
		bypass_wait <= #1 {bypass_wait[0], 1'b1};
	else
		bypass_wait <= #1 2'b00;
 
//
// Queue
//
assign queue = (refill && (|dcfsm_lsuop) && !refill_first && !refill_rest) ? 1'b1 : 1'b0;
 
//
// DC/LSU stall
//
//assign dclsu_stall = refill_start | (refill_first & ~dcbiu_valid)| refill_rest | queue | cntrbusy | (~dc_en & bypass_wait[1] & ~dcbiu_valid);
assign dclsu_stall = refill_start | (refill_first & ~dcbiu_valid)| refill_rest | queue | cntrbusy | (~dc_en & (dcbiu_read | dcbiu_write) & ~dcbiu_rdy);
 
//
// Select between claddr generated by DC FSM and addr[3:2] generated by LSU
//
assign dc_addr = (refill == 1'b1) ? saved_addr : dclsu_addr;
 
//
// Select between input data generated by LSU or by BIU
//
assign to_dcram = (refill == 1'b1) ? dcbiu_datain : lsu_datain_memaligned;
 
//
// Select between data generated by DCRAM or passed by BIU
//
assign to_mem2reg = (refill_first == 1'b1) | (~dc_en) ? dcbiu_datain : from_dcram;
 
//
// Tag comparison
//
always @(tag or saved_addr or tag_v) begin
	if ((tag == saved_addr[31:13]) && tag_v)
		hit = 1'b1;
	else
		hit = 1'b0;
end
 
//
// Valid_div counts RISC clock cycles by modulo 4
//
always @(posedge clk or posedge rst)
        if (rst)
                valid_div <= #1 2'b0;
        else
                valid_div <= #1 valid_div + 'd1;
 
//
// dcbiu_valid is one RISC clock cycle long dcbiu_rdy.
// dcbiu_rdy is two or four RISC clock cycles long because memory
// controller works at 1/2 or 1/4 of RISC clock freq (at 1/2 if
// clkdiv_by_2 is asserted).
//
assign dcbiu_valid = dcbiu_rdy & (valid_div[1] | clkdiv_by_2) & valid_div[0];
 
//
// Generate refill_start that signals to frz_logic a cache linefill is about to begin
//
assign refill_start = (refill_prepare & ~hit) ? 1'b1 : 1'b0;
 
//
// Instantiation of DC Finite State Machine
//
dc_fsm dc_fsm(
	.clk(clk),
	.rst(rst),
	.lsu_op(dcfsm_lsuop),
	.miss(~hit),
	.biudata_valid(dcbiu_valid),
	.start_addr(dclsu_addr),
	.saved_addr(saved_addr),
	.refill(refill),
	.refill_first(refill_first),
	.refill_prepare(refill_prepare),
	.dcram_we(dcram_we),
	.biu_read(dcfsm_read),
	.biu_write(dcfsm_write),
	.refill_rest(refill_rest),
	.cntrbusy(cntrbusy)
);
 
//
// Instantiation of Regfile-to-memory aligner
//
reg2mem reg2mem(
	.addr(dc_addr[1:0]),
	.lsu_op(dclsu_lsuop),
	.regdata(dclsu_datain),
	.memdata(lsu_datain_memaligned)
);
 
//
// Instantiation of DC main memory
//
dc_ram dc_ram(
	.clk(clk),
	.rst(rst),
	.addr(dc_addr[12:2]),
	.en(dc_en),
	.we(dcram_we),
	.datain(to_dcram),
	.dataout(from_dcram)
);
 
//
// Instantiation of DC TAG memory
//
dc_tag dc_tag(
	.clk(clk),
	.rst(rst),
	.addr(dctag_addr),
	.en(dctag_en),
	.we(dctag_we),
	.datain({dc_addr[31:13], dctag_v}),
	.tag_v(tag_v),
	.tag(tag)
);
 
//
// Instatiation of Memory-to-regfile aligner
//
mem2reg mem2reg(
	.addr(mem2reg_addr[1:0]),
	.lsu_op(dclsu_lsuop),
	.memdata(to_mem2reg),
	.regdata(dclsu_dataout)
);
 
endmodule
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.