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

Subversion Repositories t6507lp

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

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

powered by: WebSVN 2.1.0

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