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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1200/] [rtl/] [verilog/] [or1200_dc_fsm.v] - Diff between revs 141 and 258

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 141 Rev 258
Line 1... Line 1...
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
////  OR1200's DC FSM                                             ////
////  OR1200's DC FSM                                             ////
////                                                              ////
////                                                              ////
////  This file is part of the OpenRISC 1200 project              ////
////  This file is part of the OpenRISC 1200 project              ////
////  http://www.opencores.org/cores/or1k/                        ////
////  http://opencores.org/project,or1k                           ////
////                                                              ////
////                                                              ////
////  Description                                                 ////
////  Description                                                 ////
////  Data cache state machine                                    ////
////  Data cache state machine                                    ////
////                                                              ////
////                                                              ////
////  To Do:                                                      ////
////  To Do:                                                      ////
////   - make it smaller and faster                               ////
////   - Test error during line read or write                     ////
////                                                              ////
////                                                              ////
////  Author(s):                                                  ////
////  Author(s):                                                  ////
////      - Damjan Lampret, lampret@opencores.org                 ////
////      - Damjan Lampret, lampret@opencores.org                 ////
 
////      - Julius Baxter, julius@opencores.org                   ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
//// Copyright (C) 2000 Authors and OPENCORES.ORG                 ////
//// Copyright (C) 2000, 2010 Authors and OPENCORES.ORG           ////
////                                                              ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
//// the original copyright notice and the associated disclaimer. ////
Line 39... Line 40...
//// Public License along with this source; if not, download it   ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//
//
// CVS Revision History
 
//
 
// $Log: or1200_dc_fsm.v,v $
// $Log: or1200_dc_fsm.v,v $
// Revision 2.0  2010/06/30 11:00:00  ORSoC
// Revision 2.0  2010/06/30 11:00:00  ORSoC
// Minor update: 
// Minor update: 
// Bugs fixed. 
// Bugs fixed. 
//
//
// Revision 1.9  2004/06/08 18:17:36  lampret
 
// Non-functional changes. Coding style fixes.
 
//
 
// Revision 1.8  2004/04/05 08:29:57  lampret
 
// Merged branch_qmem into main tree.
 
//
 
// Revision 1.7.4.1  2003/07/08 15:36:37  lampret
 
// Added embedded memory QMEM.
 
//
 
// Revision 1.7  2002/03/29 15:16:55  lampret
 
// Some of the warnings fixed.
 
//
 
// Revision 1.6  2002/03/28 19:10:40  lampret
 
// Optimized cache controller FSM.
 
//
 
// Revision 1.1.1.1  2002/03/21 16:55:45  lampret
 
// First import of the "new" XESS XSV environment.
 
//
 
//
 
// Revision 1.5  2002/02/11 04:33:17  lampret
 
// Speed optimizations (removed duplicate _cyc_ and _stb_). Fixed D/IMMU cache-inhibit attr.
 
//
 
// Revision 1.4  2002/02/01 19:56:54  lampret
 
// Fixed combinational loops.
 
//
 
// Revision 1.3  2002/01/28 01:15:59  lampret
 
// Changed 'void' nop-ops instead of insn[0] to use insn[16]. Debug unit stalls the tick timer. Prepared new flag generation for add and and insns. Blocked DC/IC while they are turned off. Fixed I/D MMU SPRs layout except WAYs. TODO: smart IC invalidate, l.j 2 and TLB ways.
 
//
 
// Revision 1.2  2002/01/14 06:18:22  lampret
 
// Fixed mem2reg bug in FAST implementation. Updated debug unit to work with new genpc/if.
 
//
 
// Revision 1.1  2002/01/03 08:16:15  lampret
 
// New prefixes for RTL files, prefixed module names. Updated cache controllers and MMUs.
 
//
 
// Revision 1.9  2001/10/21 17:57:16  lampret
 
// Removed params from generic_XX.v. Added translate_off/on in sprs.v and id.v. Removed spr_addr from dc.v and ic.v. Fixed CR+LF.
 
//
 
// 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
// synopsys translate_off
`include "timescale.v"
`include "timescale.v"
// synopsys translate_on
// synopsys translate_on
`include "or1200_defines.v"
`include "or1200_defines.v"
 
 
`define OR1200_DCFSM_IDLE       3'd0
`define OR1200_DCFSM_IDLE       3'd0
`define OR1200_DCFSM_CLOAD      3'd1
`define OR1200_DCFSM_CLOADSTORE 3'd1
`define OR1200_DCFSM_LREFILL3   3'd2
`define OR1200_DCFSM_LOOP2      3'd2
`define OR1200_DCFSM_CSTORE     3'd3
`define OR1200_DCFSM_LOOP3      3'd3
`define OR1200_DCFSM_SREFILL4   3'd4
`define OR1200_DCFSM_LOOP4      3'd4
 
