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

Subversion Repositories t6507lp

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

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 61 creep
 
89 95 creep
        localparam RESET = 5'b11111;
90
 
91 61 creep
        // OPCODES TODO: verify how this get synthesised
92
        `include "../T6507LP_Package.v"
93
 
94
        // control signals
95
        localparam MEM_READ = 1'b0;
96
        localparam MEM_WRITE = 1'b1;
97
 
98 82 creep
        reg [ADDR_SIZE_:0] pc;           // program counter
99 102 creep
        reg [ADDR_SIZE_:0] sp;           // stack pointer
100 82 creep
        reg [DATA_SIZE_:0] ir;           // instruction register
101
        reg [ADDR_SIZE_:0] temp_addr;    // temporary address
102
        reg [DATA_SIZE_:0] temp_data;    // temporary data
103 61 creep
 
104 96 creep
        reg [4:0] state, next_state; // current and next state registers
105 61 creep
        // TODO: not sure if this will be 4 bits wide. as of march 9th this was 4bit wide.
106
 
107
        // wiring that simplifies the FSM logic
108
        reg absolute;
109
        reg absolute_indexed;
110
        reg accumulator;
111
        reg immediate;
112
        reg implied;
113 95 creep
        reg indirectx;
114
        reg indirecty;
115 61 creep
        reg relative;
116
        reg zero_page;
117
        reg zero_page_indexed;
118 86 creep
        reg [DATA_SIZE_:0] index; // will be assigned with either X or Y
119 61 creep
 
120
        // regs that store the type of operation. again, this simplifies the FSM a lot.
121
        reg read;
122
        reg read_modify_write;
123
        reg write;
124
        reg jump;
125 101 creep
        reg jump_indirect;
126 61 creep
 
127 82 creep
        wire [ADDR_SIZE_:0] next_pc;
128 63 creep
        assign next_pc = pc + 13'b0000000000001;
129 61 creep
 
130 87 creep
        reg [ADDR_SIZE_:0] address_plus_index; // this would update more times than actually needed, consuming power.
131
        reg page_crossed;                       // so the simple assign was changed into a combinational always block
132
 
133 94 creep
        reg branch;
134
 
135 87 creep
        always @(*) begin
136
                address_plus_index = 0;
137
                page_crossed = 0;
138 86 creep
 
139 88 creep
                if (state == READ_MEM_CALC_INDEX || state == READ_MEM_FIX_ADDR || state == FETCH_HIGH_CALC_INDEX) begin
140
                        {page_crossed, address_plus_index[7:0]} = temp_addr[7:0] + index;
141
                        address_plus_index[12:8] = temp_addr[12:8] + page_crossed;
142 87 creep
                end
143 94 creep
                else if (branch) begin
144
                        if (state == FETCH_OP_FIX_PC || state == FETCH_OP_EVAL_BRANCH) begin
145
                                {page_crossed, address_plus_index[7:0]} = pc[7:0] + index;
146
                                address_plus_index[12:8] = pc[12:8] + page_crossed;// warning: pc might feed these lines twice and cause branch failure
147
                        end                                                             // solution: add a temp reg i guess
148
                end
149 95 creep
                else if (state == READ_FROM_POINTER) begin
150 96 creep
                        if (indirectx) begin
151
                                {page_crossed, address_plus_index[7:0]} = temp_data + index;
152
                                address_plus_index[12:8] = 5'b00000;
153
                        end
154 101 creep
                        else if (jump_indirect) begin
155
                                address_plus_index[7:0] = temp_addr + 8'h01;
156
                                address_plus_index[12:8] = 5'b00000;
157
                        end
158 96 creep
                        else begin // indirecty falls here
159
                                address_plus_index[7:0] = temp_data + 8'h01;
160
                                address_plus_index[12:8] = 5'b00000;
161
                        end
162 95 creep
                end
163
                else if (state == READ_FROM_POINTER_X) begin
164
                        {page_crossed, address_plus_index[7:0]} = temp_data + index + 8'h01;
165
                        address_plus_index[12:8] = 5'b00000;
166
                end
167 96 creep
                else if (state == READ_FROM_POINTER_X1) begin
168
                        {page_crossed, address_plus_index[7:0]} = temp_addr[7:0] + index;
169
                        address_plus_index[12:8] = temp_addr[12:8] + page_crossed;
170
                end
171 87 creep
        end
172
 
173 103 creep
        wire [8:0] sp_plus_one;
174
        assign sp_plus_one = sp + 9'b000000001;
175
 
176
        wire [8:0] sp_minus_one;
177
        assign sp_minus_one = sp - 9'b000000001;
178
 
179 71 creep
        always @ (posedge clk or negedge reset_n) begin // sequencial always block
180
                if (reset_n == 1'b0) begin
181
                        // all registers must assume default values
182 68 creep
                        pc <= 0; // TODO: this is written somewhere. something about a reset vector. must be checked.
183 103 creep
                        sp <= 9'b100000000; // the default is 'h100 
184 82 creep
                        ir <= 8'h00;
185 102 creep
                        temp_addr <= 13'h00;
186 82 creep
                        temp_data <= 8'h00;
187 68 creep
                        state <= RESET;
188 71 creep
                        // registered outputs also receive default values
189
                        address <= 0;
190 82 creep
                        control <= MEM_READ;
191
                        data_out <= 8'h00;
192 61 creep
                end
193
                else begin
194
                        state <= next_state;
195 83 creep
 
196 61 creep
                        case (state)
197 68 creep
                                RESET: begin
198 82 creep
                                        // The processor was reset
199
                                        $write("under reset");
200 68 creep
                                end
201 61 creep
                                FETCH_OP: begin // this state is the simplest one. it is a simple fetch that must be done when the cpu was reset or
202
                                                // the last cycle was a memory write.
203
                                        pc <= next_pc;
204 71 creep
                                        address <= next_pc;
205 83 creep
                                        control <= MEM_READ;
206 70 creep
                                        ir <= data_in;
207 61 creep
                                end
208 71 creep
                                FETCH_OP_CALC, FETCH_OP_CALC_PARAM: begin // this is the pipeline happening!
209 61 creep
                                        pc <= next_pc;
210 71 creep
                                        address <= next_pc;
211 83 creep
                                        control <= MEM_READ;
212 70 creep
                                        ir <= data_in;
213 61 creep
                                end
214 68 creep
                                FETCH_LOW: begin // in this state the opcode is already known so truly execution begins
215
                                        if (accumulator || implied) begin
216 70 creep
                                                pc <= pc; // is this better?
217 71 creep
                                                address <= pc;
218 83 creep
                                                control <= MEM_READ;
219 61 creep
                                        end
220 94 creep
                                        else if (immediate || relative) begin
221 68 creep
                                                pc <= next_pc;
222 71 creep
                                                address <= next_pc;
223 83 creep
                                                control <= MEM_READ;
224 70 creep
                                                temp_data <= data_in; // the follow-up byte is saved in temp_data 
225 61 creep
                                        end
226 101 creep
                                        else if (absolute || absolute_indexed || jump_indirect) begin
227 71 creep
                                                pc <= next_pc;
228
                                                address <= next_pc;
229 83 creep
                                                control <= MEM_READ;
230 87 creep
                                                temp_addr <= {{5{1'b0}},data_in};
231 101 creep
                                                temp_data <= 8'h00;
232 71 creep
                                        end
233 77 creep
                                        else if (zero_page) begin
234
                                                pc <= next_pc;
235
                                                address <= {{5{1'b0}},data_in};
236 78 creep
                                                temp_addr <= {{5{1'b0}},data_in};
237
 
238 77 creep
                                                if (write) begin
239
                                                        control <= MEM_WRITE;
240 78 creep
                                                        data_out <= alu_result;
241 77 creep
                                                end
242 83 creep
                                                else begin
243
                                                        control <= MEM_READ;
244
                                                        data_out <= 8'h00;
245
                                                end
246 77 creep
                                        end
247 86 creep
                                        else if (zero_page_indexed) begin
248
                                                pc <= next_pc;
249 94 creep
                                                address <= {{5{1'b0}}, data_in};
250
                                                temp_addr <= {{5{1'b0}}, data_in};
251 86 creep
                                                control <= MEM_READ;
252
                                        end
253 96 creep
                                        else if (indirectx || indirecty) begin
254 95 creep
                                                pc <= next_pc;
255
                                                address <= data_in;
256
                                                temp_data <= data_in;
257
                                                control <= MEM_READ;
258
                                        end
259 102 creep
                                        else begin // the special instructions will fall here: BRK, RTI, RTS...
260
 
261
                                        end
262 61 creep
                                end
263 87 creep
                                FETCH_HIGH_CALC_INDEX: begin
264
                                        pc <= next_pc;
265
                                        temp_addr[12:8] <= data_in[4:0];
266
                                        address <= {data_in[4:0], address_plus_index[7:0]};
267
                                        control <= MEM_READ;
268
                                        data_out <= 8'h00;
269
                                end
270 94 creep
                                FETCH_OP_EVAL_BRANCH: begin
271
                                        if (branch) begin
272
                                                pc <= {{5{1'b0}}, address_plus_index[7:0]};
273
                                                address <= {{5{1'b0}}, address_plus_index[7:0]};
274
                                                control <= MEM_READ;
275
                                                data_out <= 8'h00;
276
                                        end
277
                                        else begin
278
                                                pc <= next_pc;
279
                                                address <= next_pc;
280
                                                control <= MEM_READ;
281
                                                data_out <= 8'h00;
282 95 creep
                                                ir <= data_in;
283 94 creep
                                        end
284
                                end
285
                                FETCH_OP_FIX_PC: begin
286
                                        if (page_crossed) begin
287
                                                pc[12:8] <= address_plus_index[12:8];
288
                                                address[12:8] <= address_plus_index[12:8];
289
                                        end
290
                                        else begin
291
                                                pc <= next_pc;
292
                                                address <= next_pc;
293
                                                control <= MEM_READ;
294
                                                ir <= data_in;
295
                                        end
296
                                end
297 71 creep
                                FETCH_HIGH: begin
298
                                        if (jump) begin
299 83 creep
                                                pc <= {data_in[4:0], temp_addr[7:0]}; // PCL <= first byte, PCH <= second byte
300
                                                address <= {data_in[4:0], temp_addr[7:0]};
301
                                                control <= MEM_READ;
302
                                                data_out <= 8'h00;
303 71 creep
                                        end
304
                                        else begin
305
                                                if (write) begin
306
                                                        pc <= next_pc;
307
                                                        temp_addr[12:8] <= data_in[4:0];
308
                                                        address <= {data_in[4:0],temp_addr[7:0]};
309
                                                        control <= MEM_WRITE;
310 77 creep
                                                        data_out <= alu_result;
311 71 creep
                                                end
312
                                                else begin // read_modify_write or just read
313
                                                        pc <= next_pc;
314
                                                        temp_addr[12:8] <= data_in[4:0];
315
                                                        address <= {data_in[4:0],temp_addr[7:0]};
316 83 creep
                                                        control <= MEM_READ;
317
                                                        data_out <= 8'h00;
318 71 creep
                                                end
319
                                        end
320
                                        //else begin
321
                                        //      $write("FETCHHIGH PROBLEM"); 
322
                                        //      $finish(0); 
323
                                        //end
324 61 creep
                                end
325 71 creep
                                READ_MEM: begin
326
                                        if (read_modify_write) begin
327
                                                pc <= pc;
328
                                                address <= temp_addr;
329
                                                control <= MEM_WRITE;
330
                                                temp_data <= data_in;
331
                                                data_out <= data_in; // writeback the same value
332
                                        end
333
                                        else begin
334
                                                pc <= pc;
335
                                                address <= pc;
336
                                                temp_data <= data_in;
337 83 creep
                                                control <= MEM_READ;
338
                                                data_out <= 8'h00;
339 71 creep
                                        end
340 70 creep
                                end
341 86 creep
                                READ_MEM_CALC_INDEX: begin
342
                                                //pc <= next_pc; // pc was  already updated in the previous cycle
343
                                                address <= address_plus_index;
344
                                                temp_addr <= address_plus_index;
345
 
346
                                                if (write) begin
347
                                                        control <= MEM_WRITE;
348
                                                        data_out <= alu_result;
349
                                                end
350
                                                else begin
351
                                                        control <= MEM_READ;
352
                                                        data_out <= 8'h00;
353
                                                end
354
 
355
                                end
356 87 creep
                                READ_MEM_FIX_ADDR: begin
357
                                        if (read) begin
358
                                                control <= MEM_READ;
359
                                                data_out <= 8'h00;
360
 
361
                                                if (page_crossed) begin
362
                                                        address <= address_plus_index;
363
                                                        temp_addr <= address_plus_index;
364
                                                end
365
                                                else begin
366
                                                        address <= pc;
367
                                                        temp_data <= data_in;
368
                                                end
369
                                        end
370
                                        else if (write) begin
371
                                                control <= MEM_WRITE;
372
                                                data_out <= alu_result;
373
                                                address <= address_plus_index;
374
                                                temp_addr <= address_plus_index;
375
 
376
                                        end
377
                                        else begin // read modify write
378
                                                control <= MEM_READ;
379
                                                data_out <= 8'h00;
380
                                                address <= address_plus_index;
381
                                                temp_addr <= address_plus_index;
382
                                        end
383
                                end
384 71 creep
                                DUMMY_WRT_CALC: begin
385
                                        pc <= pc;
386
                                        address <= temp_addr;
387
                                        control <= MEM_WRITE;
388
                                        data_out <= alu_result;
389 70 creep
                                end
390 71 creep
                                WRITE_MEM: begin
391
                                        pc <= pc;
392
                                        address <= pc;
393 83 creep
                                        control <= MEM_READ;
394
                                        data_out <= 8'h00;
395 70 creep
                                end
396 95 creep
                                READ_FROM_POINTER: begin
397 101 creep
                                        if (jump_indirect) begin
398
                                                pc[7:0] <= data_in;
399
                                                control <= MEM_READ;
400 96 creep
                                                address <= address_plus_index;
401
                                        end
402 101 creep
                                        else begin
403
                                                pc <= pc;
404
                                                control <= MEM_READ;
405
 
406
                                                if (indirectx) begin
407
                                                        address <= address_plus_index;
408
                                                end
409
                                                else begin // indirecty falls here
410
                                                        address <= address_plus_index;
411
                                                        temp_addr <= {{5{1'b0}}, data_in};
412
                                                end
413 96 creep
                                        end
414 95 creep
                                end
415
                                READ_FROM_POINTER_X: begin
416
                                        pc <= pc;
417
                                        address <= address_plus_index;
418
                                        temp_addr[7:0] <= data_in;
419
                                        control <= MEM_READ;
420
                                end
421
                                READ_FROM_POINTER_X1: begin
422 101 creep
                                        if (jump_indirect) begin
423
                                                pc[12:8] <= data_in[4:0];
424
                                                control <= MEM_READ;
425
                                                address <= {data_in[4:0], pc[7:0]};
426
                                        end
427
                                        else if (indirectx) begin
428
                                                address <= {data_in[4:0], temp_addr[7:0]};
429 96 creep
                                                if (write) begin
430
                                                        control <= MEM_WRITE;
431
                                                        data_out <= alu_result;
432
                                                end
433
                                                else begin
434
                                                        control <= MEM_READ;
435
                                                end
436 95 creep
                                        end
437 96 creep
                                        else begin // indirecty falls here
438
                                                address <= address_plus_index;
439
                                                temp_addr[12:8] <= data_in;
440 95 creep
                                                control <= MEM_READ;
441
                                        end
442
                                end
443 70 creep
                                default: begin
444 95 creep
                                        $write("unknown state"); // TODO: check if synth really ignores this 2 lines. Otherwise wrap it with a `ifdef 
