summaryrefslogtreecommitdiff
path: root/rtl/core/mmu/arbiter.sv
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-11-15 16:28:30 -0600
committerAlejandro Soto <alejandro@34project.org>2022-11-15 16:28:30 -0600
commit1d08cc6aff97a24bffa5ba5b578c52bb545fc393 (patch)
tree84884ab3452692afe143e113d658b313235d4bb1 /rtl/core/mmu/arbiter.sv
parent044558e53d50ebd053abc76930723c9d7f606569 (diff)
Rename existing MMU components to MMU arbiter
Diffstat (limited to '')
-rw-r--r--rtl/core/mmu/arbiter.sv113
1 files changed, 113 insertions, 0 deletions
diff --git a/rtl/core/mmu/arbiter.sv b/rtl/core/mmu/arbiter.sv
new file mode 100644
index 0000000..3740539
--- /dev/null
+++ b/rtl/core/mmu/arbiter.sv
@@ -0,0 +1,113 @@
+module core_mmu_arbiter
+(
+ input logic clk,
+ rst_n,
+
+ input logic bus_ready,
+ input word bus_data_rd,
+ data_data_wr,
+ input ptr insn_addr,
+ data_addr,
+ input logic insn_start,
+ data_start,
+ data_write,
+
+ output word bus_data_wr,
+ output ptr bus_addr,
+ output logic bus_start,
+ bus_write,
+ insn_ready,
+ data_ready,
+ output word insn_data_rd,
+ data_data_rd
+);
+
+ enum int unsigned
+ {
+ INSN,
+ DATA
+ } master, next_master;
+
+ ptr hold_addr;
+ word hold_data_wr;
+ logic active, hold_start, hold_write, hold_issue, hold_free, transition;
+
+ assign insn_data_rd = bus_data_rd;
+ assign data_data_rd = bus_data_rd;
+
+ always_comb begin
+ next_master = master;
+ if(bus_ready || !active)
+ unique case(master)
+ DATA: next_master = data_start ? DATA : INSN;
+ INSN: next_master = !data_start && !hold_start ? INSN : DATA;
+ endcase
+
+ // Causa UNOPTFLAT en Verilator con assign
+ transition = master != next_master;
+ hold_issue = transition && hold_start;
+ hold_free = transition || !hold_start;
+
+ insn_ready = 0;
+ data_ready = 0;
+
+ unique case(master)
+ INSN: insn_ready = bus_ready;
+ DATA: data_ready = bus_ready;
+ endcase
+
+ unique case(next_master)
+ INSN: begin
+ bus_addr = insn_addr;
+ bus_write = 0;
+ bus_start = insn_start;
+ bus_data_wr = {32{1'bx}};
+ end
+
+ DATA: begin
+ bus_addr = data_addr;
+ bus_write = data_write;
+ bus_start = data_start;
+ bus_data_wr = data_data_wr;
+ end
+ endcase
+
+ if(hold_issue) begin
+ bus_addr = hold_addr;
+ bus_write = hold_write;
+ bus_start = 1;
+ bus_data_wr = hold_data_wr;
+ end
+ end
+
+ always_ff @(posedge clk or negedge rst_n)
+ if(!rst_n) begin
+ master <= INSN;
+ active <= 0;
+
+ hold_addr <= 30'b0;
+ hold_start <= 0;
+ hold_write <= 0;
+ hold_data_wr <= 0;
+ end else begin
+ master <= next_master;
+ active <= bus_start || (active && !bus_ready);
+
+ if(hold_free)
+ unique case(next_master)
+ INSN: begin
+ hold_addr <= data_addr;
+ hold_start <= data_start;
+ hold_write <= data_write;
+ hold_data_wr <= data_data_wr;
+ end
+
+ DATA: begin
+ hold_addr <= insn_addr;
+ hold_start <= insn_start;
+ hold_write <= 0;
+ end
+ endcase
+ end
+
+endmodule