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

Subversion Repositories t6507lp

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

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

powered by: WebSVN 2.1.0

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