445 70 creep
                                        $finish(0);
446
                                end
447
 
448
                        endcase
449
                end
450
        end
451
 
452 71 creep
        always @ (*) begin // this is the next_state logic and the output logic always block
453
                alu_opcode = 8'h00;
454
                alu_a = 8'h00;
455
                alu_enable = 1'b0;
456 70 creep
 
457 71 creep
                next_state = RESET; // this prevents the latch
458 68 creep
 
459 71 creep
                case (state)
460
                        RESET: begin
461
                                next_state = FETCH_OP;
462
                        end
463
                        FETCH_OP: begin
464
                                next_state = FETCH_LOW;
465
                        end
466 82 creep
                        //FETCH_OP_CALC: begin // so far no addressing mode required the use of this state
467
                        //      next_state = FETCH_LOW;
468
                        //      alu_opcode = ir;
469
                        //      alu_enable = 1'b1;
470
                        //end
471 71 creep
                        FETCH_OP_CALC_PARAM: begin
472
                                next_state = FETCH_LOW;
473
                                alu_opcode = ir;
474
                                alu_enable = 1'b1;
475
                                alu_a = temp_data;
476
                        end
477
                        FETCH_LOW: begin
478
                                if (accumulator  || implied) begin
479
                                        alu_opcode = ir;
