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
|
`include "core/uarch.sv"
module core_cycles
(
input logic clk,
dec_execute,
dec_branch,
dec_writeback,
dec_update_flags,
input ptr dec_branch_offset,
input alu_decode dec_alu,
input ptr fetch_insn_pc,
input word rd_value_b,
output logic stall,
branch,
writeback,
update_flags,
output reg_num rd,
ra,
rb,
output ptr branch_target,
pc,
pc_visible,
output psr_mode reg_mode,
output alu_control alu,
output word alu_base,
output logic[7:0] alu_shift
);
enum
{
EXECUTE,
RD_SHIFT
} cycle, next_cycle;
logic final_writeback, data_snd_is_imm, data_snd_shift_by_reg;
logic[5:0] data_shift_imm;
logic[7:0] data_imm;
word saved_base;
reg_num r_shift;
assign stall = next_cycle != EXECUTE;
assign pc_visible = pc + 2;
assign reg_mode = `MODE_SVC; //TODO
always_comb begin
next_cycle = EXECUTE;
if((cycle == EXECUTE) & data_snd_shift_by_reg)
next_cycle = RD_SHIFT;
unique case(cycle)
RD_SHIFT:
alu_base = saved_base;
default:
if(data_snd_is_imm)
alu_base = {{24{1'b0}}, data_imm};
else
alu_base = rd_value_b;
endcase
unique case(cycle)
RD_SHIFT: alu_shift = rd_value_b[7:0];
default: alu_shift = {2'b00, data_shift_imm};
endcase
end
always_ff @(posedge clk) begin
cycle <= next_cycle;
unique case(next_cycle)
EXECUTE: begin
branch <= 0;
update_flags <= 0;
branch_target <= 30'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
final_writeback <= 0;
if(dec_execute) begin
branch <= dec_branch;
final_writeback <= dec_writeback;
update_flags <= dec_update_flags;
branch_target <= pc_visible + dec_branch_offset;
data_snd_is_imm <= dec_alu.snd_is_imm;
data_snd_shift_by_reg <= dec_alu.snd_shift_by_reg;
data_imm <= dec_alu.imm;
data_shift_imm <= dec_alu.shift_imm;
alu.op <= dec_alu.op;
alu.shl <= dec_alu.shl;
alu.shr <= dec_alu.shr;
alu.ror <= dec_alu.ror;
alu.put_carry <= dec_alu.put_carry;
alu.sign_extend <= dec_alu.sign_extend;
rd <= dec_alu.rd;
ra <= dec_alu.rn;
rb <= dec_alu.r_snd;
r_shift <= dec_alu.r_shift;
end
writeback <= final_writeback;
pc <= fetch_insn_pc;
end
RD_SHIFT: begin
rb <= r_shift;
data_snd_shift_by_reg <= 0;
saved_base <= rd_value_b;
writeback <= 0;
end
endcase
end
initial begin
cycle = EXECUTE;
branch = 1;
writeback = 0;
data_snd_shift_by_reg = 0;
branch_target = 30'd0;
pc = 0;
end
endmodule
|