-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcontroller.v
More file actions
150 lines (148 loc) · 3.24 KB
/
controller.v
File metadata and controls
150 lines (148 loc) · 3.24 KB
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
`timescale 1ns / 1ps
`include "def.v"
module Controller(clk, reset,
memdata, memaddr, ireg_d0_lsb,
instr0, instr1, current_state,
cr, pc,
pc_update_req, pc_update_addr);
//
input clk, reset;
input [31:0] memdata;
input ireg_d0_lsb;
input pc_update_req;
input [15:0] pc_update_addr;
output reg [15:0] memaddr;
output reg [31:0] instr0 = 0;
output reg [31:0] instr1 = 0;
output reg [3:0] current_state = 0;
output reg [7:0] cr = 0;
output reg [15:0] pc = 0;
//
reg [15:0] pc_next;
wire [ 7:0] cr_next;
reg [ 3:0] next_state;
always begin
case (current_state)
`STATE_FETCH0_0, `STATE_FETCH1_0: pc_next = pc + 1;
`STATE_EXEC_0: begin
if(pc_update_req) pc_next = pc_update_addr;
else pc_next = pc;
end
default: pc_next = pc;
endcase
#1;
end
//
wire [7:0] instr0_op;
wire [7:0] next_instr0_op;
assign instr0_op = instr0[31:24];
assign next_instr0_op = memdata[31:24];
//
reg cr_next_hlt;
reg cr_next_skip;
assign cr_next = {6'b0, cr_next_skip, cr_next_hlt};
always begin
// HLT bit
if(current_state == `STATE_EXEC_1 && instr0_op == `OP_HLT) begin
cr_next_hlt = 1;
end
else cr_next_hlt = cr[`BIT_CR_HLT];
// SKIP bit
case (current_state)
`STATE_FETCH0_1: begin
case(next_instr0_op)
`OP_LIMM32, `OP_LBSET: begin
cr_next_skip = cr[`BIT_CR_SKIP];
end
default: cr_next_skip = 0;
endcase
end
`STATE_FETCH1_1: begin
cr_next_skip = 0;
end
`STATE_EXEC_0: begin
cr_next_skip = 0;
end
`STATE_EXEC_1: begin
if(instr0_op == `OP_CND && ireg_d0_lsb == 0) begin
cr_next_skip = 1;
end
else cr_next_skip = 0;
end
default: cr_next_skip = cr[`BIT_CR_SKIP];
endcase #1;
end
//
always begin
case (current_state)
`STATE_FETCH0_0, `STATE_FETCH0_1: memaddr <= pc;
`STATE_FETCH1_0, `STATE_FETCH1_1: memaddr <= pc;
default: memaddr <= 0;
endcase
#1;
end
always @(negedge clk) begin
if(reset == 0 && cr[`BIT_CR_HLT] == 0) begin
if(current_state == `STATE_FETCH0_1) begin
instr0 <= memdata;
end
if(current_state == `STATE_FETCH1_1) begin
instr1 <= memdata;
end
end
end
always @(posedge clk) begin
if(reset == 1) begin
pc = 0;
current_state = `STATE_FETCH0_0;
cr = 0;
end
if(reset == 0 && cr[`BIT_CR_HLT] == 0) begin
current_state <= next_state;
pc <= pc_next;
cr <= cr_next;
end
end
// state transition
always begin
#1;
case (current_state)
`STATE_FETCH0_0:
next_state = `STATE_FETCH0_1;
`STATE_FETCH0_1: begin
case(next_instr0_op)
`OP_LIMM32, `OP_LBSET: begin
next_state = `STATE_FETCH1_0;
end
default: begin
if(cr[`BIT_CR_SKIP])
next_state = `STATE_FETCH0_0;
else
next_state = `STATE_EXEC_0;
end
endcase
end
`STATE_FETCH1_0:
next_state = `STATE_FETCH1_1;
`STATE_FETCH1_1: begin
if(cr[`BIT_CR_SKIP])
next_state = `STATE_FETCH0_0;
else
next_state = `STATE_EXEC_0;
end
`STATE_EXEC_0: begin
next_state = `STATE_EXEC_1;
end
`STATE_EXEC_1: begin
next_state = `STATE_STORE_0;
end
`STATE_STORE_0: begin
next_state = `STATE_STORE_1;
end
`STATE_STORE_1: begin
next_state = `STATE_FETCH0_0;
end
default: next_state = `STATE_HLT;
endcase
end
endmodule