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

Subversion Repositories t6507lp

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

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

powered by: WebSVN 2.1.0

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