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

Subversion Repositories altor32

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

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

Rev 27 Rev 32
Line 47... Line 47...
 
 
    // Input (CPU)
    // Input (CPU)
    input [31:0]    address_i /*verilator public*/,
    input [31:0]    address_i /*verilator public*/,
    output [31:0]   data_o /*verilator public*/,
    output [31:0]   data_o /*verilator public*/,
    input [31:0]    data_i /*verilator public*/,
    input [31:0]    data_i /*verilator public*/,
    input           rd_i /*verilator public*/,
    input           we_i /*verilator public*/,
    input [3:0]     wr_i /*verilator public*/,
    input           stb_i /*verilator public*/,
    output          accept_o /*verilator public*/,
    input [3:0]     sel_i /*verilator public*/,
 
    output          stall_o /*verilator public*/,
    output          ack_o /*verilator public*/,
    output          ack_o /*verilator public*/,
 
 
    // Output (Memory)
    // Output (Memory)
    output [31:0]   mem_addr_o /*verilator public*/,
    output [31:0]   mem_addr_o /*verilator public*/,
    input [31:0]    mem_data_i /*verilator public*/,
    input [31:0]    mem_data_i /*verilator public*/,
    output [31:0]   mem_data_o /*verilator public*/,
    output [31:0]   mem_data_o /*verilator public*/,
    output          mem_burst_o /*verilator public*/,
    output [2:0]    mem_cti_o /*verilator public*/,
    output          mem_rd_o /*verilator public*/,
    output          mem_cyc_o /*verilator public*/,
    output [3:0]    mem_wr_o /*verilator public*/,
    output          mem_stb_o /*verilator public*/,
    input           mem_accept_i/*verilator public*/,
    output          mem_we_o /*verilator public*/,
 
    output [3:0]    mem_sel_o /*verilator public*/,
 
    input           mem_stall_i/*verilator public*/,
    input           mem_ack_i/*verilator public*/
    input           mem_ack_i/*verilator public*/
);
);
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Params
// Params
Line 117... Line 120...
 
 
reg                              fill;
reg                              fill;
reg                              evict;
reg                              evict;
wire                             done;
wire                             done;
 
 
reg [31:0]                       data_w;
 
wire [31:0]                      data_r;
wire [31:0]                      data_r;
reg                              data_rd;
reg                              rd_single;
reg [3:0]                        data_wr;
reg [3:0]                        wr_single;
 
 
reg                              req_rd;
reg                              req_rd;
reg [3:0]                        req_wr;
reg [3:0]                        req_wr;
reg                              req_ack;
reg                              req_ack;
reg [31:0]                       req_address;
reg [31:0]                       req_address;
 
reg [31:0]                       req_data;
 
 
reg                              req_flush;
reg                              req_flush;
reg                              flush_single;
reg                              flush_single;
 
 
wire [31:0]                      line_address;
wire [31:0]                      line_address;
Line 155... Line 158...
 
 
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 accept_o                = (state == STATE_IDLE);
assign stall_o                 = (state != STATE_IDLE) | req_flush;
 
 
 
 
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?
wire cacheable                 = ~muxed_address[ADDR_NO_CACHE_BIT] & ~muxed_address[ADDR_CACHE_BYPASS_BIT];
wire cacheable                 = ~muxed_address[ADDR_NO_CACHE_BIT] & ~muxed_address[ADDR_CACHE_BYPASS_BIT];
 
 
 
// Address matches cache tag
 