480
                                        alu_enable = 1'b1;
481
                                        next_state = FETCH_OP;
482
                                end
483
                                else if (immediate) begin
484
                                        next_state = FETCH_OP_CALC_PARAM;
485
                                end
486 77 creep
                                else if (zero_page) begin
487
                                        if (read || read_modify_write) begin
488
                                                next_state = READ_MEM;
489
                                        end
490
                                        else if (write) begin
491
                                                next_state = WRITE_MEM;
492 86 creep
                                                alu_opcode = ir;
493
                                                alu_enable = 1'b1;
494
                                                alu_a = 8'h00;
495 77 creep
                                        end
496
                                        else begin
497
                                                $write("unknown behavior");
498
                                                $finish(0);
499
                                        end
500
                                end
501 86 creep
                                else if (zero_page_indexed) begin
502
                                        next_state = READ_MEM_CALC_INDEX;
503
                                end
504 101 creep
                                else if (absolute || jump_indirect) begin // at least the absolute address mode falls here
505 71 creep
                                        next_state = FETCH_HIGH;
506 87 creep
                                        if (write) begin // this is being done one cycle early but i have checked and the ALU will still work properly
507 86 creep
                                                alu_opcode = ir;
508
                                                alu_enable = 1'b1;
509
                                                alu_a = 8'h00;
