OpenCores
URL https://opencores.org/ocsvn/ag_6502/ag_6502/trunk

Subversion Repositories ag_6502

[/] [ag_6502/] [trunk/] [agat7/] [ag_6502.v] - Blame information for rev 4

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 olegodints
`timescale 1ns / 1ps
2
//////////////////////////////////////////////////////////////////////////////////
3
// Company:   BMSTU
4
// Engineer:  Oleg Odintsov
5
// 
6
// Create Date:    10:50:36 02/15/2012 
7
// Design Name: 
8 4 olegodints
// Module Name:    my6502 
9 2 olegodints
// Project Name:    Agat Hardware Project
10
// Target Devices: 
11
// Tool versions: 
12
// Description: 
13
//
14
// Dependencies: 
15
//
16
// Revision: 
17
// Revision 0.01 - File Created
18 4 olegodints
// Revision 0.02 - Fixed NMI bug
19 2 olegodints
// Additional Comments: 
20
//
21
//////////////////////////////////////////////////////////////////////////////////
22
 
23
 
24
// Specify following define to allow external 
25
//              clocking for phi1 and phi2
26
//      In such case you may use ag6502_ext_clock module
27
//              with baseclk frequency ~ 10 x phi_0
28
`define AG6502_EXTERNAL_CLOCK
29
 
30
 
31
`ifndef AG6502_EXTERNAL_CLOCK
32
module ag6502_clock(input phi_0, output phi_1, output phi_2);
33
        wire phi_01;
34
        not#3(phi_1,phi_0);
35
        or(phi_01,~phi_0, phi_1);
36
        not#1(phi_2, phi_01);
37
endmodule
38
 
39
 
40
`else
41
 
42
module ag6502_phase_shift(input baseclk, input phi_0, output reg phi_1);
43 4 olegodints
        parameter DELAY = 1; // delay in waves of baseclk
44 2 olegodints
        initial phi_1 = 0;
45
        integer cnt = 0;
46
 
47
        always @(posedge baseclk) begin
48
                if (phi_0 != phi_1) begin
49 4 olegodints
                        if (!cnt) begin phi_1 <= phi_0; cnt <= DELAY; end
50 2 olegodints
                        else cnt <= cnt - 1;
51
                end
52
        end
53
endmodule
54
 
55
// baseclk is used to simulate delays on a real hardware
56
module ag6502_ext_clock(input baseclk, input phi_0, output phi_1, output phi_2);
57 4 olegodints
        parameter DELAY1 = 3, DELAY2 = 1; // delays in waves of baseclk
58 2 olegodints
 
59
        wire phi_1_neg, phi_01;
60
 
61
        ag6502_phase_shift#DELAY1 d1(baseclk, phi_0, phi_1_neg);
62
        assign phi_1 = ~phi_1_neg;
63
 
64
        and(phi_01, phi_0, phi_1_neg);
65
        ag6502_phase_shift#DELAY2 d2(baseclk, phi_01, phi_2);
66
endmodule
67
 
68
`endif
69
 
70
 
71
`define ALU_ORA 3'd0
72
`define ALU_AND 3'd1
73
`define ALU_EOR 3'd2
74
`define ALU_ADC 3'd3
75
`define ALU_ASL 3'd4
76
`define ALU_LSR 3'd5
77
`define ALU_ROL 3'd6
78
`define ALU_ROR 3'd7
79
 
80
 
81
module ag6502_decimal(ADD, D_IN, NEG, CORR);
82
        input wire[4:0] ADD;
83
        input wire D_IN, NEG;
84
        output wire[4:0] CORR;
85
        wire C9 = {ADD[4]^NEG, ADD[3:0]} > 5'd9;
86
 
87
        assign CORR = D_IN?{C9^NEG, C9?ADD[3:0] + (NEG?4'd10:4'd6): ADD[3:0]}: ADD;
88
endmodule
89
 
90
 
91
module ag6502_alu(A, B, OP, NEG, C_IN, D_IN, R, C_OUT, V_OUT);
92
        input wire[7:0] A, B;
93
        input wire[2:0] OP;
94
        input wire C_IN, D_IN, NEG;
95
        output wire[7:0] R;
96
        output wire C_OUT, V_OUT;
97
 
98
        wire[4:0] ADD_L;
99
        ag6502_decimal DL({1'b0, A[3:0]} + {1'b0, B[3:0]} + C_IN, D_IN, NEG, ADD_L);
100
        wire CF_H = ADD_L[4];
101
 
102
        wire[4:0] ADD_H;
103
        ag6502_decimal DH({1'b0, A[7:4]} + {1'b0, B[7:4]} + CF_H, D_IN, NEG, ADD_H);
104
 
105
        assign
106
                {C_OUT,R} = (OP==`ALU_ORA)? A | B:
