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

Subversion Repositories t6507lp

[/] [t6507lp/] [trunk/] [rtl/] [verilog/] [t6507lp_fsm.v] - Blame information for rev 104

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

Line No. Rev Author Line
1 61 creep
////////////////////////////////////////////////////////////////////////////
2
////                                                                    ////
3
//// T6507LP IP Core                                                    ////
4
////                                                                    ////
5
//// This file is part of the T6507LP project                           ////
6
//// http://www.opencores.org/cores/t6507lp/                            ////
7
////                                                                    ////
8
//// Description                                                        ////
9
//// 6507 FSM                                                           ////
10
////                                                                    ////
11
//// TODO:                                                              ////
12 96 creep
//// - Fix relative mode, bit 7 means negative                          ////
13 61 creep
//// - Code the indirect indexed mode                                   ////
14
//// - Code the absolute indirect mode                                  ////
15
////                                                                    ////
16
//// Author(s):                                                         ////
17
//// - Gabriel Oshiro Zardo, gabrieloshiro@gmail.com                    ////
18
//// - Samuel Nascimento Pagliarini (creep), snpagliarini@gmail.com     ////
19
////                                                                    ////
20
////////////////////////////////////////////////////////////////////////////
21
////                                                                    ////
22
//// Copyright (C) 2001 Authors and OPENCORES.ORG                       ////
23
////                                                                    ////
24
//// This source file may be used and distributed without               ////
25
//// restriction provided that this copyright statement is not          ////
26
//// removed from the file and that any derivative work contains        ////
27
//// the original copyright notice and the associated disclaimer.       ////
28
////                                                                    ////
29
//// This source file is free software; you can redistribute it         ////
30
//// and/or modify it under the terms of the GNU Lesser General         ////
31
//// Public License as published by the Free Software Foundation;       ////
32
//// either version 2.1 of the License, or (at your option) any         ////
33
//// later version.                                                     ////
34
////                                                                    ////
35
//// This source is distributed in the hope that it will be             ////
36
//// useful, but WITHOUT ANY WARRANTY; without even the implied         ////
37
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR            ////
38
//// PURPOSE. See the GNU Lesser General Public License for more        ////
39
//// details.                                                           ////
40
////                                                                    ////
41
//// You should have received a copy of the GNU Lesser General          ////
42
//// Public License along with this source; if not, download it         ////
43
//// from http://www.opencores.org/lgpl.shtml                           ////
44
////                                                                    ////
45
////////////////////////////////////////////////////////////////////////////
46
 
47
`timescale 1ns / 1ps
48
 
49 86 creep
module t6507lp_fsm(clk, reset_n, alu_result, alu_status, data_in, address, control, data_out, alu_opcode, alu_a, alu_enable, alu_x, alu_y);
50 87 creep
        parameter DATA_SIZE = 8;
51
        parameter ADDR_SIZE = 13;
52 68 creep
 
53 83 creep
        localparam DATA_SIZE_ = DATA_SIZE - 4'b0001;
54
        localparam ADDR_SIZE_ = ADDR_SIZE - 4'b0001;
55 82 creep
 
56 71 creep
        input clk;
57
        input reset_n;
58 82 creep
        input [DATA_SIZE_:0] alu_result;
59
        input [DATA_SIZE_:0] alu_status;
60
        input [DATA_SIZE_:0] data_in;
61
        output reg [ADDR_SIZE_:0] address;
62 61 creep
        output reg control; // one bit is enough? read = 0, write = 1
63 82 creep
        output reg [DATA_SIZE_:0] data_out;
64
        output reg [DATA_SIZE_:0] alu_opcode;
65
        output reg [DATA_SIZE_:0] alu_a;
66 68 creep
        output reg alu_enable;
67 61 creep
 
68 86 creep
        input [DATA_SIZE_:0] alu_x;
69
        input [DATA_SIZE_:0] alu_y;
70 68 creep
 
71 61 creep
        // FSM states
72 95 creep
        localparam FETCH_OP = 5'b00000;
73
        localparam FETCH_OP_CALC = 5'b00001;
74
        localparam FETCH_LOW = 5'b00010;
75
        localparam FETCH_HIGH = 5'b00011;
76
        localparam READ_MEM = 5'b00100;
77
        localparam DUMMY_WRT_CALC = 5'b00101;
78
        localparam WRITE_MEM = 5'b00110;
79
        localparam FETCH_OP_CALC_PARAM = 5'b00111;
80
        localparam READ_MEM_CALC_INDEX = 5'b01000;
81
        localparam FETCH_HIGH_CALC_INDEX = 5'b01001;
82
        localparam READ_MEM_FIX_ADDR = 5'b01010;
83
        localparam FETCH_OP_EVAL_BRANCH = 5'b01011;
84
        localparam FETCH_OP_FIX_PC = 5'b01100;
85
        localparam READ_FROM_POINTER = 5'b01101;
86
        localparam READ_FROM_POINTER_X = 5'b01110;
87
        localparam READ_FROM_POINTER_X1 = 5'b01111;
88 104 creep
        localparam PUSH_PCH = 5'b10000;
89
        localparam PUSH_PCL = 5'b10001;
90
        localparam PUSH_STATUS = 5'b10010;
91
        localparam FETCH_PCL = 5'b10011;
92
        localparam FETCH_PCH = 5'b10100;
93 61 creep
 
94 95 creep
        localparam RESET = 5'b11111;
95
 
96 61 creep
        // OPCODES TODO: verify how this get synthesised
97
        `include "../T6507LP_Package.v"