510
                                        end
511 71 creep
                                end
512 87 creep
                                else if (absolute_indexed) begin
513
                                        next_state = FETCH_HIGH_CALC_INDEX;
514
                                end
515 94 creep
                                else if (relative) begin
516
                                        next_state = FETCH_OP_EVAL_BRANCH;
517
                                end
518 96 creep
                                else if (indirectx || indirecty) begin
519 95 creep
                                        next_state = READ_FROM_POINTER;
520
                                end
521 102 creep
                                else begin // all the special instructions will fall here
522
                                        next_state = RESET;
523
                                end
524 71 creep
                        end
525 95 creep
                        READ_FROM_POINTER: begin
526 96 creep
                                if (indirectx) begin
527
                                        next_state = READ_FROM_POINTER_X;
528
                                end
529 101 creep
                                else begin // indirecty and jump indirect falls here
530 96 creep
                                        next_state = READ_FROM_POINTER_X1;
531
                                end
532 95 creep
                        end
533
                        READ_FROM_POINTER_X: begin
534
                                next_state = READ_FROM_POINTER_X1;
535
                        end
536
                        READ_FROM_POINTER_X1: begin
537 101 creep
                                if (jump_indirect) begin
538
                                        next_state = FETCH_OP;
539
                                end
540
                                else if (indirecty) begin