`define OR1200_DCFSM_FLUSH5     3'd5
 
`define OR1200_DCFSM_INV6       3'd6
 
`define OR1200_DCFSM_WAITSPRCS7 3'd7
 
 
 
 
 
 
//
//
// Data cache FSM for cache line of 16 bytes (4x singleword)
// Data cache FSM for cache line of 16 bytes (4x singleword)
//
//
 
 
module or1200_dc_fsm(
module or1200_dc_fsm
 
  (
        // Clock and reset
        // Clock and reset
        clk, rst,
        clk, rst,
 
 
        // Internal i/f to top level DC
        // Internal i/f to top level DC
        dc_en, dcqmem_cycstb_i, dcqmem_ci_i, dcqmem_we_i, dcqmem_sel_i,
        dc_en, dcqmem_cycstb_i, dcqmem_ci_i, dcqmem_we_i, dcqmem_sel_i,
        tagcomp_miss, biudata_valid, biudata_error, start_addr, saved_addr,
   tagcomp_miss, biudata_valid, biudata_error, lsu_addr,
        dcram_we, biu_read, biu_write, biu_sel, first_hit_ack, first_miss_ack, first_miss_err,
   dcram_we, biu_read, biu_write, biu_do_sel, dcram_di_sel, first_hit_ack,
        burst, tag_we, tag_valid, dc_addr
   first_miss_ack, first_miss_err, burst, tag_we, tag_valid, dc_addr,
 
   dc_no_writethrough, tag_dirty, dirty, tag, tag_v, dc_block_flush,
 
   dc_block_writeback, spr_dat_i, mtspr_dc_done, spr_cswe
);
);
 
 
//
//
// I/O
// I/O
//
//
Line 139... Line 93...
input                           dcqmem_we_i;
input                           dcqmem_we_i;
input   [3:0]                    dcqmem_sel_i;
input   [3:0]                    dcqmem_sel_i;
input                           tagcomp_miss;
input                           tagcomp_miss;
input                           biudata_valid;
input                           biudata_valid;
input                           biudata_error;
input                           biudata_error;
input   [31:0]                   start_addr;
   input [31:0]                  lsu_addr;
output  [31:0]                   saved_addr;
 
output  [3:0]                    dcram_we;
output  [3:0]                    dcram_we;
output                          biu_read;
output                          biu_read;
output                          biu_write;
output                          biu_write;
output              biu_sel;
   output                               dcram_di_sel;
 
   output                               biu_do_sel;
output                          first_hit_ack;
output                          first_hit_ack;
output                          first_miss_ack;
output                          first_miss_ack;
output                          first_miss_err;
output                          first_miss_err;
output                          burst;
output                          burst;
output                          tag_we;
output                          tag_we;
output              tag_valid;
output              tag_valid;
output  [31:0]                   dc_addr;
output  [31:0]                   dc_addr;
 
   input                                dc_no_writethrough;
 
   output                               tag_dirty;
 
   input                                dirty;
 
   input [`OR1200_DCTAG_W-2:0]           tag;
 
   input                                tag_v;
 
   input                                dc_block_flush;
 
   input                                dc_block_writeback;
 
   input [31:0]                  spr_dat_i;
 
   output                               mtspr_dc_done;
 
   input                                spr_cswe;
 
 
 
 
//
//
// Internal wires and regs
// Internal wires and regs
//
//
reg     [31:0]                   saved_addr_r;
   reg [31:0]                            addr_r;
reg     [2:0]                    state;
reg     [2:0]                    state;
reg     [2:0]                    cnt;
reg     [2:0]                    cnt;
reg                             hitmiss_eval;
reg                             hitmiss_eval;
reg                             store;
reg                             store;
reg                             load;
reg                             load;
reg                             cache_inhibit;
reg                             cache_inhibit;
reg             cache_miss;
reg             cache_miss;
//wire                          tagcomp_miss_wide;
   reg                                  cache_dirty_needs_writeback;
