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

Subversion Repositories or1k

[/] [or1k/] [branches/] [mp3_stable/] [or1200/] [rtl/] [verilog/] [dc_fsm.v] - Rev 1778

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

//////////////////////////////////////////////////////////////////////
////                                                              ////
////  OR1200's DC FSM                                             ////
////                                                              ////
////  This file is part of the OpenRISC 1200 project              ////
////  http://www.opencores.org/cores/or1k/                        ////
////                                                              ////
////  Description                                                 ////
////  Data cache state machine                                    ////
////                                                              ////
////  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.8  2001/10/19 23:28:46  lampret
// Fixed some synthesis warnings. Configured with caches and MMUs.
//
// Revision 1.7  2001/10/14 13:12:09  lampret
// MP3 version.
//
// Revision 1.1.1.1  2001/10/06 10:18:35  igorm
// no message
//
// Revision 1.2  2001/08/09 13:39:33  lampret
// Major clean-up.
//
// 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"
 
`define DCFSM_IDLE	3'd0
`define DCFSM_DOLOAD	3'd1
`define DCFSM_LREFILL3	3'd2
`define DCFSM_DOSTORE	3'd3
`define DCFSM_SREFILL3	3'd4
`define DCFSM_SMEMWR	3'd5
 
//
// Data cache FSM for cache line of 16 bytes (4x singleword)
//
 
module dc_fsm(
	// Clock and reset
	clk, rst,
 
	// Internal i/f to top level DC
	lsu_op, miss, biudata_valid, start_addr, saved_addr,
	refill, refill_first, refill_prepare, dcram_we,
	biu_read, biu_write, refill_rest, cntrbusy
);
 
