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

Subversion Repositories t6507lp

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

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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