-
Notifications
You must be signed in to change notification settings - Fork 1
/
execute.v
177 lines (143 loc) · 3.51 KB
/
execute.v
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
`ifndef EXECUTE_V
`define EXECUTE_V
`include "header.v"
`include "alu.v"
// executes the instruction with the alu
module execute(
input clk,
input reset,
// mem-exec comms
input i_input_valid,
input [`ADDRESS_WIDTH-1:0] i_pc,
input [7:0] i_opcode,
input [`DATA_WIDTH-1:0] i_opA,
input [`DATA_WIDTH-1:0] i_opB,
input [3:0] i_dest_reg,
input [`ADDRESS_WIDTH-1:0] i_dest_addr,
output o_fetching,
// execute-writeback comms
input i_next_ready,
output o_res_valid,
output [7:0] o_opcode,
output [`DATA_WIDTH-1:0] o_res,
output [3:0] o_dest_reg,
output [`ADDRESS_WIDTH-1:0] o_dest_addr,
output o_ready
);
// ID state machine macros
`define ST_RESET 4'h0
`define ST_IDLE 4'h1
`define ST_NEW_INST 4'h2
`define ST_EXEC 4'h3
`define ST_END_INST 4'hF
// status registers
reg ready;
reg res_valid;
reg fetching;
reg state_idle;
// FSM registers
reg [3:0] reg_status = `ST_RESET;
reg [3:0] nxt_status = `ST_IDLE;
// info about current instruction
reg [`ADDRESS_WIDTH-1:0] curr_pc;
reg [7:0] opcode;
reg [`DATA_WIDTH-1:0] opA;
reg [`DATA_WIDTH-1:0] opB;
reg [3:0] dest_reg;
reg [3:0] dest_addr;
// inter-stage registers
reg [`DATA_WIDTH-1:0] res;
reg [7:0] out_opcode;
reg [3:0] out_dest_reg;
reg [`ADDRESS_WIDTH-1:0] out_dest_addr;
// alu comms
wire [`DATA_WIDTH-1:0] req_opA;
wire [`DATA_WIDTH-1:0] req_opB;
wire [2:0] req_cmd;
wire [`DATA_WIDTH-1:0] resp_res;
wire resp_valid;
wire alu_ready;
assign o_res_valid = res_valid;
assign o_ready = ready;
assign o_fetching = fetching;
assign o_opcode = out_opcode;
assign o_res = res;
assign o_dest_reg = out_dest_reg;
assign o_dest_addr = out_dest_addr;
// synchronous reset
always @(posedge clk && reset) begin
reg_status <= `ST_RESET;
end
// synchronous retrieve instruction
always @(posedge clk && i_input_valid) begin
if(state_idle) begin
reg_status = `ST_NEW_INST;
fetching = 1;
end
else
fetching = 0;
end
// when the buffer is full and the next stage is ready, pass the data
always @(posedge clk && i_next_ready && res_valid && !reset) begin
res_valid <= #20 0; // TODO: find a less hacky way to do this
end
// execute the instructions
always @(posedge clk) begin
//$display("STATE = %d",reg_status);
case (reg_status)
`ST_RESET: begin
reg_status = `ST_IDLE;
res_valid = 0;
fetching = 1;
curr_pc = 0;
end
`ST_IDLE: begin
state_idle = 1;
if (res_valid == 0 && curr_pc != 0) begin
res_valid = 1;
out_opcode = opcode;
out_dest_reg = dest_reg;
out_dest_addr = dest_addr;
end
end
`ST_NEW_INST: begin
$display("Getting ops!");
state_idle = 0;
opcode = i_opcode;
curr_pc = i_pc;
opA = i_opA;
opB = i_opB;
dest_reg = i_dest_reg;
dest_addr = i_dest_addr;
reg_status = `ST_EXEC;
end
`ST_EXEC: begin
case(opcode)
`OPC_XOR: begin
$display("XORing the SHIT out of those operands");
res = opA ^ opB;
end
`OPC_ADD: begin
end
`OPC_SUB: begin
end
default: begin
$display("OPCODE NOT IMPLEMENTED");
end
endcase
reg_status = `ST_IDLE;
end
endcase
end
alu my_alu(
.clk(clk),
.reset(reset),
.i_a(req_opA),
.i_b(req_opB),
.i_cmd(req_cmd),
.o_result(resp_res),
.o_valid(resp_valid),
.o_ready(alu_ready)
);
endmodule
`endif