-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCPU.v
216 lines (203 loc) · 7.97 KB
/
CPU.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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
//Instruction Interpreter Implementation for S-Machine CPU
//By Duncan Cameron B00819540 and Jasper Grant B00829263
//2023-10-31
`timescale 1ns / 1ns
module CPU (
input [15:0] inst,
input clk,
input enable,
input [15:0] data_in_memory,
output reg read_write_memory,
output reg [15:0] data_out_memory,
output reg [8:0] addr,
output reg [7:0] PC
);
//Declare status bits
reg Z = 0, N = 0, C = 0;
//Declare A and B registers
reg [15:0] register_A;
reg [15:0] register_B;
reg [15:0] register_temp = 0;
reg TempBranch; //temp for Branch
reg [7:0] carry_matrix = 8'b11010100;// TODO: Could this be a parameter?
initial begin
register_A = 0;
register_B = 0;
PC = 0;
end
//On every instruction input change decide which logic should be followed
always @(posedge clk) begin
if(enable == 1'b1) begin
PC = PC + 1;
//Store backup for register A in temp
register_temp = register_A;
case(inst[15:12])
4'b0010: //INC instruction
begin
//TODO: check if 2s complement is needed to handle negatives
if(inst[11]) begin
register_B = register_B + inst[7:0];
end
else begin
register_A = register_A + inst[7:0];
end
//Standard set ZNC bits
Z = register_A == 0;
N = register_A[15];
C = carry_matrix[{register_temp[15], register_B[15], register_A[15]}];
end
4'b0100: //ADD instruction
begin
register_A = register_A + register_B;
//Standard set ZNC bits
Z = register_A == 0;
N = register_A[15];
C = carry_matrix[{register_temp[15], register_B[15], register_A[15]}];
end
4'b0101: //SUB instruction
begin
register_A = register_A - register_B;
//Standard set ZNC bits
Z = register_A == 0;
N = register_A[15];
C = carry_matrix[{register_temp[15], register_B[15], register_A[15]}];
end
4'b0110: //OR instruction
begin
register_A = register_A | register_B;
//Standard set ZNC bits
Z = register_A == 0;
N = register_A[15];
C = carry_matrix[{register_temp[15], register_B[15], register_A[15]}];
end
4'b0111: //AND instruction
begin
register_A = register_A & register_B;
//Standard set ZNC bits
Z = register_A == 0;
N = register_A[15];
C = carry_matrix[{register_temp[15], register_B[15], register_A[15]}];
end
4'b1000: //XOR instruction
begin
register_A = register_A ^ register_B;
//Standard set ZNC bits
Z = register_A == 0;
N = register_A[15];
C = carry_matrix[{register_temp[15], register_B[15], register_A[15]}];
end
4'b1001: //SHR instruction
begin
//Carry bit recieves value of reg_A[0]
C = register_A[0];
//Add 0 as [15] and then put digits 15-1 into spots 14-0
register_A = {1'b0, register_A[15:1]};
end
4'b1010: //MOV instruction
begin
//Move register A to B
register_B = register_A;
end
4'b1011: //EXCH instruction
begin
//A and B register values are swapped. Temp register is already equal to previous value of A
register_A = register_B;
register_B = register_temp;
//Status bits remain the same
end
4'b1100: //CMP instruction
begin
//Perform subtraction with discarded output
register_temp = register_A - register_B;
//Standard set ZNC bits
Z = register_temp == 0;
N = register_temp[15];
C = carry_matrix[{register_A[15], register_B[15], register_temp[15]}];
end
4'b1101: //SET instruction
begin
//Set bits based on set bits in inst
Z = inst[10] ? 1 : Z;
N = inst[9] ? 1 : N;
C = inst[8] ? 1 : C;
end
4'b1110: //CLR instruction
begin
//Clear bits based on set bits in inst
Z = inst[10] ? 0 : Z;
N = inst[9] ? 0 : N;
C = inst[8] ? 0 : C;
end
4'b0000: //LD instruction
begin
if(inst[11]) begin
if(inst[10]) begin
register_B = inst[9] ? {inst[7:0], 8'b00000000} : {8'b00000000, inst[7:0]};
end
else begin
//Fool with timing. Take out magical #3
read_write_memory = 0;
addr = inst[8:0];
#3
register_B = data_in_memory;
end
end
else begin
if(inst[10]) begin
register_A = inst[9] ? {inst[7:0], 8'b00000000} : {8'b00000000, inst[7:0]};
end
else begin
//Fool with timing. Take out magical #3
read_write_memory = 0;
addr = inst[8:0];
#3
register_A = data_in_memory;
end
end
end
4'b0001: //ST instruction
begin
read_write_memory = 1;
addr = inst[8:0];
data_out_memory = inst[11] ? register_B : register_A;
end
4'b0011: //Transfer of control or BR instruciton
begin
TempBranch = 0;
if (inst[11] == 0) begin
// BZ, BN, BC plus others
if (inst[10] == Z |
inst[9] == N |
inst[8] == C) begin
TempBranch = 1;
end
else
// 0 0 0 0
if (inst[10] == 0 &&
inst[9] == 0 &&
inst[8] == 0)begin
TempBranch = 1;
end
end
else begin
// BNZ, BNN, BNC
if ((inst[10] == 1 && Z == 0) |
(inst[9] == 1 && N == 0) |
(inst[8] == 1 && C == 0)) begin
TempBranch = 1;
end
// 1 1 1 1
if (inst[10] == 1 &&
inst[9] == 1 &&
inst[8] == 1) begin
TempBranch = 1;
end
end
if (TempBranch == 1) begin
PC = inst[7:0];
end
end
endcase
end
end
endmodule