107
                                (OP==`ALU_AND)? A & B:
108
                                (OP==`ALU_EOR)? A ^ B:
109
                                (OP==`ALU_ADC)? {ADD_H, ADD_L[3:0]}:
110
                                (OP==`ALU_ASL)? {A[7], A[6:0], 1'b0}:
111
                                (OP==`ALU_LSR)? {A[0], 1'b0, A[7:1]}:
112
                                (OP==`ALU_ROL)? {A[7], A[6:0], C_IN}:
113
                                (OP==`ALU_ROR)? {A[0], C_IN, A[7:1]}:
114
                                8'bX;
115
        assign V_OUT = (A[7] == B[7]) && (A[7] != R[7]);
116
endmodule
117
 
118
/*
119
        System AB/DB discipline:
120
        1. For CPU
121
                Phi1 up => CPU set ab/db_out buses
122
                Phi2 down => CPU reads data from db_in
123
        2. For Memory / other devices
124
                Phi2 up => perform read/write operation
125
*/
126
 
127
 
128
module ag6502(input phi_0,
129
`ifdef AG6502_EXTERNAL_CLOCK
130
                input phi_1, input phi_2,
131
`else
132
                output phi_1, output phi_2,
133
`endif
134
                output reg[15:0] ab,
135
                output wire read,
136
                input[7:0] db_in, output reg[7:0] db_out,
137
                input rdy,
138
                input rst, input irq, input nmi,
139
                input so,
140
                output sync);
141
 
142
`ifndef AG6502_EXTERNAL_CLOCK
143
        ag6502_clock cgen(phi_0, phi_1, phi_2);
144
`endif
145
 
146
        reg rdyg = 1;
147
 
148
        reg[2:0] T = 7;
149 4 olegodints
        reg[7:0] IR ='h00;
150 2 olegodints
 
151
        reg[15:0] PC = 0;
152
        wire[7:0] PCH = PC[15:8], PCL = PC[7:0];
153
        reg[7:0] EAL, EAH;
154
        wire[15:0] EA = {EAH, EAL};
155
 
156
        reg FLAG_C, FLAG_Z, FLAG_I, FLAG_D, FLAG_B, FLAG_V, FLAG_N;
157
 
158
        reg[7:0] AC, X, Y, S = 0;
159
        wire[7:0] P = {FLAG_N, FLAG_V, 1'b1, FLAG_B, FLAG_D, FLAG_I, FLAG_Z, FLAG_C};
160
        wire[7:0] SB;
161
 
162
 
163
        wire[7:0] ALU_A, ALU_B;
164
        wire[7:0] RES;
165
        wire[2:0] ALU_OP;
166
        reg[8:0] eALU; // with carry
167
        wire[7:0] ALU = eALU;
168
        wire ALU_CF = eALU[8];
169
 
170
        wire CF_IN, DF_IN;
171
        wire CF_OUT, VF_OUT;
172
 
173
        reg so_prev = 0;
174
        reg nmi_prev = 0;
175
        wire irq_active = ~irq & ~FLAG_I;
176
        wire nmi_active = ~nmi & nmi_prev;
177
        wire int_active = irq_active | nmi_active;
178
        wire rst_active = ~rst;
179
        wire so_active = so & ~so_prev;
180
 
181 4 olegodints
        wire[7:0] IR_in = int_active?8'b0:db_in;
182
 
183 2 olegodints
        wire[1:0] vec_bits=
184
                        nmi_active?2'b01:
185
                        rst_active?2'b10:
186
                        2'b11;
187
 
188
        wire[15:0] vec_addr = {{13{1'b1}}, vec_bits, 1'b0};
189
 
190 4 olegodints
        wire[10:0] L = {T, IR};
191 2 olegodints
 
192
        `include "states.v"
193
 
194
        assign read = ~A_RW_W;
195
        assign sync = !T;
196
 
197
        assign SB = A_SB_DB? db_in:
198
                                        A_SB_AC? AC:
199
                                        A_SB_X? X:
200
                                        A_SB_Y? Y:
201
                                        A_SB_S? S:
202
                                        A_SB_P? P:
203
                                        A_SB_ALU? ALU:
204
                                        A_SB_0? 8'b0:
205
                                        A_SB_PCH? PCH:
206
                                        A_SB_PCL? PCL:
207
                                        8'bX;
208
 
209
        assign CF_IN = A_ALU_CF_0? 1'b0:
210
                                        A_ALU_CF_1? 1'b1:
211
                                        A_ALU_CF_ALUC? ALU_CF:
212
                                        FLAG_C;
213
 
214
        assign DF_IN = A_ALU_DF_D? FLAG_D: 1'b0;
215
 
216
        assign ALU_A =
217
                                        A_ALU_A_AC? AC:
218
                                        A_ALU_A_X? X:
219
                                        A_ALU_A_Y? Y:
220
                                        A_ALU_A_DB? db_in:
221
                                        A_ALU_A_EAL? EAL:
222
                                        A_ALU_A_ALU? ALU:
223
                                        A_ALU_A_S? S:
224
                                        A_ALU_A_SIGN? (EAL[7]?8'b11111111:8'b00000001):
225
                                        8'bX;
226
 
227
        assign ALU_B = A_ALU_B_SB? SB:
228
                                        A_ALU_B_NOTSB? ~SB:
229
                                        8'bX;
230
 
231
        assign ALU_OP = A_ALU_OP_ADC? `ALU_ADC:
232
                                        A_ALU_OP_ORA? `ALU_ORA:
233
                                        A_ALU_OP_EOR? `ALU_EOR:
234
                                        A_ALU_OP_AND? `ALU_AND:
235
                                        A_ALU_OP_ASL? `ALU_ASL:
236
                                        A_ALU_OP_LSR? `ALU_LSR:
237
                                        A_ALU_OP_ROL? `ALU_ROL:
238
                                        A_ALU_OP_ROR? `ALU_ROR:
239
                                        8'bX;
240
 
241
        ag6502_alu alu(ALU_A, ALU_B, ALU_OP, A_ALU_B_NOTSB, CF_IN, DF_IN, RES, CF_OUT, VF_OUT);
242
 
243
        always @(posedge phi_1) begin
244
                if (E_AB__PC) ab <= PC;
245
                else if (E_AB__EA) ab <= EA;
246
                else if (E_AB__S) ab <= {8'b1, S};
247
 
248
                if (E_DB__SB) db_out <= SB;
249
                else if (E_DB__PCH) db_out <= PCH;
250
                else if (E_DB__PCL) db_out <= PCL;
251
                else if (E_DB__P) db_out <= P;
252
                else if (E_DB__ALU) db_out <= ALU;
253
 
254
                if (read) rdyg <= rdy;
255
        end
256
 
257
 
258
        wire cond;
259
 
260
        assign cond =
261
                        E_T__0IFNF__IR_5_?(FLAG_N != IR[5]):
262
                        E_T__0IFVF__IR_5_?(FLAG_V != IR[5]):
263
                        E_T__0IFCF__IR_5_?(FLAG_C != IR[5]):
264
                        E_T__0IFZF__IR_5_?(FLAG_Z != IR[5]):
265
                        E_T__0IFZF__IR_5_?(FLAG_Z != IR[5]):
266
                        E_T__0IF_C7F? CF_OUT == EAL[7]:
267
                        E_T__0;
268
 
269
        always @(negedge phi_2) if (rdyg) begin
270 4 olegodints
                if (E_PC__PC_1) begin
271
                        if (T || (!int_active && !rst_active)) PC <= PC + 1;
272
                end else if (E_PC__EA) PC <= EA;
273 2 olegodints
                else begin
274
                        if (E_PCH__RES) PC[15:8] <= RES;
275
                        if (E_PCL__ALU) PC[7:0] <= ALU;
276
                        else if (E_PCL__RES) PC[7:0] <= RES;
277
                        else if (E_PCL__EAL) PC[7:0] <= EAL;
278
                        else if (E_PCL__DB) PC[7:0] <= db_in;
279
                end
280
 
281
                if (!T) begin
282 4 olegodints
                        IR <= IR_in;
283
                        if (!IR_in) begin // BRK instruction
284 2 olegodints
                                {EAH, EAL} <= vec_addr;
285
                        end
286
                        nmi_prev <= nmi;
287
                end
288
 
289
                if (E_N_Z__SB) begin FLAG_Z <= !SB; FLAG_N <= SB[7]; end
290
                else if (E_N_Z__RES) begin FLAG_Z <= !RES; FLAG_N <= RES[7]; end
291
                else if (E_N_Z__SB_RES) begin FLAG_Z <= !RES; FLAG_N <= SB[7]; end
292
 
293
                if (E_C__RES) FLAG_C <= CF_OUT;
294
                if (E_V__RES) FLAG_V <= VF_OUT;
295
                else if (E_V__SB_6_) FLAG_V <= SB[6];
296
 
297
                if (E_EAL__DB) EAL <= db_in;
298
                else if (E_EAL__ALU) EAL <= ALU;
299
 
300
 
301
                if (E_EA__DB) {EAH, EAL} <= { 8'b0, db_in };
302
                else if (E_EAH__DB) EAH <= db_in;
303
                else if (E_EAH__ALU) EAH <= ALU;
304
 
305
                if (E_AC__SB) AC <= SB;
306
                else if (E_AC__RES) AC <= RES;
307
 
308
                if (E_S__ALU) S <= ALU;
309
 
310
                if (E_X__SB) X <= SB;
311
                else if (E_X__RES) X <= RES;
312
 
313
                if (E_Y__SB) Y <= SB;
314
                else if (E_Y__RES) Y <= RES;
315
 
316
                if (E_S__SB) S <= SB;
317
                if (E_P__SB) {FLAG_N, FLAG_V, FLAG_B, FLAG_D, FLAG_I, FLAG_Z, FLAG_C} <= {SB[7], SB[6], SB[4], SB[3], SB[2], SB[1], SB[0]};
318
                else if (E_P__DB) {FLAG_N, FLAG_V, FLAG_B, FLAG_D, FLAG_I, FLAG_Z, FLAG_C} <= {db_in[7], db_in[6], db_in[4], db_in[3], db_in[2], db_in[1], db_in[0]};
319
 
320
                if (E_CF__IR_5_) FLAG_C <= IR[5];
321
                if (E_IF__IR_5_) FLAG_I <= IR[5];
322
                if (E_DF__IR_5_) FLAG_D <= IR[5];
323
                if (E_VF__0) FLAG_V <= 0;
324
                else if (so_active) FLAG_V <= 1;
325
                so_prev <= so;
326
 
327
                eALU <= {CF_OUT, RES};
328
 
329
                if (cond) begin
330
                        T <= 0;
331 4 olegodints
                        if (!IR) begin
332
                                FLAG_B <= !int_active;
333 2 olegodints
                                FLAG_I <= 1;
334
                        end
335
                end else T <= T + ((E_T__T_1IF_ALUCZ && !ALU_CF)?2: 1);
336
 
337
                if (rst_active) begin
338
                        T <= 1;
339
                        IR <= 0;
340
                        {EAH, EAL} <= vec_addr;
341
                end
342
        end
343
 
344
 
345
endmodule
346
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.