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

Subversion Repositories t6507lp

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

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

powered by: WebSVN 2.1.0

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