541 96 creep
                                        next_state = READ_MEM_FIX_ADDR;
542 95 creep
                                end
543 96 creep
                                else begin
544 102 creep
                                        if (read) begin // read_modify_write was showing up here for no reason. no instruction using pointers is from that type.
545 96 creep
                                                next_state = READ_MEM;
546
                                        end
547
                                        else if (write) begin
548
                                                alu_opcode = ir;
549
                                                alu_enable = 1'b1;
550
                                                next_state = WRITE_MEM;
551
                                        end
552 95 creep
                                end
553
                        end
554 94 creep
                        FETCH_OP_EVAL_BRANCH: begin
555
                                if (branch) begin
556
                                        next_state = FETCH_OP_FIX_PC;
557
                                end
558
                                else begin
559
                                        next_state = FETCH_LOW;
560
                                end
561
                        end
562
                        FETCH_OP_FIX_PC: begin
563
                                if (page_crossed) begin
564
                                        next_state = FETCH_OP;
565
                                end
566
                                else begin
567
                                        next_state = FETCH_LOW;
568
                                end
569
                        end
570 87 creep
                        FETCH_HIGH_CALC_INDEX: begin
571
                                next_state = READ_MEM_FIX_ADDR;
572
                        end
573
                        READ_MEM_FIX_ADDR: begin