wire addr_hit                  = (req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0]);
 
 
// Cache hit?
// Cache hit?
wire hit                       = cacheable & valid & (muxed_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0]) & (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[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}};
 
 
 
 
//-----------------------------------------------------------------
//-----------------------------------------------------------------
// Control logic
// Next State Logic
//-----------------------------------------------------------------
//-----------------------------------------------------------------
always @ (posedge rst_i or posedge clk_i )
reg [3:0] next_state_r;
begin
always @ *
   if (rst_i == 1'b1)
 
   begin
 
        data_w          <= 32'h00000000;
 
        data_wr         <= 4'h0;
 
        data_rd         <= 1'b0;
 
        req_address     <= 32'h00000000;
 
        req_ack         <= 1'b0;
 
        req_wr          <= 4'h0;
 
        req_rd          <= 1'b0;
 
        tag_wr          <= 1'b0;
 
        req_flush       <= 1'b0;
 
        flush_single    <= 1'b0;
 
        fill            <= 1'b0;
 
        evict           <= 1'b0;
 
        cache_data_w    <= 32'h00000000;
 
        cache_wr        <= 4'b0;
 
        ack             <= 1'b0;
 
        state           <= STATE_IDLE;
 
   end
 
   else
 
   begin
   begin
        ack             <= 1'b0;
    next_state_r = state;
        tag_wr          <= 1'b0;
 
        fill            <= 1'b0;
 
        evict           <= 1'b0;
 
        cache_wr        <= 4'b0;
 
        data_wr         <= 4'b0;
 
        data_rd         <= 1'b0;
 
 
 
        if (flush_i)
 
            req_flush       <= 1'b1;
 
 
 
        case (state)
        case (state)
 
 
            //-----------------------------------------
            //-----------------------------------------
            // IDLE
            // IDLE
            //-----------------------------------------
            //-----------------------------------------
            STATE_IDLE :
            STATE_IDLE :
            begin
            begin
 
        // Cache flush request
 
        if (flush_i | req_flush)
 
            next_state_r    = STATE_FLUSH2;
                // Read (uncacheable)
                // Read (uncacheable)
                if (rd_i & ~cacheable)
        else if (stb_i & ~we_i & ~cacheable)
                begin
            next_state_r    = STATE_SINGLE;
                    // Start read single from memory
 
                    req_address <= address_i;
 
                    req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0;
 
                    data_rd     <= 1'b1;
 
                    req_rd      <= 1'b1;
 
                    req_wr      <= 4'b0;
 
                    req_ack     <= 1'b1;
 
                    state       <= STATE_SINGLE;
 
                end
 
                // Read (cacheable)
                // Read (cacheable)
                else if (rd_i)
        else if (stb_i & ~we_i)
                begin
            next_state_r    = STATE_CHECK;
                    req_address <= address_i;
 
                    req_rd      <= 1'b1;
 
                    req_wr      <= 4'b0;
 
                    req_ack     <= 1'b1;
 
                    state       <= STATE_CHECK;
 
                end
 
                // Write (uncacheable)
                // Write (uncacheable)
                else if (wr_i != 4'b0000 & ~cacheable)
        else if (stb_i & we_i & ~cacheable)
                begin
            next_state_r    = STATE_SINGLE;
                    // Perform write single
 
                    req_address <= address_i;
 
                    req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0;
 
                    data_w      <= data_i;
 
                    data_wr     <= wr_i;
 
                    req_wr      <= wr_i;
 
                    req_rd      <= 1'b0;
 
                    req_ack     <= 1'b1;
 
                    state       <= STATE_SINGLE;
 
                end
 
                // Write (cacheable)
                // Write (cacheable)
                else if (wr_i != 4'b0000)
        else if (stb_i & we_i)
                begin
            next_state_r    = STATE_WRITE;
                    req_address <= address_i;
 
                    data_w      <= data_i;
 
                    req_wr      <= wr_i;
 
                    req_rd      <= 1'b0;
 
                    req_ack     <= 1'b0;
 
 
 
                    // Early ACK
 
                    ack         <= 1'b1;
 
 
 
                    state       <= STATE_WRITE;
 
                end
 
                // Cache flush request
 
                else if (flush_i | req_flush)
 
                begin
 
                    // Set to first line address
 
                    req_address <= 32'h00000000;
 
                    req_flush   <= 1'b0;
 
                    req_ack     <= 1'b0;
 
                    flush_single<= 1'b0;
 
                    state       <= STATE_FLUSH2;
 
                end
 
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // WRITE - Wait for write-thru to complete
            // WRITE - Wait for write-thru to complete
            //-----------------------------------------
            //-----------------------------------------
            STATE_WRITE :
            STATE_WRITE :
            begin
            begin
                // Cache hit
                // Cache hit
                if (valid &&
        if (valid & addr_hit)
                    (req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0]))
            next_state_r    = STATE_WAIT2;
                begin
 
                    // Update line already in cache
 
                    cache_data_w <= data_w;
 
                    cache_wr     <= req_wr;
 
 
 
                    // Mark line as dirty
 
                    tag_data_in  <= tag_data_out;
 
                    tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
 
                    tag_wr       <= 1'b1;
 
 
 
                    state        <= STATE_WAIT2;
 
                end
 
                // Cache dirty
                // Cache dirty
                else if (valid & dirty)
                else if (valid & dirty)
                begin
            next_state_r    = STATE_EVICTING;
                    // Evict cache line
 
                    evict       <= 1'b1;
 
                    state       <= STATE_EVICTING;
 
                end
 
                // Cache miss
                // Cache miss
                else
                else
                begin
            next_state_r    = STATE_UPDATE;
                    // 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_wr      <= 1'b1;
 
 
 
                    // Fill cache line
 
                    fill        <= 1'b1;
 
                    state       <= STATE_UPDATE;
 
                end
 
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // EVICTING - Evicting cache line
            // EVICTING - Evicting cache line
            //-----------------------------------------
            //-----------------------------------------
            STATE_EVICTING:
            STATE_EVICTING:
            begin
            begin
                // Data ready from memory?
                // Data ready from memory?
                if (done)
                if (done)
                begin
                begin
                    // Update tag memory with this new line's details   
 
                    tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
 
                    tag_wr      <= 1'b1;
 
 
 
                    // Fill cache line
 
                    fill        <= 1'b1;
 
 
 
                    // Evict for read?
                    // Evict for read?
                    if (req_rd)
                    if (req_rd)
                        state   <= STATE_FETCH;
                next_state_r   = STATE_FETCH;
                    // Evict for write
                    // Evict for write
                    else
                    else
                        state   <= STATE_UPDATE;
                next_state_r   = STATE_UPDATE;
                end
                end
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // UPDATE - Update fetched cache line
            // UPDATE - Update fetched cache line
            //-----------------------------------------
            //-----------------------------------------
            STATE_UPDATE:
            STATE_UPDATE:
            begin
            begin
                // Data ready from memory?
                // Data ready from memory?
                if (done)
                if (done)
                begin
            next_state_r    = STATE_WAIT2;
                    // Update line already in cache
 
                    cache_data_w <= data_w;
 
                    cache_wr     <= req_wr;
 
 
 
                    // Mark line as dirty
 
                    tag_data_in  <= tag_data_out;
 
                    tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
 
                    tag_wr       <= 1'b1;
 
 
 
                    state        <= STATE_WAIT2;
 
                end
 
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // CHECK - check cache for hit or miss
            // CHECK - check cache for hit or miss
            //-----------------------------------------
            //-----------------------------------------
            STATE_CHECK :
            STATE_CHECK :
            begin
            begin
                // Cache hit
                // Cache hit
                if (valid &&
        if (valid & addr_hit)
                    (req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW] == tag_data_out[13:0]))
            next_state_r    = STATE_IDLE;
                begin
 
                    state       <= STATE_IDLE;
 
                end
 
                // Cache dirty
                // Cache dirty
                else if (valid & dirty)
                else if (valid & dirty)
                begin
            next_state_r    = STATE_EVICTING;
                    // Evict cache line
 
                    evict       <= 1'b1;
 
                    state       <= STATE_EVICTING;
 
                end
 
                // Cache miss
                // Cache miss
                else
                else
                begin
            next_state_r    = STATE_FETCH;
                    // Update tag memory with this line's details   
 
                    tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
 
                    tag_wr      <= 1'b1;
 
 
 
                    // Fill cache line
 
                    fill        <= 1'b1;
 
                    state       <= STATE_FETCH;
 
                end
 
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // FETCH_SINGLE - Single access to memory
            // FETCH_SINGLE - Single access to memory
            //-----------------------------------------
            //-----------------------------------------
            STATE_SINGLE:
            STATE_SINGLE:
Line 398... Line 274...
                // Data ready from memory?
                // Data ready from memory?
                if (done)
                if (done)
                begin
                begin
                    // Single WRITE?
                    // Single WRITE?
                    if (~req_rd)
                    if (~req_rd)
                    begin
                next_state_r    = STATE_SINGLE_READY;
                        state       <= STATE_SINGLE_READY;
 
                        ack         <= req_ack;
 
                    end
 
                    // Dirty? Write back
                    // Dirty? Write back
                    else if (valid & dirty)
            else if (valid & dirty & addr_hit)
                    begin
                next_state_r    = STATE_FLUSH4;
                        // Evict cache line
 
                        evict       <= 1'b1;
 
                        flush_single<= 1'b1;
 
                        state       <= STATE_FLUSH4;
 
                    end
 
                    // Valid line, invalidate
                    // Valid line, invalidate
                    else if (valid)
            else if (valid & addr_hit)
                    begin
                next_state_r    = STATE_SINGLE_READY;
                        tag_data_in  <= tag_data_out;
 
                        tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
 
                        tag_wr       <= 1'b1;
 
 
 
                        state       <= STATE_SINGLE_READY;
 
                        ack         <= req_ack;
 
                    end
 
                    else
                    else
                    begin
                next_state_r    = STATE_SINGLE_READY;
                        state       <= STATE_SINGLE_READY;
 
                        ack         <= req_ack;
 
                    end
 
                end
                end
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // FETCH - Fetch row from memory
            // FETCH - Fetch row from memory
            //-----------------------------------------
            //-----------------------------------------
            STATE_FETCH :
            STATE_FETCH :
            begin
            begin
                // Cache line filled?
                // Cache line filled?
                if (done)
                if (done)
                   state    <= STATE_WAIT;
           next_state_r = STATE_WAIT;
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // WAIT - Wait cycle
            // WAIT - Wait cycle
            //-----------------------------------------
            //-----------------------------------------
            STATE_WAIT :
            STATE_WAIT :
            begin
            begin
                // Allow extra wait state to handle write & read collision               
                // Allow extra wait state to handle write & read collision               
                state   <= STATE_WAIT2;
        next_state_r    = STATE_WAIT2;
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // WAIT2 - Wait cycle
            // WAIT2 - Wait cycle
            //-----------------------------------------
            //-----------------------------------------
            STATE_WAIT2 :
            STATE_WAIT2 :
            begin
            begin
                state   <= STATE_IDLE;
        next_state_r    = STATE_IDLE;
                ack     <= req_ack;
 
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // SINGLE_READY - Uncached access ready
            // SINGLE_READY - Uncached access ready
            //-----------------------------------------
            //-----------------------------------------
            STATE_SINGLE_READY :
            STATE_SINGLE_READY :
            begin
            begin
                // Allow extra wait state to handle write & read collision               
                // Allow extra wait state to handle write & read collision               
                state   <= STATE_IDLE;
        next_state_r    = STATE_IDLE;
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // FLUSHx - Flush dirty lines & invalidate
            // FLUSHx - Flush dirty lines & invalidate
            //-----------------------------------------
            //-----------------------------------------
            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
            next_state_r    = STATE_WAIT;
                    req_ack <= 1'b0;
 
                    state   <= STATE_WAIT;
 
                end
 
                else
                else
                begin
            next_state_r    = STATE_FLUSH2;
                    // 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] + 1;
 
 
 
                    state   <= STATE_FLUSH2;
 
                end
 
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // FLUSH2 - Wait state
            // FLUSH2 - Wait state
            //-----------------------------------------
            //-----------------------------------------
            STATE_FLUSH2 :
            STATE_FLUSH2 :
            begin
            begin
                // Allow a cycle to read line state
                // Allow a cycle to read line state
                state   <= STATE_FLUSH3;
        next_state_r    = STATE_FLUSH3;
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // 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)
                begin
            next_state_r    = STATE_FLUSH4;
                    // Evict cache line
 
                    evict       <= 1'b1;
 
                    state       <= STATE_FLUSH4;
 
                end
 
                // Not dirty? Just invalidate
                // Not dirty? Just invalidate
                else
                else
                begin
                begin
                    tag_data_in  <= tag_data_out;
 
                    tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
 
                    tag_wr       <= 1'b1;
 
 
 
                    if (flush_single)
                    if (flush_single)
                        state    <= STATE_WAIT;
                next_state_r    = STATE_WAIT;
                    else
                    else
                        state    <= STATE_FLUSH1;
                next_state_r    = STATE_FLUSH1;
                end
                end
            end
            end
            //-----------------------------------------
            //-----------------------------------------
            // FLUSH4 - Wait for line flush to complete
            // FLUSH4 - Wait for line flush to complete
            //-----------------------------------------            
            //-----------------------------------------            
            STATE_FLUSH4 :
            STATE_FLUSH4 :
            begin
            begin
                // Cache line filled?
                // Cache line filled?
                if (done)
                if (done)
                begin
                begin
                    // Invalidate line
            if (flush_single)
 
                next_state_r    = STATE_SINGLE_READY;
 
            else
 
                next_state_r    = STATE_FLUSH1;
 
        end
 
    end
 
 
 
    default:
 
        ;
 
   endcase
 
end
 
 
 
// Update state
 
always @ (posedge rst_i or posedge clk_i )
 
begin
 
   if (rst_i == 1'b1)
 
        state   <= STATE_IDLE;
 
   else
 
        state   <= next_state_r;
 
end
 
 
 
//-----------------------------------------------------------------
 
// Tag Write
 
//-----------------------------------------------------------------
 
always @ (posedge rst_i or posedge clk_i )
 
begin
 
   if (rst_i == 1'b1)
 
   begin
 
        tag_data_in     <= 16'b0;
 
        tag_wr          <= 1'b0;
 
   end
 
   else
 
   begin
 
        tag_wr          <= 1'b0;
 
 
 
        case (state)
 
        //-----------------------------------------
 
        // WRITE - Wait for write-thru to complete
 
        //-----------------------------------------
 
        STATE_WRITE :
 
        begin
 
            // Cache hit
 
            if (valid & addr_hit)
 
            begin
 
                // Mark line as dirty
                    tag_data_in  <= tag_data_out;
                    tag_data_in  <= tag_data_out;
                    tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
                tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
                    tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b0;
                tag_wr       <= 1'b1;
 
            end
 
            // Cache miss / cache line doesn't require write back
 
            else if (~valid | ~dirty)
 
            begin
 
                // 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_wr      <= 1'b1;
 
            end
 
        end
 
        //-----------------------------------------
 
        // EVICTING - Evicting cache line
 
        //-----------------------------------------
 
        STATE_EVICTING:
 
        begin
 
            // Data ready from memory?
 
            if (done)
 
            begin
 
                // Update tag memory with this new line's details   
 
                tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
 
                tag_wr      <= 1'b1;
 
            end
 
        end
 
        //-----------------------------------------
 
        // UPDATE - Update fetched cache line
 
        //-----------------------------------------
 
        STATE_UPDATE:
 
        begin
 
            // Data ready from memory?
 
            if (done)
 
            begin
 
                // Mark line as dirty
 
                tag_data_in  <= tag_data_out;
 
                tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b1;
                    tag_wr       <= 1'b1;
                    tag_wr       <= 1'b1;
 
            end
 
        end
 
        //-----------------------------------------
 
        // CHECK - check cache for hit or miss
 
        //-----------------------------------------
 
        STATE_CHECK :
 
        begin
 
            // Cache hit
 
            if (valid & addr_hit)
 
            begin
 
 
                    if (flush_single)
            end
 
            // Cache miss / cache line doesn't require write back
 
            else if (~valid | ~dirty)
                    begin
                    begin
                        state   <= STATE_SINGLE_READY;
                // Update tag memory with this line's details   
                        ack     <= req_ack;
                tag_data_in <= {1'b1, 1'b0, req_address[CACHE_TAG_ADDR_HIGH:CACHE_TAG_ADDR_LOW]};
 
                tag_wr      <= 1'b1;
                    end
                    end
                    else
 
                        state   <= STATE_FLUSH1;
 
                end
                end
 
        //-----------------------------------------
 
        // FETCH_SINGLE - Single access to memory
 
        //-----------------------------------------
 
        STATE_SINGLE:
 
        begin
 
            // Data ready from memory?
 
            if (done)
 
            begin
 
                // Single WRITE?
 
                if (~req_rd)
 
                begin
 
                    // Invalidate cached version
 
                    if (valid & addr_hit)
 
                    begin
 
                        tag_data_in  <= tag_data_out;
 
                        tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
 
                        tag_wr       <= 1'b1;
 
                    end
 
                end
 
                // Valid line (not dirty), just invalidate
 
                else if (valid & ~dirty & addr_hit)
 
                begin
 
                    tag_data_in  <= tag_data_out;
 
                    tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
 
                    tag_wr       <= 1'b1;
 
                end
 
            end
 
        end
 
 
 
        //-----------------------------------------
 
        // FLUSH3 - Check if line dirty & flush
 
        //-----------------------------------------            
 
        STATE_FLUSH3 :
 
        begin
 
            // Not dirty? Just invalidate
 
            if (~dirty)
 
            begin
 
                tag_data_in  <= tag_data_out;
 
                tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
 
                tag_wr       <= 1'b1;
 
            end
 
        end
 
        //-----------------------------------------
 
        // FLUSH4 - Wait for line flush to complete
 
        //-----------------------------------------            
 
        STATE_FLUSH4 :
 
        begin
 
            // Cache line filled?
 
            if (done)
 
            begin
 
                // Invalidate line
 
                tag_data_in  <= tag_data_out;
 
                tag_data_in[CACHE_TAG_VALID_BIT] <= 1'b0;
 
                tag_data_in[CACHE_TAG_DIRTY_BIT] <= 1'b0;
 
                tag_wr       <= 1'b1;
 
            end
 
        end
 
        default:
 
            ;
 
       endcase
 
   end
 
end
 
 
 
//-----------------------------------------------------------------
 
// Register requests
 
//-----------------------------------------------------------------
 
always @ (posedge rst_i or posedge clk_i )
 
begin
 
   if (rst_i == 1'b1)
 
   begin
 
        req_address     <= 32'h00000000;
 
        req_data        <= 32'h00000000;
 
        req_ack         <= 1'b0;
 
        req_wr          <= 4'h0;
 
        req_rd          <= 1'b0;
 
        req_flush       <= 1'b0;
 
   end
 
   else
 
   begin
 
        if (flush_i)
 
            req_flush       <= 1'b1;
 
 
 
        case (state)
 
        //-----------------------------------------
 
        // IDLE
 
        //-----------------------------------------
 
        STATE_IDLE :
 
        begin
 
            // Cache flush request
 
            if (flush_i | req_flush)
 
            begin
 
                // Set to first line address
 
                req_address <= 32'h00000000;
 
                req_flush   <= 1'b0;
 
                req_ack     <= 1'b0;
 
            end
 
            // Read (uncacheable)
 
            else if (stb_i & ~we_i & ~cacheable)
 
            begin
 
                // Start read single from memory
 
                req_address <= address_i;
 
                req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0;
 
                req_rd      <= 1'b1;
 
                req_wr      <= 4'b0;
 
                req_ack     <= 1'b1;
 
            end
 
            // Read (cacheable)
 
            else if (stb_i & ~we_i)
 
            begin
 
                req_address <= address_i;
 
                req_rd      <= 1'b1;
 
                req_wr      <= 4'b0;
 
                req_ack     <= 1'b1;
 
            end
 
            // Write (uncacheable)
 
            else if (stb_i & we_i & ~cacheable)
 
            begin
 
                // Perform write single
 
                req_address <= address_i;
 
                req_address[ADDR_CACHE_BYPASS_BIT] <= 1'b0;
 
                req_data    <= data_i;
 
                req_wr      <= sel_i;
 
                req_rd      <= 1'b0;
 
                req_ack     <= 1'b1;
 
            end
 
            // Write (cacheable)
 
            else if (stb_i & we_i)
 
            begin
 
                req_address <= address_i;
 
                req_data    <= data_i;
 
                req_wr      <= sel_i;
 
                req_rd      <= 1'b0;
 
                req_ack     <= 1'b0;
 
            end
 
        end
 
        //-----------------------------------------
 
        // FLUSHx - Flush dirty lines & invalidate
 
        //-----------------------------------------
 
        STATE_FLUSH1 :
 
        begin
 
            if (req_address[CACHE_LINE_ADDR_WIDTH + CACHE_LINE_SIZE_WIDTH - 1:CACHE_LINE_SIZE_WIDTH] == {CACHE_LINE_ADDR_WIDTH{1'b1}})
 
            begin
 
                req_ack <= 1'b0;
 
            end
 
            else
 
            begin
 
                // 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] + 1;
 
            end
 
        end
 
        default:
 
            ;
 
       endcase
 
   end
 
end
 
 
 
//-----------------------------------------------------------------
 
// Cache Data Write
 
//-----------------------------------------------------------------
 
always @ (posedge rst_i or posedge clk_i )
 
begin
 
   if (rst_i == 1'b1)
 
   begin
 
        cache_data_w    <= 32'h00000000;
 
        cache_wr        <= 4'b0;
 
   end
 
   else
 
   begin
 
        cache_wr        <= 4'b0;
 
 
 
        case (state)
 
        //-----------------------------------------
 
        // WRITE - Wait for write-thru to complete
 
        //-----------------------------------------
 
        STATE_WRITE :
 
        begin
 
            // Cache hit
 
            if (valid & addr_hit)
 
            begin
 
                // Update line already in cache
 
                cache_data_w <= req_data;
 
                cache_wr     <= req_wr;
 
            end
 
        end
 
        //-----------------------------------------
 
        // UPDATE - Update fetched cache line
 
        //-----------------------------------------
 
        STATE_UPDATE:
 
        begin
 
            // Data ready from memory?
 
            if (done)
 
            begin
 
                // Update line already in cache
 
                cache_data_w <= req_data;
 
                cache_wr     <= req_wr;
 
            end
 
        end
 
        default:
 
            ;
 
       endcase
 
   end
 
end
 
 
 
//-----------------------------------------------------------------
 
// Control
 
//-----------------------------------------------------------------
 
always @ (posedge rst_i or posedge clk_i )
 
begin
 
   if (rst_i == 1'b1)
 
   begin
 
        wr_single       <= 4'h0;
 
        rd_single       <= 1'b0;
 
        flush_single    <= 1'b0;
 
        fill            <= 1'b0;
 
        evict           <= 1'b0;
 
   end
 
   else
 
   begin
 
        fill            <= 1'b0;
 
        evict           <= 1'b0;
 
        wr_single       <= 4'b0;
 
        rd_single       <= 1'b0;
 
 
 
        case (state)
 
 
 
            //-----------------------------------------
 
            // IDLE
 
            //-----------------------------------------
 
            STATE_IDLE :
 
            begin
 
                // Cache flush request
 
                if (flush_i | req_flush)
 
                begin
 
                    // Set to first line address
 
                    flush_single<= 1'b0;
 
                end
 
                // Read (uncacheable)
 
                else if (stb_i & ~we_i & ~cacheable)
 
                begin
 
                    // Start read single from memory
 
                    rd_single     <= 1'b1;
 
                end
 
                // Write (uncacheable)
 
                else if (stb_i & we_i & ~cacheable)
 
                begin
 
                    // Perform write single
 
                    wr_single     <= sel_i;
 
                end
 
            end
 
            //-----------------------------------------
 
            // WRITE - Wait for write-thru to complete
 
            //-----------------------------------------
 
            STATE_WRITE :
 
            begin
 
                // Cache hit
 
                if (valid & addr_hit)
 
                begin
 
 
 
                end
 
                // Cache dirty
 
                else if (valid & dirty)
 
                begin
 
                    // Evict cache line
 
                    evict       <= 1'b1;
 
                end
 
                // Cache miss
 
                else
 
                begin
 
                    // Fill cache line
 
                    fill        <= 1'b1;
 
                end
 
            end
 
            //-----------------------------------------
 
            // EVICTING - Evicting cache line
 
            //-----------------------------------------
 
            STATE_EVICTING:
 
            begin
 
                // Data ready from memory?
 
                if (done)
 
                begin
 
                    // Fill cache line
 
                    fill        <= 1'b1;
 
                end
 
            end
 
            //-----------------------------------------
 
            // CHECK - check cache for hit or miss
 
            //-----------------------------------------
 
            STATE_CHECK :
 
            begin
 
                // Cache hit
 
                if (valid & addr_hit)
 
                begin
 
 
 
                end
 
                // Cache dirty
 
                else if (valid & dirty)
 
                begin
 
                    // Evict cache line
 
                    evict       <= 1'b1;
 
                end
 
                // Cache miss
 
                else
 
                begin
 
                    // Fill cache line
 
                    fill        <= 1'b1;
 
                end
 
            end
 
            //-----------------------------------------
 
            // FETCH_SINGLE - Single access to memory
 
            //-----------------------------------------
 
            STATE_SINGLE:
 
            begin
 
                // Data ready from memory?
 
                if (done)
 
                begin
 
                    // Single WRITE?
 
                    if (~req_rd)
 
                    begin
 
 
 
                    end
 
                    // Dirty? Write back
 
                    else if (valid & dirty & addr_hit)
 
                    begin
 
                        // Evict cache line
 
                        evict       <= 1'b1;
 
                        flush_single<= 1'b1;
 
                    end
 
                end
 
            end
 
            //-----------------------------------------
 
            // FLUSH3 - Check if line dirty & flush
 
            //-----------------------------------------            
 
            STATE_FLUSH3 :
 
            begin
 
                // Dirty line? Evict line first
 
                if (dirty)
 
                begin
 
                    // Evict cache line
 
                    evict       <= 1'b1;
 
                end
 
            end
 
            default:
 
                ;
 
           endcase
 
   end
 
end
 
 
 
//-----------------------------------------------------------------
 
// ACK
 
//-----------------------------------------------------------------
 
always @ (posedge rst_i or posedge clk_i )
 
begin
 
   if (rst_i == 1'b1)
 
        ack     <= 1'b0;
 
   else
 
   begin
 
        ack     <= 1'b0;
 
 
 
        case (state)
 
 
 
        //-----------------------------------------
 
        // IDLE
 
        //-----------------------------------------
 
        STATE_IDLE :
 
        begin
 
            // Write (cacheable), early acknowledge
 
            if (~(flush_i | req_flush) & stb_i & we_i & cacheable)
 
                ack <= 1'b1;
 
        end
 
        //-----------------------------------------
 
        // FETCH_SINGLE - Single access to memory
 
        //-----------------------------------------
 
        STATE_SINGLE:
 
        begin
 
            // Data ready from memory?
 
            if (done)
 
            begin
 
                // Single WRITE?
 
                if (~req_rd)
 
                    ack         <= req_ack;
 
                // Dirty? Write back
 
                else if (valid & dirty & addr_hit)
 
                begin
 
 
 
                end
 
                // Valid line, invalidate
 
                else if (valid & addr_hit)
 
                    ack         <= req_ack;
 
                else
 
                    ack         <= req_ack;
 
            end
 
        end
 
        //-----------------------------------------
 
        // WAIT2 - Wait cycle
 
        //-----------------------------------------
 
        STATE_WAIT2 :
 
        begin
 
            ack     <= req_ack;
 
        end
 
        //-----------------------------------------
 
        // FLUSH4 - Wait for line flush to complete
 
        //-----------------------------------------            
 
        STATE_FLUSH4 :
 
        begin
 
            if (done & flush_single)
 
                ack     <= req_ack;
            end
            end
            default:
            default:
                ;
                ;
           endcase
           endcase
   end
   end
Line 557... Line 892...
    .clk_i(clk_i),
    .clk_i(clk_i),
    .rst_i(rst_i),
    .rst_i(rst_i),
 
 
    // Cache interface
    // Cache interface
    .address_i(muxed_address),
    .address_i(muxed_address),
    .data_i(data_w),
    .data_i(req_data),
    .data_o(data_r),
    .data_o(data_r),
    .fill_i(fill),
    .fill_i(fill),
    .evict_i(evict),
    .evict_i(evict),
    .evict_addr_i(line_address),
    .evict_addr_i(line_address),
    .rd_single_i(data_rd),
    .rd_single_i(rd_single),
    .wr_single_i(data_wr),
    .wr_single_i(wr_single),
    .done_o(done),
    .done_o(done),
 
 
    // Cache memory (fill/evict)
    // Cache memory (fill/evict)
    .cache_addr_o(cache_update_addr),
    .cache_addr_o(cache_update_addr),
    .cache_data_o(cache_update_data_w),
    .cache_data_o(cache_update_data_w),
Line 576... Line 911...
 
 
    // Memory interface (slave)
    // Memory interface (slave)
    .mem_addr_o(mem_addr_o),
    .mem_addr_o(mem_addr_o),
    .mem_data_i(mem_data_i),
    .mem_data_i(mem_data_i),
    .mem_data_o(mem_data_o),
    .mem_data_o(mem_data_o),
    .mem_burst_o(mem_burst_o),
    .mem_cti_o(mem_cti_o),
    .mem_rd_o(mem_rd_o),
    .mem_cyc_o(mem_cyc_o),
    .mem_wr_o(mem_wr_o),
    .mem_stb_o(mem_stb_o),
    .mem_accept_i(mem_accept_i),
    .mem_we_o(mem_we_o),
 
    .mem_sel_o(mem_sel_o),
 
    .mem_stall_i(mem_stall_i),
    .mem_ack_i(mem_ack_i)
    .mem_ack_i(mem_ack_i)
);
);
 
 
// Tag memory    
// Tag memory    
altor32_ram_sp
altor32_ram_sp

powered by: WebSVN 2.1.0

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