98
 
99
        // control signals
100
        localparam MEM_READ = 1'b0;
101
        localparam MEM_WRITE = 1'b1;
102
 
103 82 creep
        reg [ADDR_SIZE_:0] pc;           // program counter
104 104 creep
        reg [DATA_SIZE:0] sp;            // stack pointer. 9 bits wide.
105 82 creep
        reg [DATA_SIZE_:0] ir;           // instruction register
106
        reg [ADDR_SIZE_:0] temp_addr;    // temporary address
107
        reg [DATA_SIZE_:0] temp_data;    // temporary data
108 61 creep
 
109 96 creep
        reg [4:0] state, next_state; // current and next state registers
110 104 creep
        // TODO: not sure if this will be 5 bits wide. as of march 24th this was 5bit wide.
111 61 creep
 
112 104 creep
        // wiring that simplifies the FSM logic by simplifying the addressing modes
113 61 creep
        reg absolute;
114
        reg absolute_indexed;
115
        reg accumulator;
116
        reg immediate;
117
        reg implied;
118 95 creep
        reg indirectx;
119
        reg indirecty;
120 61 creep
        reg relative;
121
        reg zero_page;
122
        reg zero_page_indexed;
123 86 creep
        reg [DATA_SIZE_:0] index; // will be assigned with either X or Y
124 61 creep
 
125
        // regs that store the type of operation. again, this simplifies the FSM a lot.
126
        reg read;
127
        reg read_modify_write;
128
        reg write;
129
        reg jump;
130 101 creep
        reg jump_indirect;
131 61 creep
 
132 104 creep
        // regs for the special instructions
133
        reg break;
134
 
135 82 creep
        wire [ADDR_SIZE_:0] next_pc;
136 63 creep
        assign next_pc = pc + 13'b0000000000001;
137 61 creep
 
138 87 creep
        reg [ADDR_SIZE_:0] address_plus_index; // this would update more times than actually needed, consuming power.
139
        reg page_crossed;                       // so the simple assign was changed into a combinational always block
140
 
141 94 creep
        reg branch;
142
 
143 87 creep
        always @(*) begin
144
                address_plus_index = 0;
145
                page_crossed = 0;
146 86 creep
 
147 88 creep
                if (state == READ_MEM_CALC_INDEX || state == READ_MEM_FIX_ADDR || state == FETCH_HIGH_CALC_INDEX) begin
148
                        {page_crossed, address_plus_index[7:0]} = temp_addr[7:0] + index;
149
                        address_plus_index[12:8] = temp_addr[12:8] + page_crossed;
150 87 creep
                end
151 94 creep
                else if (branch) begin
152
                        if (state == FETCH_OP_FIX_PC || state == FETCH_OP_EVAL_BRANCH) begin
153
                                {page_crossed, address_plus_index[7:0]} = pc[7:0] + index;
154
                                address_plus_index[12:8] = pc[12:8] + page_crossed;// warning: pc might feed these lines twice and cause branch failure
155
                        end                                                             // solution: add a temp reg i guess
156
                end
157 95 creep
                else if (state == READ_FROM_POINTER) begin
158 96 creep
                        if (indirectx) begin
159
                                {page_crossed, address_plus_index[7:0]} = temp_data + index;
160
                                address_plus_index[12:8] = 5'b00000;
161
                        end
162 101 creep
                        else if (jump_indirect) begin
163
                                address_plus_index[7:0] = temp_addr + 8'h01;
164
                                address_plus_index[12:8] = 5'b00000;
165
                        end
166 96 creep
                        else begin // indirecty falls here
167
                                address_plus_index[7:0] = temp_data + 8'h01;
168
                                address_plus_index[12:8] = 5'b00000;
169
                        end
170 95 creep
                end
171
                else if (state == READ_FROM_POINTER_X) begin
172
                        {page_crossed, address_plus_index[7:0]} = temp_data + index + 8'h01;
173
                        address_plus_index[12:8] = 5'b00000;
174
                end
175 96 creep
                else if (state == READ_FROM_POINTER_X1) begin
176
                        {page_crossed, address_plus_index[7:0]} = temp_addr[7:0] + index;
177
                        address_plus_index[12:8] = temp_addr[12:8] + page_crossed;
178
                end
179 87 creep
        end
180
 
181 103 creep
        wire [8:0] sp_plus_one;
182
        assign sp_plus_one = sp + 9'b000000001;
183
 
184
        wire [8:0] sp_minus_one;
185
        assign sp_minus_one = sp - 9'b000000001;
186
 
187 71 creep
        always @ (posedge clk or negedge reset_n) begin // sequencial always block
