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

Subversion Repositories t6507lp

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

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

powered by: WebSVN 2.1.0

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