wire                            first_store_hit_ack;
   reg                                  did_early_load_ack;
 
   reg                                  cache_spr_block_flush;
 
   reg                                  cache_spr_block_writeback;
 
   reg                                  cache_wb;
 
   wire                                 load_hit_ack;
 
   wire                                 load_miss_ack;
 
   wire                                 load_inhibit_ack;
 
   wire                                 store_hit_ack;
 
   wire                                 store_hit_writethrough_ack;
 
   wire                                 store_miss_writethrough_ack;
 
   wire                                 store_inhibit_ack;
 
   wire                                 store_miss_ack;
 
   wire                                 dcram_we_after_line_load;
 
   wire                                 dcram_we_during_line_load;
 
   wire                                 tagram_we_end_of_loadstore_loop;
 
   wire                                 tagram_dirty_bit_set;
 
   wire                                 writethrough;
 
   wire                                 cache_inhibit_with_eval;
 
   wire [1:0]                            next_addr_word;
 
 
 
   //
 
   // Cache inhibit
 
   //
 
 
 
   // Indicates whether cache is inhibited, during hitmiss_eval and after
 
   assign cache_inhibit_with_eval = (hitmiss_eval & dcqmem_ci_i) |
 
                                    (!hitmiss_eval & cache_inhibit);
 
 
//
//
// Generate of DCRAM write enables
// Generate of DCRAM write enables
//
//
//assign dcram_we = {4{load & biudata_valid & !cache_inhibit}} | {4{first_store_hit_ack}} & dcqmem_sel_i;
 
