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

Subversion Repositories altor32

[/] [altor32/] [trunk/] [rtl/] [cpu/] [altor32_dcache.v] - Diff between revs 32 and 36

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

Rev 32 Rev 36
Line 1... Line 1...
//-----------------------------------------------------------------
//-----------------------------------------------------------------
//                           AltOR32 
//                           AltOR32 
//                Alternative Lightweight OpenRisc 
//                Alternative Lightweight OpenRisc 
//                            V2.0
//                            V2.1
//                     Ultra-Embedded.com
//                     Ultra-Embedded.com
//                   Copyright 2011 - 2013
//                   Copyright 2011 - 2014
//
//
//               Email: admin@ultra-embedded.com
//               Email: admin@ultra-embedded.com
//
//
//                       License: LGPL
//                       License: LGPL
//-----------------------------------------------------------------
//-----------------------------------------------------------------
Line 89... Line 89...
parameter CACHE_TAG_DIRTY_BIT       = 14;
parameter CACHE_TAG_DIRTY_BIT       = 14;
parameter CACHE_TAG_VALID_BIT       = 15;
parameter CACHE_TAG_VALID_BIT       = 15;
parameter ADDR_NO_CACHE_BIT         = 25;
parameter ADDR_NO_CACHE_BIT         = 25;
parameter ADDR_CACHE_BYPASS_BIT     = 31;
parameter ADDR_CACHE_BYPASS_BIT     = 31;
 
 
 
parameter FLUSH_INITIAL             = 0;
 
 
//  31          16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
//  31          16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
// |--------------|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
// |--------------|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
//  +--------------------+   +-------------------+   +-----------+      
//  +--------------------+   +-------------------+   +-----------+      
//    Tag entry                     Line address         Address 
//    Tag entry                     Line address         Address 
//       (15-bits)                    (8-bits)           within line 
//       (15-bits)                    (8-bits)           within line 
Line 131... Line 133...
reg                              req_ack;
reg                              req_ack;
reg [31:0]                       req_address;
reg [31:0]                       req_address;
reg [31:0]                       req_data;
reg [31:0]                       req_data;
 
 
reg                              req_flush;
reg                              req_flush;
 
reg                              req_init;
reg                              flush_single;
reg                              flush_single;
 
 
wire [31:0]                      line_address;
wire [31:0]                      line_address;
 
 
wire [31:0]                      muxed_address = (state == STATE_IDLE) ? address_i : req_address;
wire [31:0]                      muxed_address = (state == STATE_IDLE) ? address_i : req_address;
Line 158... Line 161...
 
 
assign tag_entry               = muxed_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH];
assign tag_entry               = muxed_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH];
assign cache_address           = {tag_entry, muxed_address[CACHE_LINE_SIZE_WIDTH-1:2]};
assign cache_address           = {tag_entry, muxed_address[CACHE_LINE_SIZE_WIDTH-1:2]};
 
 
assign data_o                  = (state == STATE_SINGLE_READY) ? data_r : cache_data_r;
assign data_o                  = (state == STATE_SINGLE_READY) ? data_r : cache_data_r;
assign stall_o                 = (state != STATE_IDLE) | req_flush;
assign stall_o                 = (state != STATE_IDLE) | req_flush | flush_i;
 
 
wire valid                     = tag_data_out[CACHE_TAG_VALID_BIT];
wire valid                     = tag_data_out[CACHE_TAG_VALID_BIT];
wire dirty                     = tag_data_out[CACHE_TAG_DIRTY_BIT];
wire dirty                     = tag_data_out[CACHE_TAG_DIRTY_BIT];
 
 
// Access is cacheable?
// Access is cacheable?
Line 174... Line 177...
// Cache hit?
// Cache hit?
wire hit                       = cacheable & valid & addr_hit & (state == STATE_CHECK);
wire hit                       = cacheable & valid & addr_hit & (state == STATE_CHECK);
 
 
assign ack_o                   = ack | hit;
assign ack_o                   = ack | hit;
 
 
 