574
                                if (read) begin
575
                                        if (page_crossed) begin
576
                                                next_state = READ_MEM;
577
                                        end
578
                                        else begin
579
                                                next_state = FETCH_OP_CALC_PARAM;
580
                                        end
581
                                end
582
                                else if (read_modify_write) begin
583
                                        next_state = READ_MEM;
584
                                end
585
                                else if (write) begin
586
                                        next_state = WRITE_MEM;
587 100 creep
                                        alu_enable = 1'b1;
588
                                        alu_opcode = ir;
589 87 creep
                                end
590
                                else begin
591
                                        $write("unknown behavior");
592
                                        $finish(0);
593
                                end
594
                        end
595 71 creep
                        FETCH_HIGH: begin
596 101 creep
                                if (jump_indirect) begin
597
                                        next_state = READ_FROM_POINTER;
598
                                end
599
                                else if (jump) begin
600 68 creep
                                        next_state = FETCH_OP;
601 61 creep
                                end
602 71 creep
                                else if (read || read_modify_write) begin
603
                                        next_state = READ_MEM;
604 61 creep
                                end
605 71 creep
                                else if (write) begin
606
                                        next_state = WRITE_MEM;
607 68 creep
                                end
608 71 creep
                                else begin
609
                                        $write("unknown behavior");
610
                                        $finish(0);
611 61 creep
                                end
612 71 creep
                        end
613 86 creep
                        READ_MEM_CALC_INDEX: begin
614
                                if (read || read_modify_write) begin
615
                                        next_state = READ_MEM;
616
                                end
617
                                else if (write) begin
618
                                        alu_opcode = ir;
619
                                        alu_enable = 1'b1;
620
                                        next_state = WRITE_MEM;
621
                                end
622
                                else begin
623
                                        $write("unknown behavior");
624
                                        $finish(0);
625
                                end
626
                        end
627 71 creep
                        READ_MEM: begin
628
                                if (read) begin
629
                                        next_state = FETCH_OP_CALC_PARAM;
630 61 creep
                                end
