1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
module core_mmu_arbiter
(
input logic clk,
rst_n,
input logic bus_ready,
bus_ex_fail,
input word bus_data_rd,
data_data_wr,
input ptr insn_addr,
data_addr,
input logic insn_start,
data_start,
data_write,
data_ex_lock,
input logic[3:0] data_data_be,
output word bus_data_wr,
output logic[3:0] bus_data_be,
output ptr bus_addr,
output logic bus_start,
bus_write,
bus_ex_lock,
insn_ready,
data_ready,
data_ex_fail,
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_ex_lock, hold_start, hold_write, hold_issue, hold_free, transition;
logic[3:0] hold_data_be;
assign data_ex_fail = bus_ex_fail;
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
bus_data_wr = data_data_wr;
unique case(next_master)
INSN: begin
bus_addr = insn_addr;
bus_write = 0;
bus_start = insn_start;
bus_data_be = 4'b1111;
bus_ex_lock = 0;
end
DATA: begin
bus_addr = data_addr;
bus_write = data_write;
bus_start = data_start;
bus_data_be = data_data_be;
bus_ex_lock = data_ex_lock;
end
endcase
if(hold_issue) begin
bus_addr = hold_addr;
bus_write = hold_write;
bus_start = 1;
bus_data_wr = hold_data_wr;
bus_data_be = hold_data_be;
bus_ex_lock = hold_ex_lock;
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;
hold_data_be <= 0;
hold_ex_lock <= 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;
hold_data_be <= data_data_be;
hold_ex_lock <= data_ex_lock;
end
DATA: begin
hold_addr <= insn_addr;
hold_start <= insn_start;
hold_write <= 0;
hold_data_be <= 4'b1111;
hold_ex_lock <= 0;
end
endcase
end
endmodule
|