blob: 80bb30b0d568ecf755ee8574765ca8c8fd7856fd [file] [log] [blame]
// SPDX-FileCopyrightText: 2022 Piotr Wegrzyn
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0
`include "config.v"
module mem_dcache_arb (
`ifdef USE_POWER_PINS
inout vccd1,
inout vssd1,
`endif
input i_clk,
input i_rst,
output mem_req,
output reg mem_we,
input mem_ack,
output reg [`WB_ADDR_W-1:0] mem_addr,
output reg [`RW-1:0] mem_o_data,
input [`RW-1:0] mem_i_data,
output reg [1:0] mem_sel,
output reg mem_cache_enable,
input mem_exception,
input mem0_req,
input mem0_we,
output reg mem0_ack,
input [`WB_ADDR_W-1:0] mem0_addr,
input [`RW-1:0] mem0_o_data,
output reg [`RW-1:0] mem0_i_data,
input [1:0] mem0_sel,
input mem0_cache_enable,
output reg mem0_exception,
input mem1_req,
input mem1_we,
output reg mem1_ack,
input [`WB_ADDR_W-1:0] mem1_addr,
input [`RW-1:0] mem1_o_data,
output reg [`RW-1:0] mem1_i_data,
input [1:0] mem1_sel,
input mem1_cache_enable,
output reg mem1_exception
);
wire request_term = mem_ack | mem_exception;
reg select, transfer_active;
reg req0_pending, req1_pending;
wire req_w = mem0_req | mem1_req | req0_pending | req1_pending;
wire req_start = ~transfer_active & req_w;
assign mem_req = req_start;
always @(posedge i_clk) begin
if (i_rst) begin
select <= 1'b0;
transfer_active <= 1'b0;
end else if (req_start & ~request_term) begin
select <= req_sel;
transfer_active <= 1'b1;
end else if (transfer_active & request_term) begin
transfer_active <= 1'b0;
end
end
always @(posedge i_clk) begin
if (i_rst) begin
req0_pending <= 1'b0;
req1_pending <= 1'b0;
end else if (req_start & ~req_sel) begin
req0_pending <= 1'b0;
req1_pending <= req1_pending | mem1_req;
end else if (req_start & req_sel) begin
req1_pending <= 1'b0;
req0_pending <= req0_pending | mem0_req;
end else if (transfer_active) begin
req0_pending <= (req0_pending | mem0_req) & select;
req1_pending <= (req1_pending | mem1_req) & ~select;
end
end
reg req_sel;
always @* begin // round robin
if (select == 1'b0 && (mem1_req | req1_pending))
req_sel = 1'b1;
else if (select == 1'b1 && (mem0_req | req0_pending))
req_sel = 1'b0;
else if (mem0_req | req0_pending)
req_sel = 1'b0;
else if (mem1_req | req1_pending)
req_sel = 1'b1;
else
req_sel = 1'b0;
end
wire select_wire = (req_start ? req_sel : select);
always @(*) begin
{mem0_ack, mem0_i_data, mem0_exception, mem1_ack, mem1_i_data, mem1_exception} = 'b0;
if(~select_wire) begin
mem_we = mem0_we;
mem_addr = mem0_addr;
mem_o_data = mem0_o_data;
mem_sel = mem0_sel;
mem_cache_enable = mem0_cache_enable;
mem0_ack = mem_ack;
mem0_i_data = mem_i_data;
mem0_exception = mem_exception;
end else begin
mem_we = mem1_we;
mem_addr = mem1_addr;
mem_o_data = mem1_o_data;
mem_sel = mem1_sel;
mem_cache_enable = mem1_cache_enable;
mem1_ack = mem_ack;
mem1_i_data = mem_i_data;
mem1_exception = mem_exception;
end
end
endmodule