631 71 creep
                                else if (read_modify_write) begin
632
                                        next_state = DUMMY_WRT_CALC;
633
                                end
634
                        end
635
                        DUMMY_WRT_CALC: begin
636
                                alu_opcode = ir;
637
                                alu_enable = 1'b1;
638
                                alu_a = data_in;
639
                                next_state = WRITE_MEM;
640
                        end
641
                        WRITE_MEM: begin
642
                                next_state = FETCH_OP;
643
                        end
644
                        default: begin
645
                                next_state = RESET;
646
                        end
647
                endcase
648 61 creep
        end
649
 
650 77 creep
        // this always block is responsible for updating the address mode and the type of operation being done
651 68 creep
        always @ (*) begin // 
652 61 creep
                absolute = 1'b0;
653
                absolute_indexed = 1'b0;
654
                accumulator = 1'b0;
655
                immediate = 1'b0;
656
                implied = 1'b0;
657 95 creep
                indirectx = 1'b0;
658
                indirecty = 1'b0;
659 61 creep
                relative = 1'b0;
660
                zero_page = 1'b0;
661
                zero_page_indexed = 1'b0;
662 86 creep
 
663
                index = 1'b0;
664 61 creep
 
665
                read = 1'b0;
666
                read_modify_write = 1'b0;
667
                write = 1'b0;
668
                jump = 1'b0;
669 101 creep
                jump_indirect = 1'b0;
670 94 creep
                branch = 1'b0;
671
 
672 70 creep
                case (ir)
673 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,
674 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
675
                                implied = 1'b1;
676
                        end
677
                        ASL_ACC, LSR_ACC, ROL_ACC, ROR_ACC: begin
678
                                accumulator = 1'b1;
679
                        end
680
                        ADC_IMM, AND_IMM, CMP_IMM, CPX_IMM, CPY_IMM, EOR_IMM, LDA_IMM, LDX_IMM, LDY_IMM, ORA_IMM, SBC_IMM: begin
681
                                immediate = 1'b1;
682
                        end
683
                        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,
684
                        LSR_ZPG, ORA_ZPG, ROL_ZPG, ROR_ZPG, SBC_ZPG, STA_ZPG, STX_ZPG, STY_ZPG: begin
685
                                zero_page = 1'b1;
686
                        end
687
                        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,
688 86 creep
                        SBC_ZPX, STA_ZPX, STY_ZPX: begin
689 70 creep
                                zero_page_indexed = 1'b1;
690 86 creep
                                index = alu_x;
691 70 creep
                        end
692 86 creep
                        LDX_ZPY, STX_ZPY: begin
693
                                zero_page_indexed = 1'b1;
694
                                index = alu_y;
695
                        end
696 94 creep
                        BCC_REL: begin
697 70 creep
                                relative = 1'b1;
698 94 creep
                                index = temp_data;
699
 
700
                                if (!alu_status[C]) begin
701
                                        branch = 1'b1;
702
                                end
703
                                else begin
704
                                        branch = 1'b0;
705
                                end
706 70 creep
                        end
707 94 creep
                        BCS_REL: begin
708
                                relative = 1'b1;
709
                                index = temp_data;
710
 
711
                                if (alu_status[C]) begin
712
                                        branch = 1'b1;
713
                                end
714
                                else begin
715
                                        branch = 1'b0;
716
                                end
717
                        end
718
                        BEQ_REL: begin
719
                                relative = 1'b1;
720
                                index = temp_data;
721
 
722
                                if (alu_status[Z]) begin
723
                                        branch = 1'b1;
724
                                end
725
                                else begin
726
                                        branch = 1'b0;
727
                                end
728
                        end
729
                        BNE_REL: begin
730
                                relative = 1'b1;
731
                                index = temp_data;
732
 