assign line_address[31:CACHE_TAG_ADDR_HIGH+1] = {(31-CACHE_TAG_ADDR_HIGH){1'b0}};
assign line_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] = tag_entry;
assign line_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] = tag_entry;
assign line_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] = tag_data_out[13:0];
assign line_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] = tag_data_out[13:0];
assign line_address[CACHE_LINE_SIZE_WIDTH-1:0] = {CACHE_LINE_SIZE_WIDTH{1'b0}};
assign line_address[CACHE_LINE_SIZE_WIDTH-1:0] = {CACHE_LINE_SIZE_WIDTH{1'b0}};
 
 
 
// Only allow cache write when same line present in the write state
 
wire cache_wr_enable           = (state == STATE_WRITE) ? valid & addr_hit : 1'b1;
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Next State Logic
// Next State Logic
//-----------------------------------------------------------------
//-----------------------------------------------------------------
reg [3:0] next_state_r;
reg [3:0] next_state_r;
Line 210... Line 216...
        // Write (cacheable)
        // Write (cacheable)
        else if (stb_i & we_i)
        else if (stb_i & we_i)
            next_state_r    = STATE_WRITE;
            next_state_r    = STATE_WRITE;
    end
    end
    //-----------------------------------------
    //-----------------------------------------
    // WRITE - Wait for write-thru to complete
    // WRITE
    //-----------------------------------------
    //-----------------------------------------
    STATE_WRITE :
    STATE_WRITE :
    begin
    begin
        // Cache hit
        // Cache hit (line already dirty)
        if (valid & addr_hit)
        if (valid & addr_hit & dirty)
 
            next_state_r    = STATE_IDLE;
 
        // Cache hit, make line dirty
 
        else if (valid & addr_hit & ~dirty)
            next_state_r    = STATE_WAIT2;
            next_state_r    = STATE_WAIT2;
        // Cache dirty
        // Cache dirty
        else if (valid & dirty)
        else if (valid & dirty)
            next_state_r    = STATE_EVICTING;
            next_state_r    = STATE_EVICTING;
        // Cache miss
        // Cache miss
Line 341... Line 350...
    // FLUSH3 - Check if line dirty & flush
    // FLUSH3 - Check if line dirty & flush
    //-----------------------------------------            
    //-----------------------------------------            
    STATE_FLUSH3 :
    STATE_FLUSH3 :
    begin
    begin
        // Dirty line? Evict line first
        // Dirty line? Evict line first
        if (dirty)
        if (dirty && ~req_init)
            next_state_r    = STATE_FLUSH4;
            next_state_r    = STATE_FLUSH4;
        // Not dirty? Just invalidate
        // Not dirty? Just invalidate
        else
        else
        begin
        begin
            if (flush_single)
            if (flush_single)
Line 397... Line 406...
   begin
   begin
        tag_wr          <= 1'b0;
        tag_wr          <= 1'b0;
 
 
        case (state)
        case (state)
        //-----------------------------------------
        //-----------------------------------------
        // WRITE - Wait for write-thru to complete
        // WRITE
        //-----------------------------------------
        //-----------------------------------------
        STATE_WRITE :
        STATE_WRITE :
        begin
        begin
            // Cache hit
            // Cache hit
            if (valid & addr_hit)
            if (valid & addr_hit)
            begin
            begin
                // Mark line as dirty
                // Mark line as dirty
 
                if (~dirty)
 
                begin
                tag_data_in  <= tag_data_out;
                tag_data_in  <= tag_data_out;
                tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
                tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
                tag_wr       <= 1'b1;
                tag_wr       <= 1'b1;
            end
            end
 
            end
            // Cache miss / cache line doesn't require write back
            // Cache miss / cache line doesn't require write back
            else if (~valid | ~dirty)
            else if (~valid | ~dirty)
            begin
            begin
                // Update tag memory with this line's details   
                // Update tag memory with this line's details   
                tag_data_in <= {1'b1, 1'b1, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
                tag_data_in <= {1'b1, 1'b1, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
Line 497... Line 509...
        // FLUSH3 - Check if line dirty & flush
        // FLUSH3 - Check if line dirty & flush
        //-----------------------------------------            
        //-----------------------------------------            
        STATE_FLUSH3 :
        STATE_FLUSH3 :
        begin
        begin
            // Not dirty? Just invalidate
            // Not dirty? Just invalidate
            if (~dirty)
            if (~dirty | req_init)
            begin
            begin
                tag_data_in  <= tag_data_out;
                tag_data_in  <= 16'b0;
                tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
                tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
                tag_wr       <= 1'b1;
                tag_wr       <= 1'b1;
            end
            end
        end
        end
        //-----------------------------------------
        //-----------------------------------------
Line 513... Line 525...
        begin
        begin
            // Cache line filled?
            // Cache line filled?
            if (done)
            if (done)
            begin
            begin
                // Invalidate line
                // Invalidate line
                tag_data_in  <= tag_data_out;
                tag_data_in  <= 16'b0;
                tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
                tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
                tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b0;
                tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b0;
                tag_wr       <= 1'b1;
                tag_wr       <= 1'b1;
            end
            end
        end
        end
Line 537... Line 549...
        req_address     <= 32'h00000000;
        req_address     <= 32'h00000000;
        req_data        <= 32'h00000000;
        req_data        <= 32'h00000000;
        req_ack         <= 1'b0;
        req_ack         <= 1'b0;
        req_wr          <= 4'h0;
        req_wr          <= 4'h0;
        req_rd          <= 1'b0;
        req_rd          <= 1'b0;
        req_flush       <= 1'b0;
        req_flush       <= 1'b1;
 
        req_init        <= FLUSH_INITIAL;
   end
   end
   else
   else
   begin
   begin
        if (flush_i)
        if (flush_i)
            req_flush       <= 1'b1;
            req_flush       <= 1'b1;
Line 605... Line 618...
        STATE_FLUSH1 :
        STATE_FLUSH1 :
        begin
        begin
            if (req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] == {CACHE_LINE_ADDR_WIDTH{1'b1}})
            if (req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] == {CACHE_LINE_ADDR_WIDTH{1'b1}})
            begin
            begin
                req_ack <= 1'b0;
                req_ack <= 1'b0;
 
                req_init <= 1'b0;
            end
            end
            else
            else
            begin
            begin
                // Increment flush line address
                // Increment flush line address
                req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] <=
                req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] <=
Line 635... Line 649...
   begin
   begin
        cache_wr        <= 4'b0;
        cache_wr        <= 4'b0;
 
 
        case (state)
        case (state)
        //-----------------------------------------
        //-----------------------------------------
        // WRITE - Wait for write-thru to complete
        // IDLE
        //-----------------------------------------
        //-----------------------------------------
        STATE_WRITE :
        STATE_IDLE:
        begin
        begin
            // Cache hit
            // Write (cacheable)
            if (valid & addr_hit)
            if (stb_i & we_i & cacheable & ~(flush_i | req_flush))
            begin
            begin
                // Update line already in cache
                // Early write which is gated on line match
                cache_data_w <= req_data;
                cache_data_w <= data_i;
                cache_wr     <= req_wr;
                cache_wr     <= sel_i;
            end
            end
        end
        end
        //-----------------------------------------
        //-----------------------------------------
        // UPDATE - Update fetched cache line
        // UPDATE - Update fetched cache line
        //-----------------------------------------
        //-----------------------------------------
Line 713... Line 727...
                    // Perform write single
                    // Perform write single
                    wr_single     <= sel_i;
                    wr_single     <= sel_i;
                end
                end
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // WRITE - Wait for write-thru to complete
            // WRITE
            //-----------------------------------------
            //-----------------------------------------
            STATE_WRITE :
            STATE_WRITE :
            begin
            begin
                // Cache hit
                // Cache hit
                if (valid & addr_hit)
                if (valid & addr_hit)
Line 947... Line 961...
(
(
    .aclk_i(clk_i),
    .aclk_i(clk_i),
    .aadr_i(cache_address),
    .aadr_i(cache_address),
    .adat_o(cache_data_r[7:0]),
    .adat_o(cache_data_r[7:0]),
    .adat_i(cache_data_w[7:0]),
    .adat_i(cache_data_w[7:0]),
    .awr_i(cache_wr[0]),
    .awr_i(cache_wr[0] & cache_wr_enable),
 
 
    .bclk_i(clk_i),
    .bclk_i(clk_i),
    .badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
    .badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
    .bdat_o(cache_update_data_r[7:0]),
    .bdat_o(cache_update_data_r[7:0]),
    .bdat_i(cache_update_data_w[7:0]),
    .bdat_i(cache_update_data_w[7:0]),
Line 967... Line 981...
(
(
    .aclk_i(clk_i),
    .aclk_i(clk_i),
    .aadr_i(cache_address),
    .aadr_i(cache_address),
    .adat_o(cache_data_r[15:8]),
    .adat_o(cache_data_r[15:8]),
    .adat_i(cache_data_w[15:8]),
    .adat_i(cache_data_w[15:8]),
    .awr_i(cache_wr[1]),
    .awr_i(cache_wr[1] & cache_wr_enable),
 
 
    .bclk_i(clk_i),
    .bclk_i(clk_i),
    .badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
    .badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
    .bdat_o(cache_update_data_r[15:8]),
    .bdat_o(cache_update_data_r[15:8]),
    .bdat_i(cache_update_data_w[15:8]),
    .bdat_i(cache_update_data_w[15:8]),
Line 987... Line 1001...
(
(
    .aclk_i(clk_i),
    .aclk_i(clk_i),
    .aadr_i(cache_address),
    .aadr_i(cache_address),
    .adat_o(cache_data_r[23:16]),
    .adat_o(cache_data_r[23:16]),
    .adat_i(cache_data_w[23:16]),
    .adat_i(cache_data_w[23:16]),
    .awr_i(cache_wr[2]),
    .awr_i(cache_wr[2] & cache_wr_enable),
 
 
    .bclk_i(clk_i),
    .bclk_i(clk_i),
    .badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
    .badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
    .bdat_o(cache_update_data_r[23:16]),
    .bdat_o(cache_update_data_r[23:16]),
    .bdat_i(cache_update_data_w[23:16]),
    .bdat_i(cache_update_data_w[23:16]),
Line 1007... Line 1021...
(
(
    .aclk_i(clk_i),
    .aclk_i(clk_i),
    .aadr_i(cache_address),
    .aadr_i(cache_address),
    .adat_o(cache_data_r[31:24]),
    .adat_o(cache_data_r[31:24]),
    .adat_i(cache_data_w[31:24]),
    .adat_i(cache_data_w[31:24]),
    .awr_i(cache_wr[3]),
    .awr_i(cache_wr[3] & cache_wr_enable),
 
 
    .bclk_i(clk_i),
    .bclk_i(clk_i),
    .badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
    .badr_i(cache_update_addr[CACHE_DWIDTH+2-1:2]),
    .bdat_o(cache_update_data_r[31:24]),
    .bdat_o(cache_update_data_r[31:24]),
    .bdat_i(cache_update_data_w[31:24]),
    .bdat_i(cache_update_data_w[31:24]),

powered by: WebSVN 2.1.0

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