blob: 3a6a7486244327b46fb2d609dc11beedbab54e12 [file] [log] [blame]
/*
*
* This file is part of the Elpis processor project.
*
* Copyright © 2020-present. All rights reserved.
* Authors: Aurora Tomas and Rodrigo Huerta.
*
* This file is licensed under both the BSD-3 license for individual/non-commercial
* use. Full text of both licenses can be found in LICENSE file.
*/
`default_nettype none
`ifdef TESTS
`include "elpis/definitions.v"
`else
`include "/project/openlane/user_proj_example/../../verilog/rtl/elpis/definitions.v"
`endif
module arbiter(
input clk,
input reset,
output reg[19:0] mem_addr,
input[127:0] dcache_to_mem_data_in, // Input data from dCache
output reg[127:0] dcache_to_mem_data_out, // Output data to memory
output [127:0] mem_to_icache_data, // Output data to iCache
output [127:0] mem_to_dcache_data, // Output data to dCache
input[127:0] data_from_mem, // Input data from memory
input dcache_we,
output reg mem_we,
input icache_request,
input dcache_request,
input mem_ready,
output reg is_icache_ready,
output reg is_dcache_ready,
input reset_mem_req,
input hit_itlb_in,
input hit_dtlb_in,
input[19:0] itlb_physical_addr_in,
input[19:0] dtlb_physical_addr_in,
input dcache_re,
output reg is_mem_req
);
reg[2:0] arb_state, next_arb_state;
assign mem_to_icache_data = data_from_mem;
assign mem_to_dcache_data = data_from_mem;
always@(posedge clk) begin
if (reset || reset_mem_req) begin
arb_state <= `ARB_IDLE_STATE;
end
else arb_state <= next_arb_state;
end
always@(dcache_request or icache_request or hit_dtlb_in or hit_itlb_in or mem_ready or arb_state) begin
case(arb_state)
`ARB_IDLE_STATE: begin
if (dcache_request && hit_dtlb_in) next_arb_state <= `ARB_DCACHE_REQUEST;
else if (icache_request && hit_itlb_in) next_arb_state <= `ARB_ICACHE_REQUEST;
else next_arb_state <= `ARB_IDLE_STATE;
end
`ARB_DCACHE_REQUEST: begin
next_arb_state <= `ARB_DCACHE_WAIT;
end
`ARB_ICACHE_REQUEST: begin
next_arb_state <= `ARB_ICACHE_WAIT;
end
`ARB_DCACHE_WAIT: begin
if(mem_ready)begin
next_arb_state <= `ARB_IDLE_STATE;
end else begin
next_arb_state <= `ARB_DCACHE_WAIT;
end
end
`ARB_ICACHE_WAIT: begin
if(mem_ready) begin
next_arb_state <= `ARB_IDLE_STATE;
end else begin
next_arb_state <= `ARB_ICACHE_WAIT;
end
end
default: next_arb_state <= `ARB_IDLE_STATE;
endcase
end
always@(arb_state or mem_ready) begin
case(arb_state)
`ARB_IDLE_STATE: begin
is_dcache_ready <= 0;
is_icache_ready <= 0;
mem_we <= 0;
dcache_to_mem_data_out <= 0;
mem_addr <= 0;
is_mem_req <= 1'b0;
end
`ARB_DCACHE_REQUEST: begin
is_dcache_ready <= 0;
is_icache_ready <= 0;
mem_we <= dcache_we;
mem_addr <= dtlb_physical_addr_in;
dcache_to_mem_data_out <= dcache_to_mem_data_in;
is_mem_req <= 1'b1;
end
`ARB_ICACHE_REQUEST: begin
is_dcache_ready <= 0;
is_icache_ready <= 0;
mem_we <= 0;
mem_addr <= itlb_physical_addr_in;
dcache_to_mem_data_out <= 0;
is_mem_req <= 1'b1;
end
`ARB_DCACHE_WAIT: begin
if (mem_ready) begin
is_dcache_ready <= mem_ready;
is_mem_req <= 1'b0;
end else begin
is_dcache_ready <= 0;
is_mem_req <= 1'b1;
end
is_icache_ready <= 0;
mem_we <= dcache_we;
dcache_to_mem_data_out <= dcache_to_mem_data_in;
mem_addr <= dtlb_physical_addr_in;
end
`ARB_ICACHE_WAIT: begin
if (mem_ready) begin
is_icache_ready <= mem_ready;
is_mem_req <= 1'b0;
end else begin
is_icache_ready <= 0;
is_mem_req <= 1'b1;
end
is_dcache_ready <= 0;
mem_we <= 0;
dcache_to_mem_data_out <= 0;
mem_addr <= itlb_physical_addr_in;
end
default: begin
is_dcache_ready <= 0;
is_icache_ready <= 0;
mem_we <= 0;
dcache_to_mem_data_out <= 0;
mem_addr <= 0;
is_mem_req <= 1'b0;
end
endcase
end
endmodule