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
|
module core_mmu
(
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;
//TODO
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
|