188
                if (reset_n == 1'b0) begin
189
                        // all registers must assume default values
190 68 creep
                        pc <= 0; // TODO: this is written somewhere. something about a reset vector. must be checked.
191 103 creep
                        sp <= 9'b100000000; // the default is 'h100 
192 82 creep
                        ir <= 8'h00;
193 102 creep
                        temp_addr <= 13'h00;
194 82 creep
                        temp_data <= 8'h00;
195 68 creep
                        state <= RESET;
196 71 creep
                        // registered outputs also receive default values
197
                        address <= 0;
198 82 creep
                        control <= MEM_READ;
199
                        data_out <= 8'h00;
200 61 creep
                end
201
                else begin
202
                        state <= next_state;
203 83 creep
 
204 61 creep
                        case (state)
205 104 creep
                                RESET: begin    // The processor was reset
206 82 creep
                                        $write("under reset");
207 68 creep
                                end
208 104 creep
                                /*
209
                                FETCH_OP: executed when the processor was reset or the last instruction could not fetch.
210
                                FETCH_OP_CALC: enables the alu and fetchs the next instruction opcode. (pipelining)
211
                                FETCH_OP_CALC_PARAM: enables the alu with an argument (alu_a) and fetchs the next instruction opcode. (pipelining)
212
                                */
213
                                FETCH_OP, FETCH_OP_CALC, FETCH_OP_CALC_PARAM: begin // this is the pipeline happening!
214 61 creep
                                        pc <= next_pc;
215 71 creep
                                        address <= next_pc;
216 83 creep
                                        control <= MEM_READ;
217 70 creep
                                        ir <= data_in;
218 61 creep
                                end
219 104 creep
                                /*
220
                                in this state the opcode is already known so truly execution begins.
221
                                all instruction execute this cycle.
222
                                */
223
                                FETCH_LOW: begin
224 68 creep
                                        if (accumulator || implied) begin
225 70 creep
                                                pc <= pc; // is this better?
226 71 creep
                                                address <= pc;
227 83 creep
                                                control <= MEM_READ;
228 61 creep
                                        end
229 94 creep
                                        else if (immediate || relative) begin
230 68 creep
                                                pc <= next_pc;
231 71 creep
                                                address <= next_pc;
232 83 creep
                                                control <= MEM_READ;
233 70 creep
                                                temp_data <= data_in; // the follow-up byte is saved in temp_data 
234 61 creep
                                        end
235 101 creep
                                        else if (absolute || absolute_indexed || jump_indirect) begin
236 71 creep
                                                pc <= next_pc;
237
                                                address <= next_pc;
238 83 creep
                                                control <= MEM_READ;
239 87 creep
                                                temp_addr <= {{5{1'b0}},data_in};
240 101 creep
                                                temp_data <= 8'h00;
241 71 creep
                                        end
242 77 creep
                                        else if (zero_page) begin
243
                                                pc <= next_pc;
244
                                                address <= {{5{1'b0}},data_in};
245 78 creep
                                                temp_addr <= {{5{1'b0}},data_in};
246
 
247 77 creep
                                                if (write) begin
248
                                                        control <= MEM_WRITE;
249 78 creep
                                                        data_out <= alu_result;
250 77 creep
                                                end
251 83 creep
                                                else begin
252
                                                        control <= MEM_READ;
253
                                                        data_out <= 8'h00;
254
                                                end
255 77 creep
                                        end
256 86 creep
                                        else if (zero_page_indexed) begin
257
                                                pc <= next_pc;
258 94 creep
                                                address <= {{5{1'b0}}, data_in};
259
                                                temp_addr <= {{5{1'b0}}, data_in};
260 86 creep
                                                control <= MEM_READ;
261
                                        end
262 96 creep
                                        else if (indirectx || indirecty) begin
263 95 creep
                                                pc <= next_pc;
264
                                                address <= data_in;
265
                                                temp_data <= data_in;
266
                                                control <= MEM_READ;
267
                                        end
268 102 creep
                                        else begin // the special instructions will fall here: BRK, RTI, RTS...
269 104 creep
                                                if (break) begin
270
                                                        pc <= next_pc;
271
                                                        address <= sp;
272
                                                        data_out <= {{3{1'b0}}, pc[12:8]};
273
                                                        control <= MEM_WRITE;
274
                                                        sp <= sp_minus_one;
275
                                                end
276 102 creep
                                        end
277 61 creep
                                end
278 87 creep
                                FETCH_HIGH_CALC_INDEX: begin
279
                                        pc <= next_pc;
280
                                        temp_addr[12:8] <= data_in[4:0];
281
                                        address <= {data_in[4:0], address_plus_index[7:0]};
282
                                        control <= MEM_READ;
283
                                        data_out <= 8'h00;
284
                                end
285 104 creep
                                // this cycle fetchs the next operand while still evaluating if a branch occurred.
286 94 creep
                                FETCH_OP_EVAL_BRANCH: begin
287
                                        if (branch) begin
288
                                                pc <= {{5{1'b0}}, address_plus_index[7:0]};
289
                                                address <= {{5{1'b0}}, address_plus_index[7:0]};
290
                                                control <= MEM_READ;
291
                                                data_out <= 8'h00;
292
                                        end
293
                                        else begin
294
                                                pc <= next_pc;
295
                                                address <= next_pc;
296
                                                control <= MEM_READ;
297
                                                data_out <= 8'h00;
298 95 creep
                                                ir <= data_in;
299 94 creep
                                        end
300
                                end
301 104 creep
                                // sometimes when reading memory page crosses may occur. the pc register must be fixed, i.e., add 16'h0100
302 94 creep
                                FETCH_OP_FIX_PC: begin
303
                                        if (page_crossed) begin
304
                                                pc[12:8] <= address_plus_index[12:8];
305
                                                address[12:8] <= address_plus_index[12:8];
306
                                        end
307
                                        else begin
308
                                                pc <= next_pc;
309
                                                address <= next_pc;
310
                                                control <= MEM_READ;
311
                                                ir <= data_in;
312
                                        end
313
                                end
314 104 creep
                                // several instructions ocupy 3 bytes in memory. this cycle reads the third byte.
315 71 creep
                                FETCH_HIGH: begin
316
                                        if (jump) begin
317 83 creep
                                                pc <= {data_in[4:0], temp_addr[7:0]}; // PCL <= first byte, PCH <= second byte
318
                                                address <= {data_in[4:0], temp_addr[7:0]};
319
                                                control <= MEM_READ;
320
                                                data_out <= 8'h00;
321 71 creep
                                        end
322
                                        else begin
323
                                                if (write) begin
324
                                                        pc <= next_pc;
325
                                                        temp_addr[12:8] <= data_in[4:0];
326
                                                        address <= {data_in[4:0],temp_addr[7:0]};
327
                                                        control <= MEM_WRITE;
328 77 creep
                                                        data_out <= alu_result;
329 71 creep
                                                end
330
                                                else begin // read_modify_write or just read
331
                                                        pc <= next_pc;
332
                                                        temp_addr[12:8] <= data_in[4:0];
333
                                                        address <= {data_in[4:0],temp_addr[7:0]};
334 83 creep
                                                        control <= MEM_READ;
335
                                                        data_out <= 8'h00;
336 71 creep
                                                end
337
                                        end
338
                                        //else begin
339
                                        //      $write("FETCHHIGH PROBLEM"); 
340
                                        //      $finish(0); 
341
                                        //end
342 61 creep
                                end
343 71 creep
                                READ_MEM: begin
344
                                        if (read_modify_write) begin
345
                                                pc <= pc;
346
                                                address <= temp_addr;
347
                                                control <= MEM_WRITE;
348
                                                temp_data <= data_in;
349
                                                data_out <= data_in; // writeback the same value
350
                                        end
351
                                        else begin
352
                                                pc <= pc;
353
                                                address <= pc;
354
                                                temp_data <= data_in;
355 83 creep
                                                control <= MEM_READ;
356
                                                data_out <= 8'h00;
357 71 creep
                                        end
358 70 creep
                                end
359 86 creep
                                READ_MEM_CALC_INDEX: begin
360
                                                //pc <= next_pc; // pc was  already updated in the previous cycle
361
                                                address <= address_plus_index;
362
                                                temp_addr <= address_plus_index;
363
 
364
                                                if (write) begin
365
                                                        control <= MEM_WRITE;
366
                                                        data_out <= alu_result;
367
                                                end
368
                                                else begin
369
                                                        control <= MEM_READ;
370
                                                        data_out <= 8'h00;
371
                                                end
372
 
373
                                end
374 87 creep
                                READ_MEM_FIX_ADDR: begin
375
                                        if (read) begin
376
                                                control <= MEM_READ;
377
                                                data_out <= 8'h00;
378
 
379
                                                if (page_crossed) begin
380
                                                        address <= address_plus_index;
381
                                                        temp_addr <= address_plus_index;
382
                                                end
383
                                                else begin
384
                                                        address <= pc;
385
                                                        temp_data <= data_in;
386
                                                end
387
                                        end
388
                                        else if (write) begin
389
                                                control <= MEM_WRITE;
390
                                                data_out <= alu_result;
391
                                                address <= address_plus_index;
392
                                                temp_addr <= address_plus_index;
393
 
394
                                        end
395
                                        else begin // read modify write
396
                                                control <= MEM_READ;
397
                                                data_out <= 8'h00;
398
                                                address <= address_plus_index;
399
                                                temp_addr <= address_plus_index;
400
                                        end
401
                                end
402 71 creep
                                DUMMY_WRT_CALC: begin
403
                                        pc <= pc;
404
                                        address <= temp_addr;
405
                                        control <= MEM_WRITE;
406
                                        data_out <= alu_result;
407 70 creep
                                end
408 71 creep
                                WRITE_MEM: begin
409
                                        pc <= pc;
410
                                        address <= pc;
411 83 creep
                                        control <= MEM_READ;
412
                                        data_out <= 8'h00;
413 70 creep
                                end
414 95 creep
                                READ_FROM_POINTER: begin
415 101 creep
                                        if (jump_indirect) begin
416
                                                pc[7:0] <= data_in;
417
                                                control <= MEM_READ;
418 96 creep
                                                address <= address_plus_index;
419
                                        end
420 101 creep
                                        else begin
421
                                                pc <= pc;
422
                                                control <= MEM_READ;
423
 
424
                                                if (indirectx) begin
425
                                                        address <= address_plus_index;
426
                                                end
427
                                                else begin // indirecty falls here
428
                                                        address <= address_plus_index;
429
                                                        temp_addr <= {{5{1'b0}}, data_in};
430
                                                end
431 96 creep
                                        end
432 95 creep
                                end
433
                                READ_FROM_POINTER_X: begin
434
                                        pc <= pc;
435
                                        address <= address_plus_index;
436
                                        temp_addr[7:0] <= data_in;
437
                                        control <= MEM_READ;
438
                                end
439
                                READ_FROM_POINTER_X1: begin
440 101 creep
                                        if (jump_indirect) begin
441
                                                pc[12:8] <= data_in[4:0];
442
                                                control <= MEM_READ;
443
                                                address <= {data_in[4:0], pc[7:0]};
444
                                        end
445
                                        else if (indirectx) begin
446
                                                address <= {data_in[4:0], temp_addr[7:0]};
447 96 creep
                                                if (write) begin
448
                                                        control <= MEM_WRITE;
449
                                                        data_out <= alu_result;
450
                                                end
451
                                                else begin
452
                                                        control <= MEM_READ;
453
                                                end
454 95 creep
                                        end
455 96 creep
                                        else begin // indirecty falls here
456
                                                address <= address_plus_index;
457
                                                temp_addr[12:8] <= data_in;
458 95 creep
                                                control <= MEM_READ;
459
                                        end
460
                                end
461 104 creep
                                PUSH_PCH: begin
462
                                        pc <= pc;
463
                                        address <= sp;
464
                                        data_out <= pc[7:0];
465
                                        control <= MEM_WRITE;
466
                                        sp <= sp_minus_one;
467
                                end
468
                                PUSH_PCL: begin
469
                                        pc <= pc;
470
                                        address <= sp;
471
                                        data_out <= alu_status;
472
                                        control <= MEM_WRITE;
473
                                        sp <= sp_minus_one;
474
                                end
475
                                PUSH_STATUS: begin
476
                                        address <= 13'hFFFE;
477
                                        control <= MEM_READ;
478
                                end
479
                                FETCH_PCL: begin
480
                                        pc[7:0] <= data_in;
481
                                        address <= 13'hFFFF;
482
                                        control <= MEM_READ;
483
                                end
484
                                FETCH_PCH: begin
485
                                        pc[12:8] <= data_in[4:0];
486
                                        address <= {data_in[4:0], pc[7:0]};
487
                                        control <= MEM_READ;
488
                                end
489 70 creep
                                default: begin
490 95 creep
                                        $write("unknown state"); // TODO: check if synth really ignores this 2 lines. Otherwise wrap it with a `ifdef 
491 70 creep
                                        $finish(0);
492
                                end
493
 
494
                        endcase
495
                end
496
        end
497
 
498 71 creep
        always @ (*) begin // this is the next_state logic and the output logic always block
499
                alu_opcode = 8'h00;
500
                alu_a = 8'h00;
501
                alu_enable = 1'b0;
502 70 creep
 
503 71 creep
                next_state = RESET; // this prevents the latch
504 68 creep
 
505 71 creep
                case (state)
506
                        RESET: begin
507
                                next_state = FETCH_OP;
508
                        end
509
                        FETCH_OP: begin
510
                                next_state = FETCH_LOW;
511
                        end
512 82 creep
                        //FETCH_OP_CALC: begin // so far no addressing mode required the use of this state
513
                        //      next_state = FETCH_LOW;
514
                        //      alu_opcode = ir;
515
                        //      alu_enable = 1'b1;
516
                        //end
517 71 creep
                        FETCH_OP_CALC_PARAM: begin
518
                                next_state = FETCH_LOW;
519
                                alu_opcode = ir;
520
                                alu_enable = 1'b1;
521
                                alu_a = temp_data;
522
                        end
523
                        FETCH_LOW: begin
524
                                if (accumulator  || implied) begin
525
                                        alu_opcode = ir;
526
                                        alu_enable = 1'b1;
527
                                        next_state = FETCH_OP;
528
                                end
529
                                else if (immediate) begin
530
                                        next_state = FETCH_OP_CALC_PARAM;
531
                                end
532 77 creep
                                else if (zero_page) begin
533
                                        if (read || read_modify_write) begin
534
                                                next_state = READ_MEM;
535
                                        end
536
                                        else if (write) begin
537
                                                next_state = WRITE_MEM;
538 86 creep
                                                alu_opcode = ir;
539
                                                alu_enable = 1'b1;
540
                                                alu_a = 8'h00;
541 77 creep
                                        end
542
                                        else begin
543
                                                $write("unknown behavior");
544
                                                $finish(0);
545
                                        end
546
                                end
547 86 creep
                                else if (zero_page_indexed) begin
548
                                        next_state = READ_MEM_CALC_INDEX;
549
                                end
550 101 creep
                                else if (absolute || jump_indirect) begin // at least the absolute address mode falls here
551 71 creep
                                        next_state = FETCH_HIGH;
552 87 creep
                                        if (write) begin // this is being done one cycle early but i have checked and the ALU will still work properly
553 86 creep
                                                alu_opcode = ir;
554
                                                alu_enable = 1'b1;
555
                                                alu_a = 8'h00;
556
                                        end
557 71 creep
                                end
558 87 creep
                                else if (absolute_indexed) begin
559
                                        next_state = FETCH_HIGH_CALC_INDEX;
560
                                end
561 94 creep
                                else if (relative) begin
562
                                        next_state = FETCH_OP_EVAL_BRANCH;
563
                                end
564 96 creep
                                else if (indirectx || indirecty) begin
565 95 creep
                                        next_state = READ_FROM_POINTER;
566
                                end
567 102 creep
                                else begin // all the special instructions will fall here
568 104 creep
                                        if (break) begin
569
                                                next_state = PUSH_PCH;
570
                                        end
571 102 creep
                                end
572 71 creep
                        end
573 95 creep
                        READ_FROM_POINTER: begin
574 96 creep
                                if (indirectx) begin
575
                                        next_state = READ_FROM_POINTER_X;
576
                                end
577 101 creep
                                else begin // indirecty and jump indirect falls here
578 96 creep
                                        next_state = READ_FROM_POINTER_X1;
579
                                end
580 95 creep
                        end
581
                        READ_FROM_POINTER_X: begin
582
                                next_state = READ_FROM_POINTER_X1;
583
                        end
584
                        READ_FROM_POINTER_X1: begin
585 101 creep
                                if (jump_indirect) begin
586
                                        next_state = FETCH_OP;
587
                                end
588
                                else if (indirecty) begin
589 96 creep
                                        next_state = READ_MEM_FIX_ADDR;
590 95 creep
                                end
591 96 creep
                                else begin
592 102 creep
                                        if (read) begin // read_modify_write was showing up here for no reason. no instruction using pointers is from that type.
593 96 creep
                                                next_state = READ_MEM;
594
                                        end
595
                                        else if (write) begin
596
                                                alu_opcode = ir;
597
                                                alu_enable = 1'b1;
598
                                                next_state = WRITE_MEM;
599
                                        end
600 95 creep
                                end
601
                        end
602 94 creep
                        FETCH_OP_EVAL_BRANCH: begin
603
                                if (branch) begin
604
                                        next_state = FETCH_OP_FIX_PC;
605
                                end
606
                                else begin
607
                                        next_state = FETCH_LOW;
608
                                end
609
                        end
610
                        FETCH_OP_FIX_PC: begin
611
                                if (page_crossed) begin
612
                                        next_state = FETCH_OP;
613
                                end
614
                                else begin
615
                                        next_state = FETCH_LOW;
616
                                end
617
                        end
618 87 creep
                        FETCH_HIGH_CALC_INDEX: begin
619
                                next_state = READ_MEM_FIX_ADDR;
620
                        end
621
                        READ_MEM_FIX_ADDR: begin
622
                                if (read) begin
623
                                        if (page_crossed) begin
624
                                                next_state = READ_MEM;
625
                                        end
626
                                        else begin
627
                                                next_state = FETCH_OP_CALC_PARAM;
628
                                        end
629
                                end
630
                                else if (read_modify_write) begin
631
                                        next_state = READ_MEM;
632
                                end
633
                                else if (write) begin
634
                                        next_state = WRITE_MEM;
635 100 creep
                                        alu_enable = 1'b1;
636
                                        alu_opcode = ir;
637 87 creep
                                end
638
                                else begin
639
                                        $write("unknown behavior");
640
                                        $finish(0);
641
                                end
642
                        end
643 71 creep
                        FETCH_HIGH: begin
644 101 creep
                                if (jump_indirect) begin
645
                                        next_state = READ_FROM_POINTER;
646
                                end
647
                                else if (jump) begin
648 68 creep
                                        next_state = FETCH_OP;
649 61 creep
                                end
650 71 creep
                                else if (read || read_modify_write) begin
651
                                        next_state = READ_MEM;
652 61 creep
                                end
653 71 creep
                                else if (write) begin
654
                                        next_state = WRITE_MEM;
655 68 creep
                                end
656 71 creep
                                else begin
657
                                        $write("unknown behavior");
658
                                        $finish(0);
659 61 creep
                                end
660 71 creep
                        end
661 86 creep
                        READ_MEM_CALC_INDEX: begin
662
                                if (read || read_modify_write) begin
663
                                        next_state = READ_MEM;
664
                                end
665
                                else if (write) begin
666
                                        alu_opcode = ir;
667
                                        alu_enable = 1'b1;
668
                                        next_state = WRITE_MEM;
669
                                end
670
                                else begin
671
                                        $write("unknown behavior");
672
                                        $finish(0);
673
                                end
674
                        end
675 71 creep
                        READ_MEM: begin
676
                                if (read) begin
677
                                        next_state = FETCH_OP_CALC_PARAM;
678 61 creep
                                end
679 71 creep
                                else if (read_modify_write) begin
680
                                        next_state = DUMMY_WRT_CALC;
681
                                end
682
                        end
683
                        DUMMY_WRT_CALC: begin
684
                                alu_opcode = ir;
685
                                alu_enable = 1'b1;
686
                                alu_a = data_in;
687
                                next_state = WRITE_MEM;
688
                        end
689
                        WRITE_MEM: begin
690
                                next_state = FETCH_OP;
691
                        end
692 104 creep
                        PUSH_PCH: begin
693
                                next_state = PUSH_PCL;
694
                        end
695
                        PUSH_PCL: begin
696
                                next_state = PUSH_STATUS;
697
                        end
698
                        PUSH_STATUS: begin
699
                                next_state = FETCH_PCL;
700
                        end
701
                        FETCH_PCL: begin
702
                                next_state = FETCH_PCH;
703
                        end
704
                        FETCH_PCH: begin
705
                                next_state = FETCH_OP;
706
                        end
707 71 creep
                        default: begin
708
                                next_state = RESET;
709
                        end
710
                endcase
711 61 creep
        end
712
 
713 77 creep
        // this always block is responsible for updating the address mode and the type of operation being done
714 68 creep
        always @ (*) begin // 
715 61 creep
                absolute = 1'b0;
716
                absolute_indexed = 1'b0;
717
                accumulator = 1'b0;
718
                immediate = 1'b0;
719
                implied = 1'b0;
720 95 creep
                indirectx = 1'b0;
721
                indirecty = 1'b0;
722 61 creep
                relative = 1'b0;
723
                zero_page = 1'b0;
724
                zero_page_indexed = 1'b0;
725 86 creep
 
726
                index = 1'b0;
727 61 creep
 
728
                read = 1'b0;
729
                read_modify_write = 1'b0;
730
                write = 1'b0;
731
                jump = 1'b0;
732 101 creep
                jump_indirect = 1'b0;
733 94 creep
                branch = 1'b0;
734
 
735 104 creep
                break = 1'b0;
736
 
737 70 creep
                case (ir)
738 102 creep
                        CLC_IMP, CLD_IMP, CLI_IMP, CLV_IMP, DEX_IMP, DEY_IMP, INX_IMP, INY_IMP, NOP_IMP, PHA_IMP, PHP_IMP, PLA_IMP,
739 70 creep
                        PLP_IMP, RTI_IMP, RTS_IMP, SEC_IMP, SED_IMP, SEI_IMP, TAX_IMP, TAY_IMP, TSX_IMP, TXA_IMP, TXS_IMP, TYA_IMP: begin
740
                                implied = 1'b1;
741
                        end
742
                        ASL_ACC, LSR_ACC, ROL_ACC, ROR_ACC: begin
743
                                accumulator = 1'b1;
744
                        end
745
                        ADC_IMM, AND_IMM, CMP_IMM, CPX_IMM, CPY_IMM, EOR_IMM, LDA_IMM, LDX_IMM, LDY_IMM, ORA_IMM, SBC_IMM: begin
746
                                immediate = 1'b1;
747
                        end
748
                        ADC_ZPG, AND_ZPG, ASL_ZPG, BIT_ZPG, CMP_ZPG, CPX_ZPG, CPY_ZPG, DEC_ZPG, EOR_ZPG, INC_ZPG, LDA_ZPG, LDX_ZPG, LDY_ZPG,
749
                        LSR_ZPG, ORA_ZPG, ROL_ZPG, ROR_ZPG, SBC_ZPG, STA_ZPG, STX_ZPG, STY_ZPG: begin
750
                                zero_page = 1'b1;
751
                        end
752
                        ADC_ZPX, AND_ZPX, ASL_ZPX, CMP_ZPX, DEC_ZPX, EOR_ZPX, INC_ZPX, LDA_ZPX, LDY_ZPX, LSR_ZPX, ORA_ZPX, ROL_ZPX, ROR_ZPX,
753 86 creep
                        SBC_ZPX, STA_ZPX, STY_ZPX: begin
754 70 creep
                                zero_page_indexed = 1'b1;
755 86 creep
                                index = alu_x;
756 70 creep
                        end
757 86 creep
                        LDX_ZPY, STX_ZPY: begin
758
                                zero_page_indexed = 1'b1;
759
                                index = alu_y;
760
                        end
761 94 creep
                        BCC_REL: begin
762 70 creep
                                relative = 1'b1;
763 94 creep
                                index = temp_data;
764
 
765
                                if (!alu_status[C]) begin
766
                                        branch = 1'b1;
767
                                end
768
                                else begin
769
                                        branch = 1'b0;
770
                                end
771 70 creep
                        end
772 94 creep
                        BCS_REL: begin
773
                                relative = 1'b1;
774
                                index = temp_data;
775
 
776
                                if (alu_status[C]) begin
777
                                        branch = 1'b1;
778
                                end
779
                                else begin
780
                                        branch = 1'b0;
781
                                end
782
                        end
783
                        BEQ_REL: begin
784
                                relative = 1'b1;
785
                                index = temp_data;
786
 
787
                                if (alu_status[Z]) begin
788
                                        branch = 1'b1;
789
                                end
790
                                else begin
791
                                        branch = 1'b0;
792
                                end
793
                        end
794
                        BNE_REL: begin
795
                                relative = 1'b1;
796
                                index = temp_data;
797
 
798
                                if (alu_status[Z] == 1'b0) begin
799
                                        branch = 1'b1;
800
                                end
801
                                else begin
802
                                        branch = 1'b0;
803
                                end
804
                        end
805
                        BPL_REL: begin
806
                                relative = 1'b1;
807
                                index = temp_data;
808
 
809
                                if (!alu_status[N]) begin
810
                                        branch = 1'b1;
811
                                end
812
                                else begin
813
                                        branch = 1'b0;
814
                                end
815
                        end
816
                        BMI_REL: begin
817
                                relative = 1'b1;
818
                                index = temp_data;
819
 
820
                                if (alu_status[N]) begin
821
                                        branch = 1'b1;
822
                                end
823
                                else begin
824
                                        branch = 1'b0;
825
                                end
826
                        end
827
                        BVC_REL: begin
828
                                relative = 1'b1;
829
                                index = temp_data;
830
 
831
                                if (!alu_status[V]) begin
832
                                        branch = 1'b1;
833
                                end
834
                                else begin
835
                                        branch = 1'b0;
836
                                end
837
                        end
838
                        BVS_REL: begin
839
                                relative = 1'b1;
840
                                index = temp_data;
841
 
842
                                if (alu_status[V]) begin
843
                                        branch = 1'b1;
844
                                end
845
                                else begin
846
                                        branch = 1'b0;
847
                                end
848
                        end
849 101 creep
                        ADC_ABS, AND_ABS, ASL_ABS, BIT_ABS, CMP_ABS, CPX_ABS, CPY_ABS, DEC_ABS, EOR_ABS, INC_ABS, JSR_ABS, LDA_ABS,
850 70 creep
                        LDX_ABS, LDY_ABS, LSR_ABS, ORA_ABS, ROL_ABS, ROR_ABS, SBC_ABS, STA_ABS, STX_ABS, STY_ABS: begin
851
                                absolute = 1'b1;
852
                        end
853
                        ADC_ABX, AND_ABX, ASL_ABX, CMP_ABX, DEC_ABX, EOR_ABX, INC_ABX, LDA_ABX, LDY_ABX, LSR_ABX, ORA_ABX, ROL_ABX, ROR_ABX,
854 87 creep
                        SBC_ABX, STA_ABX: begin
855 70 creep
                                absolute_indexed = 1'b1;
856 87 creep
                                index = alu_x;
857 70 creep
                        end
858 87 creep
                        ADC_ABY, AND_ABY, CMP_ABY, EOR_ABY, LDA_ABY, LDX_ABY, ORA_ABY, SBC_ABY, STA_ABY: begin
859
                                absolute_indexed = 1'b1;
860
                                index = alu_y;
861
                        end
862 95 creep
                        ADC_IDX, AND_IDX, CMP_IDX, EOR_IDX, LDA_IDX, ORA_IDX, SBC_IDX, STA_IDX: begin
863
                                indirectx = 1'b1;
864
                                index = alu_x;
865 70 creep
                        end
866 95 creep
                        ADC_IDY, AND_IDY, CMP_IDY, EOR_IDY, LDA_IDY, ORA_IDY, SBC_IDY, STA_IDY: begin
867
                                indirecty = 1'b1;
868
                                index = alu_y;
869
                        end
870 101 creep
                        JMP_ABS: begin
871
                                absolute = 1'b1;
872
                                jump = 1'b1;
873
                        end
874
                        JMP_IND: begin
875
                                jump_indirect = 1'b1;
876
                        end
877 102 creep
                        BRK_IMP: begin
878 104 creep
                                break = 1'b1;
879 102 creep
                        end
880 71 creep
                        default: begin
881 94 creep
                                $write("state : %b", state);
882
                                if (reset_n == 1 && state != FETCH_OP_FIX_PC) begin // the processor is NOT being reset neither it is fixing the pc
883 86 creep
                                        $write("\nunknown OPCODE!!!!! 0x%h\n", ir);
884
                                        $finish();
885
                                end
886 71 creep
                        end
887 70 creep
                endcase
888 71 creep
 
889
                case (ir)
890
                        ASL_ACC, ASL_ZPG, ASL_ZPX, ASL_ABS, ASL_ABX, LSR_ACC, LSR_ZPG, LSR_ZPX, LSR_ABS, LSR_ABX, ROL_ACC, ROL_ZPG, ROL_ZPX, ROL_ABS,
891
                        ROL_ABX, ROR_ACC, ROR_ZPG, ROR_ZPX, ROR_ABS, ROR_ABX, INC_ZPG, INC_ZPX, INC_ABS, INC_ABX, DEC_ZPG, DEC_ZPX, DEC_ABS,
892
                        DEC_ABX: begin
893
                                read_modify_write = 1'b1;
894
                        end
895
                        STA_ZPG, STA_ZPX, STA_ABS, STA_ABX, STA_ABY, STA_IDX, STA_IDY, STX_ZPG, STX_ZPY, STX_ABS, STY_ZPG, STY_ZPX, STY_ABS: begin
896
                                write = 1'b1;
897
                        end
898
                        default: begin // this should work fine since the previous case statement will detect the unknown/undocumented/unsupported opcodes
899
                                read = 1'b1;
900
                        end
901
                endcase
902 86 creep
        end
903 61 creep
endmodule
904
 
905
 
906
 

powered by: WebSVN 2.1.0

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