URL
https://opencores.org/ocsvn/or1k_old/or1k_old/trunk
Subversion Repositories or1k_old
[/] [or1k_old/] [branches/] [mp3_stable/] [or1200/] [rtl/] [verilog/] [dc.v] - Rev 1782
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.9 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.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_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_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