URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [branches/] [mp3_stable/] [or1200/] [rtl/] [verilog/] [dc.v] - Rev 168
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.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. // // `include "timescale.v" `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, // Inernal i/f dc_en, dclsu_addr, dclsu_lsuop, dclsu_datain, dclsu_dataout, dclsu_stall, // Trace tp2w ); 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; // // Trace // input [`TP2W_WIDTH-1:0] tp2w; // // Internal wires and regs // 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; // // Simple assignments // assign dcbiu_addr = dc_addr; assign dctag_we = refill; // // 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 <= #1 4'b1000; {1'b0, `LSUOP_SB, 2'b01} : dcbiu_sel <= #1 4'b0100; {1'b0, `LSUOP_SB, 2'b10} : dcbiu_sel <= #1 4'b0010; {1'b0, `LSUOP_SB, 2'b11} : dcbiu_sel <= #1 4'b0001; {1'b0, `LSUOP_SH, 2'b00} : dcbiu_sel <= #1 4'b1100; {1'b0, `LSUOP_SH, 2'b10} : dcbiu_sel <= #1 4'b0011; {1'b0, `LSUOP_SW, 2'b00} : dcbiu_sel <= #1 4'b1111; {1'b0, `LSUOP_LBZ, 2'b00}, {1'b0, `LSUOP_LBS, 2'b00} : dcbiu_sel <= #1 4'b1000; {1'b0, `LSUOP_LBZ, 2'b01}, {1'b0, `LSUOP_LBS, 2'b01} : dcbiu_sel <= #1 4'b0100; {1'b0, `LSUOP_LBZ, 2'b10}, {1'b0, `LSUOP_LBS, 2'b10} : dcbiu_sel <= #1 4'b0010; {1'b0, `LSUOP_LBZ, 2'b11}, {1'b0, `LSUOP_LBS, 2'b11} : dcbiu_sel <= #1 4'b0001; {1'b0, `LSUOP_LHZ, 2'b00}, {1'b0, `LSUOP_LHS, 2'b00} : dcbiu_sel <= #1 4'b1100; {1'b0, `LSUOP_LHZ, 2'b10}, {1'b0, `LSUOP_LHS, 2'b10} : dcbiu_sel <= #1 4'b0011; {1'b0, `LSUOP_LWZ, 2'b00}, {1'b0, `LSUOP_LWS, 2'b00} : dcbiu_sel <= #1 4'b1111; 7'b1xxxxxx : dcbiu_sel <= #1 4'b1111; default : dcbiu_sel <= #1 4'b0000; endcase assign mem2reg_addr = (dc_en) ? saved_addr[1:0] : dclsu_addr[1:0]; // // Wait for DC bypass acess // always @(posedge rst or posedge clk) if (rst) bypass_wait <= #1 2'b0; else if (dcbiu_valid) bypass_wait <= #1 2'b0; else if (dcbiu_read | dcbiu_write) bypass_wait <= #1 {bypass_wait, 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); // // 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) begin if (tag == saved_addr[31:13]) hit <= #1 1'b1; else hit <= #1 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]), .we(dcram_we), .datain(to_dcram), .dataout(from_dcram) ); // // Instantiation of DC TAG memory // dc_tag dc_tag( .clk(clk), .rst(rst), .addr(dc_addr[12:4]), .we(dctag_we), .datain(dc_addr[31:13]), .dataout(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