//
// I/O
//
input				clk;
input				rst;
input				miss;
input				biudata_valid;
input	[31:0]			start_addr;
input	[`LSUOP_WIDTH-1:0]	lsu_op;
output	[31:0]			saved_addr;
output				refill;
output				refill_first;
output				refill_prepare;
output	[3:0]			dcram_we;
output				biu_read;
output				biu_write;
output				refill_rest;
output				cntrbusy;
 
//
// Internal wires and regs
//
wire				dcache_off = 1'b0;
reg	[31:0]			saved_addr;
reg				refill;
reg	[3:0]			dcram_we;
reg	[2:0]			state;
reg	[2:0]			cnt;
reg				refill_first;
reg				refill_prepare;
reg				biu_read;
reg				biu_write;
reg				refill_rest;
reg				cntrbusy;
 
//
// Generation of DCRAM write enable
//
always @(refill_first or refill or biudata_valid or lsu_op or start_addr or biu_write) begin
	if (refill_first || !refill)
		casex({lsu_op, start_addr[1:0]})
			{`LSUOP_SB, 2'b00} : dcram_we = 4'b1000 ^ {4{refill_first}};
			{`LSUOP_SB, 2'b01} : dcram_we = 4'b0100 ^ {4{refill_first}};
			{`LSUOP_SB, 2'b10} : dcram_we = 4'b0010 ^ {4{refill_first}};
			{`LSUOP_SB, 2'b11} : dcram_we = 4'b0001 ^ {4{refill_first}};
			{`LSUOP_SH, 2'b00} : dcram_we = 4'b1100 ^ {4{refill_first}};
			{`LSUOP_SH, 2'b10} : dcram_we = 4'b0011 ^ {4{refill_first}};
			{`LSUOP_SW, 2'b00} : dcram_we = 4'b1111 ^ {4{refill_first}};
			{`LSUOP_LWZ, 2'bxx}, {`LSUOP_LHZ, 2'bxx}, {`LSUOP_LHS, 2'bxx},
			{`LSUOP_LBS, 2'bxx}, {`LSUOP_LBZ, 2'bxx} : dcram_we = 4'b0000 ^ {4{refill_first}};
			default : dcram_we = 4'b0000;
		endcase
	else
		dcram_we = {4{refill & biudata_valid & ~biu_write}};
end
 
//
// Main DC FSM
//
always @(posedge clk or posedge rst) begin
	if (rst) begin
		refill <= #1 1'b0;
		state <= #1 `DCFSM_IDLE;
		cnt <= #1 3'b000;
		refill_first <= #1 1'b0;
		biu_read <= #1 1'b0;
		biu_write <= #1 1'b0;
		saved_addr <= #1 32'b0;
		refill_prepare <= #1 1'b0;
		refill_rest <= #1 1'b0;
		cntrbusy <= #1 1'b0;
	end
	else
	case (state)	// synopsys parallel_case
		`DCFSM_IDLE :
			casex(lsu_op)
				`LSUOP_LBZ, `LSUOP_LBS, `LSUOP_LHZ, `LSUOP_LHS, `LSUOP_LWZ: begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
					$display("%t: DC_FSM Load op %h  start_addr %h", $time, lsu_op, start_addr);
// synopsys translate_on
`endif
					state <= #1 `DCFSM_DOLOAD;
					refill <= #1 1'b0;
					saved_addr <= #1 start_addr;
					refill_first <= #1 1'b0;
					refill_prepare <= #1 1'b1;
					biu_read <= #1 1'b0;
					biu_write <= #1 1'b0;
					refill_rest <= #1 1'b0;
					cntrbusy <= #1 1'b0;
				end
				`LSUOP_SB, `LSUOP_SH, `LSUOP_SW: begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
					$display("%t: DC_FSM Store op %h  start_addr %h", $time, lsu_op, start_addr);
// synopsys translate_on
`endif
					state <= #1 `DCFSM_DOSTORE;
					refill <= #1 1'b0;
					saved_addr <= #1 start_addr;
					refill_first <= #1 1'b0;
					refill_prepare <= #1 1'b1;
					biu_read <= #1 1'b0;
					biu_write <= #1 1'b0;
					refill_rest <= #1 1'b0;
					cntrbusy <= #1 1'b0;
				end
				default: begin
					state <= #1 `DCFSM_IDLE;
					refill <= #1 1'b0;
					refill_first <= #1 1'b0;
					refill_prepare <= #1 1'b0;
					refill_rest <= #1 1'b0;
					biu_read <= #1 1'b0;
					biu_write <= #1 1'b0;
					cntrbusy <= #1 1'b0;
				end
			endcase
		`DCFSM_DOLOAD:
			if (dcache_off) begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
				$display("%t: DC_FSM DCache off", $time);
// synopsys translate_on
`endif
				state <= #1 `DCFSM_DOLOAD;
				refill <= #1 1'b1;
				refill_first <= #1 1'b1;
				refill_prepare <= #1 1'b0;
				refill_rest <= #1 1'b0;
				biu_read <= #1 1'b1;
				if (biudata_valid) begin
					state <= #1 `DCFSM_IDLE;
					refill <= #1 1'b0;
					refill_first <= #1 1'b0;
					biu_read <= #1 1'b0;
					saved_addr <= #1 start_addr;
				end
			end else
			if (miss) begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
				$display("%t: DC_FSM Load miss", $time);
// synopsys translate_on
`endif
				state <= #1 `DCFSM_LREFILL3;
				refill <= #1 1'b1;
				refill_first <= #1 1'b1;
				refill_prepare <= #1 1'b0;
				cnt <= #1 3'd3;
				biu_read <= #1 1'b1;
			end
			else begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
				$display("%t: DC_FSM Load hit", $time);
// synopsys translate_on
`endif
				state <= #1 `DCFSM_IDLE;
				refill <= #1 1'b0;
				refill_first <= #1 1'b0;
				refill_prepare <= #1 1'b0;
				cntrbusy <= #1 (lsu_op) ? 1'b1 : 1'b0;
			end
		`DCFSM_LREFILL3 : begin
			if (biudata_valid && (|cnt)) begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
				$display("%t: DC_FSM Load refill %d", $time, cnt);
// synopsys translate_on
`endif
				cnt <= #1 cnt - 'd1;
				saved_addr[3:2] <= #1 saved_addr[3:2] + 'd1;
				refill_first <= #1 1'b0;
			end
			else if (biudata_valid) begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
				$display("%t: DC_FSM Load refill end", $time, cnt);
// synopsys translate_on
`endif
				state <= #1 `DCFSM_IDLE;
				refill <= #1 1'b0;
				refill_first <= #1 1'b0;
				biu_read <= #1 1'b0;
				cntrbusy <= #1 (lsu_op) ? 1'b1 : 1'b0;
			end
			refill_rest <= #1 ~refill_first & refill;
		end
		`DCFSM_DOSTORE:
			if (miss) begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
				$display("%t: DC_FSM Store miss", $time);
// synopsys translate_on
`endif
				state <= #1 `DCFSM_SREFILL3;
				refill <= #1 1'b1;
				refill_first <= #1 1'b1;
				refill_prepare <= #1 1'b0;
				cnt <= #1 3'd3;
				biu_read <= #1 1'b1;
			end
			else begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
				$display("%t: DC_FSM Store hit", $time);
// synopsys translate_on
`endif
				state <= #1 `DCFSM_SMEMWR;
				refill <= #1 1'b1;
				refill_first <= #1 1'b0;
				refill_prepare <= #1 1'b0;
				biu_write <= #1 1'b1;
				biu_read <= #1 1'b0;
			end
		`DCFSM_SREFILL3 : begin
			if (biudata_valid && (|cnt)) begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
				$display("%t: DC_FSM Store refill %d", $time, cnt);
// synopsys translate_on
`endif
				cnt <= #1 cnt - 'd1;
				saved_addr[3:2] <= #1 saved_addr[3:2] + 'd1;
				refill_first <= #1 1'b0;
			end
			else if (biudata_valid) begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
				$display("%t: DC_FSM Store refill almost done", $time);
// synopsys translate_on
`endif
				state <= #1 `DCFSM_SMEMWR;
				saved_addr[3:2] <= #1 saved_addr[3:2] + 'd1;
				biu_write <= #1 1'b1;
				biu_read <= #1 1'b0;
			end
			refill_rest <= #1 ~refill_first & refill;
		end
		`DCFSM_SMEMWR :
			if (biudata_valid) begin
`ifdef OR1200_VERBOSE
// synopsys translate_off
				$display("%t: DC_FSM Store refill end (just finished store to external mem)", $time);
// synopsys translate_on
`endif
				state <= #1 `DCFSM_IDLE;
				refill <= #1 1'b0;
				biu_write <= #1 1'b0;
				cntrbusy <= #1 (lsu_op) ? 1'b1 : 1'b0;
			end
	endcase
end
 
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.