assign dcram_we = {4{load & biudata_valid & !cache_inhibit & !hitmiss_eval}} |
   // WE when non-writethrough, and had to wait for a line to load.
                  {4{first_store_hit_ack}} & dcqmem_sel_i;
   assign dcram_we_after_line_load = (state == `OR1200_DCFSM_LOOP3) &
//assign tag_we = biu_read & biudata_valid & !cache_inhibit;
                                    dcqmem_we_i & !cache_dirty_needs_writeback &
assign tag_we = load & (biudata_valid & (!cache_inhibit | !cache_miss) | biudata_error) & !hitmiss_eval |
                                     !did_early_load_ack;
                store & (biudata_valid & cache_inhibit & !cache_miss | biudata_error) & !hitmiss_eval;
 
assign tag_valid = biudata_valid & !cache_inhibit;
   // WE when receiving the data cache line
 
   assign dcram_we_during_line_load = (state == `OR1200_DCFSM_LOOP2) & load &
 
                                      biudata_valid;
 
 
 
   assign dcram_we =(// Write when hit - make sure it is only when hit - could
 
                     // maybe be doing write through and don't want to corrupt
 
                     // cache lines corresponding to the writethrough addr_r.
 
                     ({4{store_hit_ack | store_hit_writethrough_ack}} |
 
                     // Write after load of line
 
                     {4{dcram_we_after_line_load}}) &
 
                     dcqmem_sel_i                ) |
 
                    // Write during load
 
                    {4{dcram_we_during_line_load}};
 
 
 
   //
 
   // Tag RAM signals
 
   //
 
 
 
   // WE to tag RAM when we finish loading a line.
 
   assign tagram_we_end_of_loadstore_loop = ((state==`OR1200_DCFSM_LOOP2) &
 
                                             biudata_valid & !(|cnt));
 
 
 
`ifndef OR1200_DC_WRITETHROUGH
 
   // No writethrough, so mark a line dirty whenever we write to it
 
   assign tagram_dirty_bit_set = store_hit_ack | store_miss_ack;
 
 
 
   // Generate done signal for MTSPR instructions that may block execution
 
   assign mtspr_dc_done = // Either DC disabled or we're not selected, or
 
                          !dc_en | !spr_cswe |
 
                          // Requested address not valid or writeback and !dirty
 
                          ((state==`OR1200_DCFSM_FLUSH5) &
 
                           (!tag_v | (cache_spr_block_writeback & !dirty))) |
 
                          // Writeback or flush is finished
 
                          ((state==`OR1200_DCFSM_LOOP3) &
 
                           (cache_spr_block_flush | cache_spr_block_writeback))|
 
                          // Invalidate of clean line finished
 
                          ((state==`OR1200_DCFSM_INV6) & cache_spr_block_flush);
 
 
 
 
 
`else
 
 `ifdef OR1200_DC_NOSTACKWRITETHROUGH
 
   // For dirty bit setting when having writethrough but not for stack
 
   assign tagram_dirty_bit_set = store_hit_ack | store_miss_ack;
 
 `else
 
   // Lines will never be dirty if always writethrough
 
   assign tagram_dirty_bit_set = 0;
 
 `endif
 
 
 
   assign mtspr_dc_done = 1'b1;
 
 
 
`endif
 
 
 
   assign tag_dirty = tagram_dirty_bit_set;
 
 
 
   // WE to tag RAM
 
   assign tag_we = tagram_we_end_of_loadstore_loop |
 
                    tagram_dirty_bit_set | (state == `OR1200_DCFSM_INV6);
 
 
 
 
 
   // Valid bit
 
   // Set valid when end of line load, or marking dirty (is still valid)
 
   assign tag_valid = ( tagram_we_end_of_loadstore_loop &
 
                        (load | (store & cache_spr_block_writeback)) ) |
 
                      tagram_dirty_bit_set;
 
 
 
 
 
 
//
//
// BIU read and write
// BIU read and write
//
//
//assign biu_read = (hitmiss_eval & tagcomp_miss) | (!hitmiss_eval & load);
 
//assign biu_read = ((hitmiss_eval & tagcomp_miss) | (!hitmiss_eval & load)) & (dcqmem_cycstb_i | biudata_valid);
   assign biu_read = // Bus read request when:
assign biu_read = (state == `OR1200_DCFSM_CLOAD) & (hitmiss_eval ? ((tagcomp_miss | dcqmem_ci_i) & dcqmem_cycstb_i) : (cache_miss & !cache_inhibit & biudata_valid | dcqmem_cycstb_i & !biudata_error)) |
                     // 1) Have a miss and not dirty or a load with inhibit
                  (state == `OR1200_DCFSM_LREFILL3) & !(biudata_valid & !cnt) & !biudata_error;
                     ((state == `OR1200_DCFSM_CLOADSTORE) &
//assign biu_write = store;
                      (((hitmiss_eval & tagcomp_miss & !dirty &
//assign biu_write = store & dcqmem_cycstb_i;
                         !(store & writethrough)) |
assign biu_write = store & dcqmem_cycstb_i;
                        (load & cache_inhibit_with_eval)) & dcqmem_cycstb_i)) |
assign biu_sel = load;
                     // 2) In the loop and loading
 
                     ((state == `OR1200_DCFSM_LOOP2) & load);
//assign dc_addr = (biu_read | biu_write) & !hitmiss_eval ? saved_addr : start_addr;
 
assign dc_addr = (!(load | store) | hitmiss_eval) ? start_addr : saved_addr;
 
assign saved_addr = saved_addr_r;
   assign biu_write = // Bus write request when:
 
                      // 1) Have a miss and dirty or store with inhibit
//
                      ((state == `OR1200_DCFSM_CLOADSTORE) &
// Assert for cache hit first word ready
                       (((hitmiss_eval & tagcomp_miss & dirty) |
// Assert for store cache hit first word ready
                         (store & writethrough)) |
// Assert for cache miss first word stored/loaded OK
                        (store & cache_inhibit_with_eval)) & dcqmem_cycstb_i) |
// Assert for cache miss first word stored/loaded with an error
                      // 2) In the loop and storing
//
                      ((state == `OR1200_DCFSM_LOOP2) & store);
//assign tagcomp_miss_wide = tagcomp_miss | (saved_addr != start_addr);
 
//assign first_hit_ack = (state == `OR1200_DCFSM_CLOAD) & !tagcomp_miss_wide & !cache_inhibit | first_store_hit_ack;
   //
assign first_hit_ack = (state == `OR1200_DCFSM_CLOAD) & hitmiss_eval & !tagcomp_miss & !dcqmem_ci_i | first_store_hit_ack;
   // Select for data to actual cache RAM (from LSU or BIU)
//assign first_store_hit_ack = (state == `OR1200_DCFSM_CSTORE) & !tagcomp_miss_wide & biudata_valid & !cache_inhibit;
   //
assign first_store_hit_ack = (state == `OR1200_DCFSM_CSTORE) & !hitmiss_eval & !cache_miss & biudata_valid & !cache_inhibit;
   // Data to DCRAM - from external bus when loading (from IU when store)
assign first_miss_ack = ((state == `OR1200_DCFSM_CLOAD) | (state == `OR1200_DCFSM_CSTORE)) & biudata_valid;
   assign dcram_di_sel = load;
assign first_miss_err = ((state == `OR1200_DCFSM_CLOAD) | (state == `OR1200_DCFSM_CSTORE)) & biudata_error;
   // Data to external bus - always from IU except in case of bursting back
 
   //                        the line to memory. (1 selects DCRAM)
//
   assign biu_do_sel = (state == `OR1200_DCFSM_LOOP2) & store;
// Assert burst when doing reload of complete cache line
 
//
   // 2-bit wire for calculating next word of burst write
//assign burst = (state == `OR1200_DCFSM_CLOAD) & tagcomp_miss & !cache_inhibit
   assign next_addr_word = addr_r[3:2] + 1;
//              | (state == `OR1200_DCFSM_LREFILL3)
 
//`ifdef OR1200_DC_STORE_REFILL
   // Address to cache RAM (tag address also derived from this)   
//              | (state == `OR1200_DCFSM_SREFILL4)
   assign dc_addr =
//`endif
                   // First check if we've got a block flush or WB op
//              ;
                   ((dc_block_flush & !cache_spr_block_flush) |
assign burst = load & (hitmiss_eval ? !dcqmem_ci_i : !cache_inhibit);
                   (dc_block_writeback & !cache_spr_block_writeback)) ?
 
                   spr_dat_i :
 
                   (state==`OR1200_DCFSM_FLUSH5) ? addr_r:
 
                    // If no SPR action, then always put out address from LSU
 
                    (state==`OR1200_DCFSM_IDLE | hitmiss_eval) ? lsu_addr :
 
                    // Next, if in writeback loop, when ACKed must immediately
 
                    // output next word address (the RAM address takes a cycle
 
                    // to increment, but it's needed immediately for burst)
 
                    // otherwise, output our registered address.
 
                    (state==`OR1200_DCFSM_LOOP2 & biudata_valid & store ) ?
 
                    {addr_r[31:4], next_addr_word, 2'b00} : addr_r;
 
 
 
`ifdef OR1200_DC_WRITETHROUGH
 
 `ifdef OR1200_DC_NOSTACKWRITETHROUGH
 
   assign writethrough = !dc_no_writethrough;
 
 `else
 
   assign writethrough = 1;
 
 `endif
 
`else
 
   assign writethrough = 0;
 
`endif
 
 
 
   //
 
   // ACK generation for LSU
 
   //
 
 
 
   // ACK for when it's a cache hit
 
   assign first_hit_ack = load_hit_ack | store_hit_ack |
 
                          store_hit_writethrough_ack |
 
                          store_miss_writethrough_ack |
 
                          store_inhibit_ack | store_miss_ack ;
 
 
 
   // ACK for when it's a cache miss - load only, is used in MUX for data back
 
   //                                  LSU straight off external data bus. In
 
   //                                  this was is also used for cache inhibit
 
   //                                  loads.
 
   assign first_miss_ack = load_miss_ack | load_inhibit_ack;
 
 
 
   // ACK cache hit on load
 
   assign load_hit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
 
                         hitmiss_eval & !tagcomp_miss & !dcqmem_ci_i & load;
 
 
 
   // ACK cache hit on store, no writethrough
 
   assign store_hit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
 
                          hitmiss_eval  & !tagcomp_miss & !dcqmem_ci_i &
 
                          store & !writethrough;
 
 
 
   // ACK cache hit on store with writethrough
 
   assign store_hit_writethrough_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
 
                                       !cache_miss & !cache_inhibit &
 
                                       store & writethrough & biudata_valid;
 
 
 
   // ACK cache miss on store with writethrough
 
   assign store_miss_writethrough_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
 
                                        cache_miss & !cache_inhibit &
 
                                        store & writethrough & biudata_valid;
 
 
 
   // ACK store when cacheinhibit
 
   assign store_inhibit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
 
                              store & cache_inhibit & biudata_valid;
 
 
 
 
 
   // Get the _early_ ack on first ACK back from wishbone during load only
 
   // Condition is that we're in the loop - that it's the first ack we get (can
 
   // tell from value of cnt), and we're loading a line to read from it (not
 
   // loading to write to it, in the case of a write without writethrough.)
 
   assign load_miss_ack =  ((state== `OR1200_DCFSM_LOOP2) & load &
 
                             (cnt==`OR1200_DCLS-1) & biudata_valid &
 
                            !(dcqmem_we_i & !writethrough));
 
 
 
   assign load_inhibit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
 
                             load & cache_inhibit & biudata_valid;
 
 
 
   // This will be case of write through disabled, and had to load a line.
 
   assign store_miss_ack = dcram_we_after_line_load;
 
 
 
   assign first_miss_err = biudata_error & dcqmem_cycstb_i;
 
 
 
   // Signal burst when in the load/store loop. We will always try to burst.
 
   assign burst = (state == `OR1200_DCFSM_LOOP2);
 
 
//
//
// Main DC FSM
// Main DC FSM
//
//
always @(posedge clk or posedge rst) begin
always @(posedge clk or posedge rst) begin
        if (rst) begin
        if (rst) begin
                state <= #1 `OR1200_DCFSM_IDLE;
         state <=  `OR1200_DCFSM_IDLE;
                saved_addr_r <= #1 32'b0;
         addr_r <=  32'b0;
                hitmiss_eval <= #1 1'b0;
         hitmiss_eval <=  1'b0;
                store <= #1 1'b0;
         store <=  1'b0;
                load <= #1 1'b0;
         load <=  1'b0;
                cnt <= #1 3'b000;
         cnt <=  3'b000;
        cache_miss <= #1 1'b0;
         cache_miss <=  1'b0;
                cache_inhibit <= #1 1'b0;
         cache_dirty_needs_writeback <= 1'b0;
 
         cache_inhibit <=  1'b0;
 
         did_early_load_ack <= 1'b0;
 
         cache_spr_block_flush <= 1'b0;
 
         cache_spr_block_writeback <= 1'b0;
        end
        end
        else
        else
        case (state)    // synopsys parallel_case
        case (state)    // synopsys parallel_case
 
 
        `OR1200_DCFSM_IDLE : begin
        `OR1200_DCFSM_IDLE : begin
            if (dcqmem_we_i & dc_en & dcqmem_cycstb_i) // store
             if (dc_en & (dc_block_flush | dc_block_writeback))
                state <= #1 `OR1200_DCFSM_CSTORE;
               begin
            else if (!dcqmem_we_i & dc_en & dcqmem_cycstb_i) // store
                  cache_spr_block_flush <= dc_block_flush;
                state <= #1 `OR1200_DCFSM_CLOAD;
                  cache_spr_block_writeback <= dc_block_writeback;
            cache_inhibit <= #1 1'b0;         // not dcqmem_ci_i because it is delayed (due to DTLB)
                  hitmiss_eval <= 1'b1;
            hitmiss_eval <= #1 dc_en & dcqmem_cycstb_i  ;
                  state <= `OR1200_DCFSM_FLUSH5;
            store <= #1 dc_en & dcqmem_cycstb_i & dcqmem_we_i;
                  addr_r <=  spr_dat_i;
            load <= #1 dc_en & dcqmem_cycstb_i & !dcqmem_we_i;
               end
        end
             else if (dc_en & dcqmem_cycstb_i)
        `OR1200_DCFSM_CLOAD: begin      // load
               begin
            if (!hitmiss_eval && cache_miss && !cache_inhibit && biudata_valid) begin
                  state <= `OR1200_DCFSM_CLOADSTORE;
                state <= #1 `OR1200_DCFSM_LREFILL3;
                  hitmiss_eval <=  1'b1;
            end
                  store <=  dcqmem_we_i;
            else if (!dcqmem_cycstb_i || !hitmiss_eval && (biudata_valid || biudata_error) || hitmiss_eval && !tagcomp_miss && !dcqmem_ci_i) begin
                  load <=  !dcqmem_we_i;
                state <= #1 `OR1200_DCFSM_IDLE;
 
                load <= #1 1'b0;
 
            end
 
            hitmiss_eval <= #1 1'b0;
 
            cnt <= #1 `OR1200_DCLS-2;
 
            if (hitmiss_eval) begin
 
                cache_inhibit <= #1 dcqmem_ci_i;
 
                cache_miss <= #1 tagcomp_miss;
 
            end
            end
            if (hitmiss_eval)
 
                saved_addr_r <= #1 start_addr;
 
            else if (biudata_valid)
          end // case: `OR1200_DCFSM_IDLE
                saved_addr_r[3:2] <= #1 saved_addr_r[3:2] + 1'b1;
 
        end
          `OR1200_DCFSM_CLOADSTORE: begin
        `OR1200_DCFSM_LREFILL3 : begin
 
            if (!dc_en || biudata_valid && !cnt || biudata_error) begin                     // finish/abort
 
                state <= #1 `OR1200_DCFSM_IDLE;
 
                load <= #1 1'b0;
 
            end
 
            if (biudata_valid) begin
 
                cnt <= #1 cnt - 1'b1;
 
                saved_addr_r[3:2] <= #1 saved_addr_r[3:2] + 1'b1;
 
            end
 
        end
 
        `OR1200_DCFSM_CSTORE: begin     // store
 
            hitmiss_eval <= 1'b0;
            hitmiss_eval <= 1'b0;
            if (hitmiss_eval) begin
            if (hitmiss_eval) begin
                cache_inhibit <= #1 dcqmem_ci_i;
                cache_inhibit <=  dcqmem_ci_i; // Check for cache inhibit here
                cache_miss <= #1 tagcomp_miss;
                cache_miss <=  tagcomp_miss;
 
                cache_dirty_needs_writeback <= dirty;
 
                addr_r <=  lsu_addr;
 
             end
 
 
 
             // Evaluate any cache line load/stores in first cycle:
 
                             //
 
             if (hitmiss_eval & tagcomp_miss & !(store & writethrough) &
 
                 !dcqmem_ci_i)
 
               begin
 
                  // Miss - first either:
 
                  //  1) write back dirty line 
 
                  if (dirty) begin
 
                     // Address for writeback
 
                     addr_r <=  {tag, lsu_addr[`OR1200_DCINDXH:2],2'd0};
 
                     load <= 1'b0;
 
                     store <= 1'b1;
 
`ifdef OR1200_VERBOSE
 
                     $display("%t: dcache miss and dirty", $time);
 
`endif
            end
            end
            if (hitmiss_eval)
                  //  2) load requested line
                saved_addr_r <= #1 start_addr;
                  else begin
`ifdef OR1200_DC_STORE_REFILL
                     addr_r <=  lsu_addr;
            else if (biudata_valid)
                     load <= 1'b1;
                saved_addr_r[3:2] <= #1 saved_addr_r[3:2] + 1'b1;
                     store <= 1'b0;
            cnt <= #1 `OR1200_DCLS-1;
                  end // else: !if(dirty)
            if (!hitmiss_eval && cache_miss && !cache_inhibit && biudata_valid) begin
                  state <= `OR1200_DCFSM_LOOP2;
                state <= #1 `OR1200_DCFSM_SREFILL4;
                  // Set the counter for the burst accesses
                store <= #1 1'b0;
                  cnt <=  `OR1200_DCLS-1;
                load <= #1 1'b1;
               end
 
             else if (// Strobe goes low
 
                      !dcqmem_cycstb_i |
 
                      // Cycle finishes
 
                      (!hitmiss_eval & (biudata_valid | biudata_error)) |
 
                      // Cache hit in first cycle....
 
                      (hitmiss_eval & !tagcomp_miss & !dcqmem_ci_i &
 
                      // .. and you're not doing a writethrough store..
 
                      !(store & writethrough))) begin
 
                state <=  `OR1200_DCFSM_IDLE;
 
                load <=  1'b0;
 
                store <= 1'b0;
 
                cache_inhibit <= 1'b0;
 
                cache_dirty_needs_writeback <= 1'b0;
 
             end
 
          end // case: `OR1200_DCFSM_CLOADSTORE   
 
 
 
          `OR1200_DCFSM_LOOP2 : begin // loop/abort          
 
             if (!dc_en| biudata_error) begin
 
                state <=  `OR1200_DCFSM_IDLE;
 
                load <=  1'b0;
 
                store <= 1'b0;
 
                cnt <= 1'b0;
 
             end
 
             if (biudata_valid & (|cnt)) begin
 
                cnt <=  cnt - 1'b1;
 
                addr_r[3:2] <=  addr_r[3:2] + 1'b1;
 
             end
 
             else if (biudata_valid & !(|cnt)) begin
 
                state <= `OR1200_DCFSM_LOOP3;
 
                addr_r <=  lsu_addr;
 
                load <= 1'b0;
 
                store <= 1'b0;
 
             end
 
 
 
             // Track if we did an early ack during a load
 
             if (load_miss_ack)
 
               did_early_load_ack <= 1'b1;
 
 
 
 
 
          end // case: `OR1200_DCFSM_LOOP2
 
 
 
          `OR1200_DCFSM_LOOP3: begin // figure out next step
 
             if (cache_dirty_needs_writeback) begin
 
                // Just did store of the dirty line so now load new one
 
                load <= 1'b1;
 
                // Set the counter for the burst accesses
 
                cnt <=  `OR1200_DCLS-1;
 
                // Address of line to be loaded
 
                addr_r <=  lsu_addr;
 
                cache_dirty_needs_writeback <= 1'b0;
 
                state <= `OR1200_DCFSM_LOOP2;
 
             end // if (cache_dirty_needs_writeback)
 
             else if (cache_spr_block_flush | cache_spr_block_writeback) begin
 
                // Just wrote back the line to memory, we're finished.
 
                cache_spr_block_flush <= 1'b0;
 
                cache_spr_block_writeback <= 1'b0;
 
                state <= `OR1200_DCFSM_WAITSPRCS7;
 
             end
 
             else begin
 
                // Just loaded a new line, finish up
 
                did_early_load_ack <= 1'b0;
 
                state <= `OR1200_DCFSM_LOOP4;
            end
            end
            else
          end // case: `OR1200_DCFSM_LOOP3
`endif
 
            if (!dcqmem_cycstb_i || !hitmiss_eval && (biudata_error || biudata_valid)) begin
          `OR1200_DCFSM_LOOP4: begin
                state <= #1 `OR1200_DCFSM_IDLE;
             state <=  `OR1200_DCFSM_IDLE;
                store <= #1 1'b0;
 
            end
 
`ifdef OR1200_DC_STORE_REFILL
 
        `OR1200_DCFSM_SREFILL4 : begin
 
            if (!dc_en) begin                       // somebody just turned off DC therefore we abort
 
                cnt <= #1 3'd0;                     // DC will have to be invalidated before
 
                state <= #1 `OR1200_DCFSM_IDLE;     // it can be turned on again
 
                load <= #1 1'b0;
 
            end
 
            else if (biudata_valid && (|cnt)) begin // refill ack, more loads to come
 
                cnt <= #1 cnt - 1'd1;
 
                saved_addr_r[3:2] <= #1 saved_addr_r[3:2] + 1'd1;
 
            end
 
            else if (biudata_valid) begin           // last load of line refill
 
                state <= #1 `OR1200_DCFSM_IDLE;
 
                load <= #1 1'b0;
 
            end
            end
 
 
 
          `OR1200_DCFSM_FLUSH5: begin
 
             hitmiss_eval <= 1'b0;
 
             if (hitmiss_eval & !tag_v)
 
               begin
 
                  // Not even cached, just ignore
 
                  cache_spr_block_flush <= 1'b0;
 
                  cache_spr_block_writeback <= 1'b0;
 
                  state <=  `OR1200_DCFSM_WAITSPRCS7;
 
               end
 
             else if (hitmiss_eval & tag_v)
 
               begin
 
                  // Tag is valid - what do we do?
 
                  if ((cache_spr_block_flush | cache_spr_block_writeback) &
 
                      dirty) begin
 
                     // Need to writeback
 
                     // Address for writeback (spr_dat_i has already changed so
 
                     // use line number from addr_r)
 
                     addr_r <=  {tag, addr_r[`OR1200_DCINDXH:2],2'd0};
 
                     load <= 1'b0;
 
                     store <= 1'b1;
 
`ifdef OR1200_VERBOSE
 
                     $display("%t: block flush: dirty block", $time);
`endif
`endif
 
                     state <= `OR1200_DCFSM_LOOP2;
 
                     // Set the counter for the burst accesses
 
                     cnt <=  `OR1200_DCLS-1;
 
                  end
 
                  else if (cache_spr_block_flush & !dirty)
 
                    begin
 
                       // Line not dirty, just need to invalidate
 
                       state <=  `OR1200_DCFSM_INV6;
 
                    end // else: !if(dirty)
 
                  else if (cache_spr_block_writeback & !dirty)
 
                    begin
 
                       // Nothing to do - line is valid but not dirty
 
                       cache_spr_block_writeback <= 1'b0;
 
                       state <=  `OR1200_DCFSM_WAITSPRCS7;
 
                    end
 
          end // if (hitmiss_eval & tag_v)
 
          end
 
          `OR1200_DCFSM_INV6: begin
 
             cache_spr_block_flush <= 1'b0;
 
             // Wait until SPR CS goes low before going back to idle
 
             if (!spr_cswe)
 
               state <=  `OR1200_DCFSM_IDLE;
 
          end
 
          `OR1200_DCFSM_WAITSPRCS7: begin
 
             // Wait until SPR CS goes low before going back to idle
 
             if (!spr_cswe)
 
               state <=  `OR1200_DCFSM_IDLE;
        end
        end
 
 
        default:
        endcase // case (state)
            state <= #1 `OR1200_DCFSM_IDLE;
 
    endcase
   end // always @ (posedge clk or posedge rst)
end
 
 
 
endmodule
endmodule
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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