733
                                if (alu_status[Z] == 1'b0) begin
734
                                        branch = 1'b1;
735
                                end
736
                                else begin
737
                                        branch = 1'b0;
738
                                end
739
                        end
740
                        BPL_REL: begin
741
                                relative = 1'b1;
742
                                index = temp_data;
743
 
744
                                if (!alu_status[N]) begin
745
                                        branch = 1'b1;
746
                                end
747
                                else begin
748
                                        branch = 1'b0;
749
                                end
750
                        end
751
                        BMI_REL: begin
752
                                relative = 1'b1;
753
                                index = temp_data;
754
 
755
                                if (alu_status[N]) begin
756
                                        branch = 1'b1;
757
                                end
758
                                else begin
759
                                        branch = 1'b0;
760
                                end
761
                        end
762
                        BVC_REL: begin
763
                                relative = 1'b1;
764
                                index = temp_data;
765
 
766
                                if (!alu_status[V]) begin
767
                                        branch = 1'b1;
768
                                end
769
                                else begin
770
                                        branch = 1'b0;
771
                                end
772
                        end
773
                        BVS_REL: begin
774
                                relative = 1'b1;
775
                                index = temp_data;
776
 
777
                                if (alu_status[V]) begin
778
                                        branch = 1'b1;
779
                                end
780
                                else begin
781
                                        branch = 1'b0;
782
                                end
783
                        end
784 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,
785 70 creep
                        LDX_ABS, LDY_ABS, LSR_ABS, ORA_ABS, ROL_ABS, ROR_ABS, SBC_ABS, STA_ABS, STX_ABS, STY_ABS: begin
786
                                absolute = 1'b1;
787
                        end
788
                        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,
789 87 creep
                        SBC_ABX, STA_ABX: begin
790 70 creep
                                absolute_indexed = 1'b1;
791 87 creep
                                index = alu_x;
792 70 creep
                        end
793 87 creep
                        ADC_ABY, AND_ABY, CMP_ABY, EOR_ABY, LDA_ABY, LDX_ABY, ORA_ABY, SBC_ABY, STA_ABY: begin
794
                                absolute_indexed = 1'b1;
795
                                index = alu_y;
796
                        end
797 95 creep
                        ADC_IDX, AND_IDX, CMP_IDX, EOR_IDX, LDA_IDX, ORA_IDX, SBC_IDX, STA_IDX: begin
798
                                indirectx = 1'b1;
799
                                index = alu_x;
800 70 creep
                        end
801 95 creep
                        ADC_IDY, AND_IDY, CMP_IDY, EOR_IDY, LDA_IDY, ORA_IDY, SBC_IDY, STA_IDY: begin
802
                                indirecty = 1'b1;
803
                                index = alu_y;
804
                        end
805 101 creep
                        JMP_ABS: begin
806
                                absolute = 1'b1;
807
                                jump = 1'b1;
808
                        end
809
                        JMP_IND: begin
810
                                jump_indirect = 1'b1;
811
                        end
812 102 creep
                        BRK_IMP: begin
813
                                // something goes in here
814
                        end
815 71 creep
                        default: begin
816 94 creep
                                $write("state : %b", state);
817
                                if (reset_n == 1 && state != FETCH_OP_FIX_PC) begin // the processor is NOT being reset neither it is fixing the pc
818 86 creep
                                        $write("\nunknown OPCODE!!!!! 0x%h\n", ir);
819
                                        $finish();
820
                                end
821 71 creep
                        end
822 70 creep
                endcase
823 71 creep
 
824
                case (ir)
825
                        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,
826
                        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,
827
                        DEC_ABX: begin
828
                                read_modify_write = 1'b1;
829
                        end
830
                        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
831
                                write = 1'b1;
832
                        end
833
                        default: begin // this should work fine since the previous case statement will detect the unknown/undocumented/unsupported opcodes
834
                                read = 1'b1;
835
                        end
836
                endcase
837 86 creep
        end
838 61 creep
endmodule
839
 
840
 
841
 

powered by: WebSVN 2.1.0

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