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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [rtl/] [verilog/] [or1200/] [or1200_dc_fsm.v] - Diff between revs 363 and 477

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 363 Rev 477
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
////  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://opencores.org/project,or1k                           ////
////  http://opencores.org/project,or1k                           ////
////                                                              ////
////                                                              ////
////  Description                                                 ////
////  Description                                                 ////
////  Data cache state machine                                    ////
////  Data cache state machine                                    ////
////                                                              ////
////                                                              ////
////  To Do:                                                      ////
////  To Do:                                                      ////
////   - Test error during line read or write                     ////
////   - 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                   ////
////      - Julius Baxter, julius@opencores.org                   ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
////                                                              ////
////                                                              ////
//// Copyright (C) 2000, 2010 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. ////
////                                                              ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
//// later version.                                               ////
////                                                              ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
//// details.                                                     ////
////                                                              ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// You should have received a copy of the GNU Lesser General    ////
//// 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                     ////
////                                                              ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//
//
// $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. 
//
//
 
 
// 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_CLOADSTORE 3'd1
`define OR1200_DCFSM_CLOADSTORE 3'd1
`define OR1200_DCFSM_LOOP2      3'd2
`define OR1200_DCFSM_LOOP2      3'd2
`define OR1200_DCFSM_LOOP3      3'd3
`define OR1200_DCFSM_LOOP3      3'd3
`define OR1200_DCFSM_LOOP4      3'd4
`define OR1200_DCFSM_LOOP4      3'd4
`define OR1200_DCFSM_FLUSH5     3'd5
`define OR1200_DCFSM_FLUSH5     3'd5
`define OR1200_DCFSM_INV6       3'd6
`define OR1200_DCFSM_INV6       3'd6
`define OR1200_DCFSM_WAITSPRCS7 3'd7
`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, lsu_addr,
   tagcomp_miss, biudata_valid, biudata_error, lsu_addr,
   dcram_we, biu_read, biu_write, biu_do_sel, dcram_di_sel, first_hit_ack,
   dcram_we, biu_read, biu_write, biu_do_sel, dcram_di_sel, first_hit_ack,
   first_miss_ack, first_miss_err, 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_no_writethrough, tag_dirty, dirty, tag, tag_v, dc_block_flush,
   dc_block_writeback, spr_dat_i, mtspr_dc_done, spr_cswe
   dc_block_writeback, spr_dat_i, mtspr_dc_done, spr_cswe
   );
   );
 
 
   //
   //
   // I/O
   // I/O
   //
   //
   input                                clk;
   input                                clk;
   input                                rst;
   input                                rst;
   input                                dc_en;
   input                                dc_en;
   input                                dcqmem_cycstb_i;
   input                                dcqmem_cycstb_i;
   input                                dcqmem_ci_i;
   input                                dcqmem_ci_i;
   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]                  lsu_addr;
   input [31:0]                  lsu_addr;
   output [3:0]                  dcram_we;
   output [3:0]                  dcram_we;
   output                               biu_read;
   output                               biu_read;
   output                               biu_write;
   output                               biu_write;
   output                               dcram_di_sel;
   output                               dcram_di_sel;
   output                               biu_do_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;
   input                                dc_no_writethrough;
   output                               tag_dirty;
   output                               tag_dirty;
   input                                dirty;
   input                                dirty;
   input [`OR1200_DCTAG_W-2:0]           tag;
   input [`OR1200_DCTAG_W-2:0]           tag;
   input                                tag_v;
   input                                tag_v;
   input                                dc_block_flush;
   input                                dc_block_flush;
   input                                dc_block_writeback;
   input                                dc_block_writeback;
   input [31:0]                  spr_dat_i;
   input [31:0]                  spr_dat_i;
   output                               mtspr_dc_done;
   output                               mtspr_dc_done;
   input                                spr_cswe;
   input                                spr_cswe;
 
 
 
 
   //
   //
   // Internal wires and regs
   // Internal wires and regs
   //
   //
   reg [31:0]                            addr_r;
   reg [31:0]                            addr_r;
   reg [2:0]                             state;
   reg [2:0]                             state;
   reg [2:0]                             cnt;
   reg [`OR1200_DCLS-1: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;
   reg                                  cache_dirty_needs_writeback;
   reg                                  cache_dirty_needs_writeback;
   reg                                  did_early_load_ack;
   reg                                  did_early_load_ack;
   reg                                  cache_spr_block_flush;
   reg                                  cache_spr_block_flush;
   reg                                  cache_spr_block_writeback;
   reg                                  cache_spr_block_writeback;
   reg                                  cache_wb;
   reg                                  cache_wb;
   wire                                 load_hit_ack;
   wire                                 load_hit_ack;
   wire                                 load_miss_ack;
   wire                                 load_miss_ack;
   wire                                 load_inhibit_ack;
   wire                                 load_inhibit_ack;
   wire                                 store_hit_ack;
   wire                                 store_hit_ack;
   wire                                 store_hit_writethrough_ack;
   wire                                 store_hit_writethrough_ack;
   wire                                 store_miss_writethrough_ack;
   wire                                 store_miss_writethrough_ack;
   wire                                 store_inhibit_ack;
   wire                                 store_inhibit_ack;
   wire                                 store_miss_ack;
   wire                                 store_miss_ack;
   wire                                 dcram_we_after_line_load;
   wire                                 dcram_we_after_line_load;
   wire                                 dcram_we_during_line_load;
   wire                                 dcram_we_during_line_load;
   wire                                 tagram_we_end_of_loadstore_loop;
   wire                                 tagram_we_end_of_loadstore_loop;
   wire                                 tagram_dirty_bit_set;
   wire                                 tagram_dirty_bit_set;
   wire                                 writethrough;
   wire                                 writethrough;
   wire                                 cache_inhibit_with_eval;
   wire                                 cache_inhibit_with_eval;
   wire [1:0]                            next_addr_word;
   wire [(`OR1200_DCLS-1)-2:0]           next_addr_word;
 
 
   //
   //
   // Cache inhibit
   // Cache inhibit
   //
   //
 
 
   // Indicates whether cache is inhibited, during hitmiss_eval and after
   // Indicates whether cache is inhibited, during hitmiss_eval and after
   assign cache_inhibit_with_eval = (hitmiss_eval & dcqmem_ci_i) |
   assign cache_inhibit_with_eval = (hitmiss_eval & dcqmem_ci_i) |
                                    (!hitmiss_eval & cache_inhibit);
                                    (!hitmiss_eval & cache_inhibit);
 
 
   //
   //
   // Generate of DCRAM write enables
   // Generate of DCRAM write enables
   //
   //
 
 
   // WE when non-writethrough, and had to wait for a line to load.
   // WE when non-writethrough, and had to wait for a line to load.
   assign dcram_we_after_line_load = (state == `OR1200_DCFSM_LOOP3) &
   assign dcram_we_after_line_load = (state == `OR1200_DCFSM_LOOP3) &
                                    dcqmem_we_i & !cache_dirty_needs_writeback &
                                    dcqmem_we_i & !cache_dirty_needs_writeback &
                                     !did_early_load_ack;
                                     !did_early_load_ack;
 
 
   // WE when receiving the data cache line
   // WE when receiving the data cache line
   assign dcram_we_during_line_load = (state == `OR1200_DCFSM_LOOP2) & load &
   assign dcram_we_during_line_load = (state == `OR1200_DCFSM_LOOP2) & load &
                                      biudata_valid;
                                      biudata_valid;
 
 
   assign dcram_we =(// Write when hit - make sure it is only when hit - could
   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
                     // maybe be doing write through and don't want to corrupt
                     // cache lines corresponding to the writethrough addr_r.
                     // cache lines corresponding to the writethrough addr_r.
                     ({4{store_hit_ack | store_hit_writethrough_ack}} |
                     ({4{store_hit_ack | store_hit_writethrough_ack}} |
                     // Write after load of line
                     // Write after load of line
                     {4{dcram_we_after_line_load}}) &
                     {4{dcram_we_after_line_load}}) &
                     dcqmem_sel_i                ) |
                     dcqmem_sel_i                ) |
                    // Write during load
                    // Write during load
                    {4{dcram_we_during_line_load}};
                    {4{dcram_we_during_line_load}};
 
 
   //
   //
   // Tag RAM signals
   // Tag RAM signals
   //
   //
 
 
   // WE to tag RAM when we finish loading a line.
   // WE to tag RAM when we finish loading a line.
   assign tagram_we_end_of_loadstore_loop = ((state==`OR1200_DCFSM_LOOP2) &
   assign tagram_we_end_of_loadstore_loop = ((state==`OR1200_DCFSM_LOOP2) &
                                             biudata_valid & !(|cnt));
                                             biudata_valid & !(|cnt));
 
 
`ifndef OR1200_DC_WRITETHROUGH
`ifndef OR1200_DC_WRITETHROUGH
   // No writethrough, so mark a line dirty whenever we write to it
   // No writethrough, so mark a line dirty whenever we write to it
   assign tagram_dirty_bit_set = store_hit_ack | store_miss_ack;
   assign tagram_dirty_bit_set = store_hit_ack | store_miss_ack;
 
 
   // Generate done signal for MTSPR instructions that may block execution
   // Generate done signal for MTSPR instructions that may block execution
   assign mtspr_dc_done = // Either DC disabled or we're not selected, or
   assign mtspr_dc_done = // Either DC disabled or we're not selected, or
                          !dc_en | !spr_cswe |
                          !dc_en | !spr_cswe |
                          // Requested address not valid or writeback and !dirty
                          // Requested address not valid or writeback and !dirty
                          ((state==`OR1200_DCFSM_FLUSH5) &
                          ((state==`OR1200_DCFSM_FLUSH5) &
                           (!tag_v | (cache_spr_block_writeback & !dirty))) |
                           (!tag_v | (cache_spr_block_writeback & !dirty))) |
                          // Writeback or flush is finished
                          // Writeback or flush is finished
                          ((state==`OR1200_DCFSM_LOOP3) &
                          ((state==`OR1200_DCFSM_LOOP3) &
                           (cache_spr_block_flush | cache_spr_block_writeback))|
                           (cache_spr_block_flush | cache_spr_block_writeback))|
                          // Invalidate of clean line finished
                          // Invalidate of clean line finished
                          ((state==`OR1200_DCFSM_INV6) & cache_spr_block_flush);
                          ((state==`OR1200_DCFSM_INV6) & cache_spr_block_flush);
 
 
 
 
`else
`else
 `ifdef OR1200_DC_NOSTACKWRITETHROUGH
 `ifdef OR1200_DC_NOSTACKWRITETHROUGH
   // For dirty bit setting when having writethrough but not for stack
   // For dirty bit setting when having writethrough but not for stack
   assign tagram_dirty_bit_set = store_hit_ack | store_miss_ack;
   assign tagram_dirty_bit_set = store_hit_ack | store_miss_ack;
 `else
 `else
   // Lines will never be dirty if always writethrough
   // Lines will never be dirty if always writethrough
   assign tagram_dirty_bit_set = 0;
   assign tagram_dirty_bit_set = 0;
 `endif
 `endif
 
 
   assign mtspr_dc_done = 1'b1;
   assign mtspr_dc_done = 1'b1;
 
 
`endif
`endif
 
 
   assign tag_dirty = tagram_dirty_bit_set;
   assign tag_dirty = tagram_dirty_bit_set;
 
 
   // WE to tag RAM
   // WE to tag RAM
   assign tag_we = tagram_we_end_of_loadstore_loop |
   assign tag_we = tagram_we_end_of_loadstore_loop |
                    tagram_dirty_bit_set | (state == `OR1200_DCFSM_INV6);
                    tagram_dirty_bit_set | (state == `OR1200_DCFSM_INV6);
 
 
 
 
   // Valid bit
   // Valid bit
   // Set valid when end of line load, or marking dirty (is still valid)
   // Set valid when end of line load, or marking dirty (is still valid)
   assign tag_valid = ( tagram_we_end_of_loadstore_loop &
   assign tag_valid = ( tagram_we_end_of_loadstore_loop &
                        (load | (store & cache_spr_block_writeback)) ) |
                        (load | (store & cache_spr_block_writeback)) ) |
                      tagram_dirty_bit_set;
                      tagram_dirty_bit_set;
 
 
 
 
 
 
   //
   //
   // BIU read and write
   // BIU read and write
   //
   //
 
 
   assign biu_read = // Bus read request when:
   assign biu_read = // Bus read request when:
                     // 1) Have a miss and not dirty or a load with inhibit
                     // 1) Have a miss and not dirty or a load with inhibit
                     ((state == `OR1200_DCFSM_CLOADSTORE) &
                     ((state == `OR1200_DCFSM_CLOADSTORE) &
                      (((hitmiss_eval & tagcomp_miss & !dirty &
                      (((hitmiss_eval & tagcomp_miss & !dirty &
                         !(store & writethrough)) |
                         !(store & writethrough)) |
                        (load & cache_inhibit_with_eval)) & dcqmem_cycstb_i)) |
                        (load & cache_inhibit_with_eval)) & dcqmem_cycstb_i)) |
                     // 2) In the loop and loading
                     // 2) In the loop and loading
                     ((state == `OR1200_DCFSM_LOOP2) & load);
                     ((state == `OR1200_DCFSM_LOOP2) & load);
 
 
 
 
   assign biu_write = // Bus write request when:
   assign biu_write = // Bus write request when:
                      // 1) Have a miss and dirty or store with inhibit
                      // 1) Have a miss and dirty or store with inhibit
                      ((state == `OR1200_DCFSM_CLOADSTORE) &
                      ((state == `OR1200_DCFSM_CLOADSTORE) &
                       (((hitmiss_eval & tagcomp_miss & dirty) |
                       (((hitmiss_eval & tagcomp_miss & dirty) |
                         (store & writethrough)) |
                         (store & writethrough)) |
                        (store & cache_inhibit_with_eval)) & dcqmem_cycstb_i) |
                        (store & cache_inhibit_with_eval)) & dcqmem_cycstb_i) |
                      // 2) In the loop and storing
                      // 2) In the loop and storing
                      ((state == `OR1200_DCFSM_LOOP2) & store);
                      ((state == `OR1200_DCFSM_LOOP2) & store);
 
 
   //
   //
   // Select for data to actual cache RAM (from LSU or BIU)
   // Select for data to actual cache RAM (from LSU or BIU)
   //
   //
   // Data to DCRAM - from external bus when loading (from IU when store)
   // Data to DCRAM - from external bus when loading (from IU when store)
   assign dcram_di_sel = load;
   assign dcram_di_sel = load;
   // Data to external bus - always from IU except in case of bursting back
   // Data to external bus - always from IU except in case of bursting back
   //                        the line to memory. (1 selects DCRAM)
   //                        the line to memory. (1 selects DCRAM)
   assign biu_do_sel = (state == `OR1200_DCFSM_LOOP2) & store;
   assign biu_do_sel = (state == `OR1200_DCFSM_LOOP2) & store;
 
 
   // 2-bit wire for calculating next word of burst write
   // 3-bit wire for calculating next word of burst write, depending on
   assign next_addr_word = addr_r[3:2] + 1;
   // line size of data cache.
 
   assign next_addr_word =  addr_r[`OR1200_DCLS-1:2] + 1;
 
 
   // Address to cache RAM (tag address also derived from this)   
   // Address to cache RAM (tag address also derived from this)   
   assign dc_addr =
   assign dc_addr =
                   // First check if we've got a block flush or WB op
                   // First check if we've got a block flush or WB op
                   ((dc_block_flush & !cache_spr_block_flush) |
                   ((dc_block_flush & !cache_spr_block_flush) |
                   (dc_block_writeback & !cache_spr_block_writeback)) ?
                   (dc_block_writeback & !cache_spr_block_writeback)) ?
                   spr_dat_i :
                   spr_dat_i :
                   (state==`OR1200_DCFSM_FLUSH5) ? addr_r:
                   (state==`OR1200_DCFSM_FLUSH5) ? addr_r:
                    // If no SPR action, then always put out address from LSU
                    // If no SPR action, then always put out address from LSU
                    (state==`OR1200_DCFSM_IDLE | hitmiss_eval) ? lsu_addr :
                    (state==`OR1200_DCFSM_IDLE | hitmiss_eval) ? lsu_addr :
                    // Next, if in writeback loop, when ACKed must immediately
                    // Next, if in writeback loop, when ACKed must immediately
                    // output next word address (the RAM address takes a cycle
                    // output next word address (the RAM address takes a cycle
                    // to increment, but it's needed immediately for burst)
                    // to increment, but it's needed immediately for burst)
                    // otherwise, output our registered address.
                    // otherwise, output our registered address.
                    (state==`OR1200_DCFSM_LOOP2 & biudata_valid & store ) ?
                    (state==`OR1200_DCFSM_LOOP2 & biudata_valid & store ) ?
                    {addr_r[31:4], next_addr_word, 2'b00} : addr_r;
                    {addr_r[31:`OR1200_DCLS], next_addr_word, 2'b00} : addr_r;
 
 
`ifdef OR1200_DC_WRITETHROUGH
`ifdef OR1200_DC_WRITETHROUGH
 `ifdef OR1200_DC_NOSTACKWRITETHROUGH
 `ifdef OR1200_DC_NOSTACKWRITETHROUGH
   assign writethrough = !dc_no_writethrough;
   assign writethrough = !dc_no_writethrough;
 `else
 `else
   assign writethrough = 1;
   assign writethrough = 1;
 `endif
 `endif
`else
`else
   assign writethrough = 0;
   assign writethrough = 0;
`endif
`endif
 
 
   //
   //
   // ACK generation for LSU
   // ACK generation for LSU
   //
   //
 
 
   // ACK for when it's a cache hit
   // ACK for when it's a cache hit
   assign first_hit_ack = load_hit_ack | store_hit_ack |
   assign first_hit_ack = load_hit_ack | store_hit_ack |
                          store_hit_writethrough_ack |
                          store_hit_writethrough_ack |
                          store_miss_writethrough_ack |
                          store_miss_writethrough_ack |
                          store_inhibit_ack | store_miss_ack ;
                          store_inhibit_ack | store_miss_ack ;
 
 
   // ACK for when it's a cache miss - load only, is used in MUX for data back
   // ACK for when it's a cache miss - load only, is used in MUX for data back
   //                                  LSU straight off external data bus. In
   //                                  LSU straight off external data bus. In
   //                                  this was is also used for cache inhibit
   //                                  this was is also used for cache inhibit
   //                                  loads.
   //                                  loads.
   assign first_miss_ack = load_miss_ack | load_inhibit_ack;
   assign first_miss_ack = load_miss_ack | load_inhibit_ack;
 
 
   // ACK cache hit on load
   // ACK cache hit on load
   assign load_hit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
   assign load_hit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
                         hitmiss_eval & !tagcomp_miss & !dcqmem_ci_i & load;
                         hitmiss_eval & !tagcomp_miss & !dcqmem_ci_i & load;
 
 
   // ACK cache hit on store, no writethrough
   // ACK cache hit on store, no writethrough
   assign store_hit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
   assign store_hit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
                          hitmiss_eval  & !tagcomp_miss & !dcqmem_ci_i &
                          hitmiss_eval  & !tagcomp_miss & !dcqmem_ci_i &
                          store & !writethrough;
                          store & !writethrough;
 
 
   // ACK cache hit on store with writethrough
   // ACK cache hit on store with writethrough
   assign store_hit_writethrough_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
   assign store_hit_writethrough_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
                                       !cache_miss & !cache_inhibit &
                                       !cache_miss & !cache_inhibit &
                                       store & writethrough & biudata_valid;
                                       store & writethrough & biudata_valid;
 
 
   // ACK cache miss on store with writethrough
   // ACK cache miss on store with writethrough
   assign store_miss_writethrough_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
   assign store_miss_writethrough_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
                                        cache_miss & !cache_inhibit &
                                        cache_miss & !cache_inhibit &
                                        store & writethrough & biudata_valid;
                                        store & writethrough & biudata_valid;
 
 
   // ACK store when cacheinhibit
   // ACK store when cacheinhibit
   assign store_inhibit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
   assign store_inhibit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
                              store & cache_inhibit & biudata_valid;
                              store & cache_inhibit & biudata_valid;
 
 
 
 
   // Get the _early_ ack on first ACK back from wishbone during load only
   // 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
   // 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
   // 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.)
   // loading to write to it, in the case of a write without writethrough.)
   assign load_miss_ack =  ((state== `OR1200_DCFSM_LOOP2) & load &
   assign load_miss_ack =  ((state== `OR1200_DCFSM_LOOP2) & load &
                             (cnt==`OR1200_DCLS-1) & biudata_valid &
                            (cnt==((1 << `OR1200_DCLS) - 4)) & biudata_valid &
                            !(dcqmem_we_i & !writethrough));
                            !(dcqmem_we_i & !writethrough));
 
 
   assign load_inhibit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
   assign load_inhibit_ack = (state == `OR1200_DCFSM_CLOADSTORE) &
                             load & cache_inhibit & biudata_valid;
                             load & cache_inhibit & biudata_valid;
 
 
   // This will be case of write through disabled, and had to load a line.
   // This will be case of write through disabled, and had to load a line.
   assign store_miss_ack = dcram_we_after_line_load;
   assign store_miss_ack = dcram_we_after_line_load;
 
 
   assign first_miss_err = biudata_error & dcqmem_cycstb_i;
   assign first_miss_err = biudata_error & dcqmem_cycstb_i;
 
 
   // Signal burst when in the load/store loop. We will always try to burst.
   // Signal burst when in the load/store loop. We will always try to burst.
   assign burst = (state == `OR1200_DCFSM_LOOP2);
   assign burst = (state == `OR1200_DCFSM_LOOP2);
 
 
   //
   //
   // Main DC FSM
   // Main DC FSM
   //
   //
   always @(posedge clk or `OR1200_RST_EVENT rst) begin
   always @(posedge clk or `OR1200_RST_EVENT rst) begin
      if (rst == `OR1200_RST_VALUE) begin
      if (rst == `OR1200_RST_VALUE) begin
         state <=  `OR1200_DCFSM_IDLE;
         state <=  `OR1200_DCFSM_IDLE;
         addr_r <=  32'b0;
         addr_r <=  32'd0;
         hitmiss_eval <=  1'b0;
         hitmiss_eval <=  1'b0;
         store <=  1'b0;
         store <=  1'b0;
         load <=  1'b0;
         load <=  1'b0;
         cnt <=  3'd0;
         cnt <=  `OR1200_DCLS'd0;
         cache_miss <=  1'b0;
         cache_miss <=  1'b0;
         cache_dirty_needs_writeback <= 1'b0;
         cache_dirty_needs_writeback <= 1'b0;
         cache_inhibit <=  1'b0;
         cache_inhibit <=  1'b0;
         did_early_load_ack <= 1'b0;
         did_early_load_ack <= 1'b0;
         cache_spr_block_flush <= 1'b0;
         cache_spr_block_flush <= 1'b0;
         cache_spr_block_writeback <= 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 (dc_en & (dc_block_flush | dc_block_writeback))
             if (dc_en & (dc_block_flush | dc_block_writeback))
               begin
               begin
                  cache_spr_block_flush <= dc_block_flush;
                  cache_spr_block_flush <= dc_block_flush;
                  cache_spr_block_writeback <= dc_block_writeback;
                  cache_spr_block_writeback <= dc_block_writeback;
                  hitmiss_eval <= 1'b1;
                  hitmiss_eval <= 1'b1;
                  state <= `OR1200_DCFSM_FLUSH5;
                  state <= `OR1200_DCFSM_FLUSH5;
                  addr_r <=  spr_dat_i;
                  addr_r <=  spr_dat_i;
               end
               end
             else if (dc_en & dcqmem_cycstb_i)
             else if (dc_en & dcqmem_cycstb_i)
               begin
               begin
                  state <= `OR1200_DCFSM_CLOADSTORE;
                  state <= `OR1200_DCFSM_CLOADSTORE;
                  hitmiss_eval <=  1'b1;
                  hitmiss_eval <=  1'b1;
                  store <=  dcqmem_we_i;
                  store <=  dcqmem_we_i;
                  load <=  !dcqmem_we_i;
                  load <=  !dcqmem_we_i;
               end
               end
 
 
 
 
          end // case: `OR1200_DCFSM_IDLE
          end // case: `OR1200_DCFSM_IDLE
 
 
          `OR1200_DCFSM_CLOADSTORE: begin
          `OR1200_DCFSM_CLOADSTORE: begin
             hitmiss_eval <=  1'b0;
             hitmiss_eval <=  1'b0;
             if (hitmiss_eval) begin
             if (hitmiss_eval) begin
                cache_inhibit <=  dcqmem_ci_i; // Check for cache inhibit here
                cache_inhibit <=  dcqmem_ci_i; // Check for cache inhibit here
                cache_miss <=  tagcomp_miss;
                cache_miss <=  tagcomp_miss;
                cache_dirty_needs_writeback <= dirty;
                cache_dirty_needs_writeback <= dirty;
                addr_r <=  lsu_addr;
                addr_r <=  lsu_addr;
             end
             end
 
 
             // Evaluate any cache line load/stores in first cycle:
             // Evaluate any cache line load/stores in first cycle:
                             //
                             //
             if (hitmiss_eval & tagcomp_miss & !(store & writethrough) &
             if (hitmiss_eval & tagcomp_miss & !(store & writethrough) &
                 !dcqmem_ci_i)
                 !dcqmem_ci_i)
               begin
               begin
                  // Miss - first either:
                  // Miss - first either:
                  //  1) write back dirty line 
                  //  1) write back dirty line 
                  if (dirty) begin
                  if (dirty) begin
                     // Address for writeback
                     // Address for writeback
                     addr_r <=  {tag, lsu_addr[`OR1200_DCINDXH:2],2'd0};
                     addr_r <=  {tag, lsu_addr[`OR1200_DCINDXH:2],2'd0};
                     load <= 1'b0;
                     load <= 1'b0;
                     store <= 1'b1;
                     store <= 1'b1;
`ifdef OR1200_VERBOSE
`ifdef OR1200_VERBOSE
                     $display("%t: dcache miss and dirty", $time);
                     $display("%t: dcache miss and dirty", $time);
`endif
`endif
                  end
                  end
                  //  2) load requested line
                  //  2) load requested line
                  else begin
                  else begin
                     addr_r <=  lsu_addr;
                     addr_r <=  lsu_addr;
                     load <= 1'b1;
                     load <= 1'b1;
                     store <= 1'b0;
                     store <= 1'b0;
                  end // else: !if(dirty)
                  end // else: !if(dirty)
                  state <= `OR1200_DCFSM_LOOP2;
                  state <= `OR1200_DCFSM_LOOP2;
                  // Set the counter for the burst accesses
                  // Set the counter for the burst accesses
                  cnt <=  `OR1200_DCLS-1;
                  cnt <=  ((1 << `OR1200_DCLS) - 4);
               end
               end
             else if (// Strobe goes low
             else if (// Strobe goes low
                      !dcqmem_cycstb_i |
                      !dcqmem_cycstb_i |
                      // Cycle finishes
                      // Cycle finishes
                      (!hitmiss_eval & (biudata_valid | biudata_error)) |
                      (!hitmiss_eval & (biudata_valid | biudata_error)) |
                      // Cache hit in first cycle....
                      // Cache hit in first cycle....
                      (hitmiss_eval & !tagcomp_miss & !dcqmem_ci_i &
                      (hitmiss_eval & !tagcomp_miss & !dcqmem_ci_i &
                      // .. and you're not doing a writethrough store..
                      // .. and you're not doing a writethrough store..
                      !(store & writethrough))) begin
                      !(store & writethrough))) begin
                state <=  `OR1200_DCFSM_IDLE;
                state <=  `OR1200_DCFSM_IDLE;
                load <=  1'b0;
                load <=  1'b0;
                store <= 1'b0;
                store <= 1'b0;
                cache_inhibit <= 1'b0;
                cache_inhibit <= 1'b0;
                cache_dirty_needs_writeback <= 1'b0;
                cache_dirty_needs_writeback <= 1'b0;
             end
             end
          end // case: `OR1200_DCFSM_CLOADSTORE   
          end // case: `OR1200_DCFSM_CLOADSTORE   
 
 
          `OR1200_DCFSM_LOOP2 : begin // loop/abort          
          `OR1200_DCFSM_LOOP2 : begin // loop/abort          
             if (!dc_en| biudata_error) begin
             if (!dc_en| biudata_error) begin
                state <=  `OR1200_DCFSM_IDLE;
                state <=  `OR1200_DCFSM_IDLE;
                load <=  1'b0;
                load <=  1'b0;
                store <= 1'b0;
                store <= 1'b0;
                cnt <= 3'd0;
                cnt <= `OR1200_DCLS'd0;
             end
             end
             if (biudata_valid & (|cnt)) begin
             if (biudata_valid & (|cnt)) begin
                cnt <=  cnt - 3'd1;
                cnt <=  cnt - 4;
                addr_r[3:2] <=  addr_r[3:2] + 1'b1;
                addr_r[`OR1200_DCLS-1:2] <=  addr_r[`OR1200_DCLS-1:2] + 1;
             end
             end
             else if (biudata_valid & !(|cnt)) begin
             else if (biudata_valid & !(|cnt)) begin
                state <= `OR1200_DCFSM_LOOP3;
                state <= `OR1200_DCFSM_LOOP3;
                addr_r <=  lsu_addr;
                addr_r <=  lsu_addr;
                load <= 1'b0;
                load <= 1'b0;
                store <= 1'b0;
                store <= 1'b0;
             end
             end
 
 
             // Track if we did an early ack during a load
             // Track if we did an early ack during a load
             if (load_miss_ack)
             if (load_miss_ack)
               did_early_load_ack <= 1'b1;
               did_early_load_ack <= 1'b1;
 
 
 
 
          end // case: `OR1200_DCFSM_LOOP2
          end // case: `OR1200_DCFSM_LOOP2
 
 
          `OR1200_DCFSM_LOOP3: begin // figure out next step
          `OR1200_DCFSM_LOOP3: begin // figure out next step
             if (cache_dirty_needs_writeback) begin
             if (cache_dirty_needs_writeback) begin
                // Just did store of the dirty line so now load new one
                // Just did store of the dirty line so now load new one
                load <= 1'b1;
                load <= 1'b1;
                // Set the counter for the burst accesses
                // Set the counter for the burst accesses
                cnt <=  `OR1200_DCLS-1;
                cnt <=  ((1 << `OR1200_DCLS) - 4);
                // Address of line to be loaded
                // Address of line to be loaded
                addr_r <=  lsu_addr;
                addr_r <=  lsu_addr;
                cache_dirty_needs_writeback <= 1'b0;
                cache_dirty_needs_writeback <= 1'b0;
                state <= `OR1200_DCFSM_LOOP2;
                state <= `OR1200_DCFSM_LOOP2;
             end // if (cache_dirty_needs_writeback)
             end // if (cache_dirty_needs_writeback)
             else if (cache_spr_block_flush | cache_spr_block_writeback) begin
             else if (cache_spr_block_flush | cache_spr_block_writeback) begin
                // Just wrote back the line to memory, we're finished.
                // Just wrote back the line to memory, we're finished.
                cache_spr_block_flush <= 1'b0;
                cache_spr_block_flush <= 1'b0;
                cache_spr_block_writeback <= 1'b0;
                cache_spr_block_writeback <= 1'b0;
                state <= `OR1200_DCFSM_WAITSPRCS7;
                state <= `OR1200_DCFSM_WAITSPRCS7;
             end
             end
             else begin
             else begin
                // Just loaded a new line, finish up
                // Just loaded a new line, finish up
                did_early_load_ack <= 1'b0;
                did_early_load_ack <= 1'b0;
                state <= `OR1200_DCFSM_LOOP4;
                state <= `OR1200_DCFSM_LOOP4;
             end
             end
          end // case: `OR1200_DCFSM_LOOP3
          end // case: `OR1200_DCFSM_LOOP3
 
 
          `OR1200_DCFSM_LOOP4: begin
          `OR1200_DCFSM_LOOP4: begin
             state <=  `OR1200_DCFSM_IDLE;
             state <=  `OR1200_DCFSM_IDLE;
          end
          end
 
 
          `OR1200_DCFSM_FLUSH5: begin
          `OR1200_DCFSM_FLUSH5: begin
             hitmiss_eval <= 1'b0;
             hitmiss_eval <= 1'b0;
             if (hitmiss_eval & !tag_v)
             if (hitmiss_eval & !tag_v)
               begin
               begin
                  // Not even cached, just ignore
                  // Not even cached, just ignore
                  cache_spr_block_flush <= 1'b0;
                  cache_spr_block_flush <= 1'b0;
                  cache_spr_block_writeback <= 1'b0;
                  cache_spr_block_writeback <= 1'b0;
                  state <=  `OR1200_DCFSM_WAITSPRCS7;
                  state <=  `OR1200_DCFSM_WAITSPRCS7;
               end
               end
             else if (hitmiss_eval & tag_v)
             else if (hitmiss_eval & tag_v)
               begin
               begin
                  // Tag is valid - what do we do?
                  // Tag is valid - what do we do?
                  if ((cache_spr_block_flush | cache_spr_block_writeback) &
                  if ((cache_spr_block_flush | cache_spr_block_writeback) &
                      dirty) begin
                      dirty) begin
                     // Need to writeback
                     // Need to writeback
                     // Address for writeback (spr_dat_i has already changed so
                     // Address for writeback (spr_dat_i has already changed so
                     // use line number from addr_r)
                     // use line number from addr_r)
                     addr_r <=  {tag, addr_r[`OR1200_DCINDXH:2],2'd0};
                     addr_r <=  {tag, addr_r[`OR1200_DCINDXH:2],2'd0};
                     load <= 1'b0;
                     load <= 1'b0;
                     store <= 1'b1;
                     store <= 1'b1;
`ifdef OR1200_VERBOSE
`ifdef OR1200_VERBOSE
                     $display("%t: block flush: dirty block", $time);
                     $display("%t: block flush: dirty block", $time);
`endif
`endif
                     state <= `OR1200_DCFSM_LOOP2;
                     state <= `OR1200_DCFSM_LOOP2;
                     // Set the counter for the burst accesses
                     // Set the counter for the burst accesses
                     cnt <=  `OR1200_DCLS-1;
                     cnt <=  ((1 << `OR1200_DCLS) - 4);
                  end
                  end
                  else if (cache_spr_block_flush & !dirty)
                  else if (cache_spr_block_flush & !dirty)
                    begin
                    begin
                       // Line not dirty, just need to invalidate
                       // Line not dirty, just need to invalidate
                       state <=  `OR1200_DCFSM_INV6;
                       state <=  `OR1200_DCFSM_INV6;
                    end // else: !if(dirty)
                    end // else: !if(dirty)
                  else if (cache_spr_block_writeback & !dirty)
                  else if (cache_spr_block_writeback & !dirty)
                    begin
                    begin
                       // Nothing to do - line is valid but not dirty
                       // Nothing to do - line is valid but not dirty
                       cache_spr_block_writeback <= 1'b0;
                       cache_spr_block_writeback <= 1'b0;
                       state <=  `OR1200_DCFSM_WAITSPRCS7;
                       state <=  `OR1200_DCFSM_WAITSPRCS7;
                    end
                    end
          end // if (hitmiss_eval & tag_v)
          end // if (hitmiss_eval & tag_v)
          end
          end
          `OR1200_DCFSM_INV6: begin
          `OR1200_DCFSM_INV6: begin
             cache_spr_block_flush <= 1'b0;
             cache_spr_block_flush <= 1'b0;
             // Wait until SPR CS goes low before going back to idle
             // Wait until SPR CS goes low before going back to idle
             if (!spr_cswe)
             if (!spr_cswe)
               state <=  `OR1200_DCFSM_IDLE;
               state <=  `OR1200_DCFSM_IDLE;
          end
          end
          `OR1200_DCFSM_WAITSPRCS7: begin
          `OR1200_DCFSM_WAITSPRCS7: begin
             // Wait until SPR CS goes low before going back to idle
             // Wait until SPR CS goes low before going back to idle
             if (!spr_cswe)
             if (!spr_cswe)
               state <=  `OR1200_DCFSM_IDLE;
               state <=  `OR1200_DCFSM_IDLE;
          end
          end
 
 
        endcase // case (state)
        endcase // case (state)
 
 
   end // always @ (posedge clk or `OR1200_RST_EVENT rst)
   end // always @ (posedge clk or `OR1200_RST_EVENT rst)
 
 
 
 
endmodule
endmodule
 
 

powered by: WebSVN 2.1.0

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