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

Subversion Repositories t6507lp

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

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

Line No. Rev Author Line
1 61 creep
////////////////////////////////////////////////////////////////////////////
2
////                                                                    ////
3
//// T6507LP IP Core                                                    ////
4
////                                                                    ////
5
//// This file is part of the T6507LP project                           ////
6
//// http://www.opencores.org/cores/t6507lp/                            ////
7
////                                                                    ////
8
//// Description                                                        ////
9
//// 6507 FSM                                                           ////
10
////                                                                    ////
11
//// TODO:                                                              ////
12
//// - Fix absolute indexed mode                                        ////
13
//// - Code the relative mode                                           ////
14
//// - Code the indexed indirect mode                                   ////
15
//// - Code the indirect indexed mode                                   ////
16
//// - Code the absolute indirect mode                                  ////
17
////                                                                    ////
18
//// Author(s):                                                         ////
19
//// - Gabriel Oshiro Zardo, gabrieloshiro@gmail.com                    ////
20
//// - Samuel Nascimento Pagliarini (creep), snpagliarini@gmail.com     ////
21
////                                                                    ////
22
////////////////////////////////////////////////////////////////////////////
23
////                                                                    ////
24
//// Copyright (C) 2001 Authors and OPENCORES.ORG                       ////
25
////                                                                    ////
26
//// This source file may be used and distributed without               ////
27
//// restriction provided that this copyright statement is not          ////
28
//// removed from the file and that any derivative work contains        ////
29
//// the original copyright notice and the associated disclaimer.       ////
30
////                                                                    ////
31
//// This source file is free software; you can redistribute it         ////
32
//// and/or modify it under the terms of the GNU Lesser General         ////
33
//// Public License as published by the Free Software Foundation;       ////
34
//// either version 2.1 of the License, or (at your option) any         ////
35
//// later version.                                                     ////
36
////                                                                    ////
37
//// This source is distributed in the hope that it will be             ////
38
//// useful, but WITHOUT ANY WARRANTY; without even the implied         ////
39
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR            ////
40
//// PURPOSE. See the GNU Lesser General Public License for more        ////
41
//// details.                                                           ////
42
////                                                                    ////
43
//// You should have received a copy of the GNU Lesser General          ////
44
//// Public License along with this source; if not, download it         ////
45
//// from http://www.opencores.org/lgpl.shtml                           ////
46
////                                                                    ////
47
////////////////////////////////////////////////////////////////////////////
48
 
49
`timescale 1ns / 1ps
50
 
51
module t6507lp_fsm(clk_in, n_rst_in, alu_result, alu_status, data_in, address, control, data_out, alu_opcode, alu_a);
52
        input clk_in;
53
        input n_rst_in;
54
        input [7:0] alu_result;
55
        input [7:0] alu_status;
56
        input [7:0] data_in;
57
        output reg [12:0] address;
58
        output reg control; // one bit is enough? read = 0, write = 1
59
        output reg [7:0] data_out;
60
        output reg [7:0] alu_opcode;
61
        output reg [7:0] alu_a;
62
 
63
        // FSM states
64
        localparam FETCH_OP = 4'b000;
65
        localparam FETCH_LOW = 4'b0001;
66
        localparam FETCH_HIGH = 4'b0010;
67
        localparam SET_PC = 4'b0011;
68
        localparam READ_EFFECTIVE = 4'b0100;
69
        localparam DO_OPERATION = 4'b0101;
70
        localparam WRITE_DUMMY = 4'b0110;
71
        localparam WRITE_EFFECTIVE = 4'b0110;
72
        localparam CALCULATE_INDEX = 4'b0111;
73
        localparam CHECK_FOR_PAGE_CROSS = 4'b1000;
74
 
75
        // OPCODES TODO: verify how this get synthesised
76
        `include "../T6507LP_Package.v"
77
 
78
        // control signals
79
        localparam MEM_READ = 1'b0;
80
        localparam MEM_WRITE = 1'b1;
81
 
82
        reg [12:0] pc;           // program counter
83
        reg [7:0] sp;            // stack pointer
84
        reg [7:0] ir;            // instruction register
85
        reg [12:0] temp_add;     // temporary address
86
        reg [7:0] temp_data;     // temporary data
87
 
88
        reg [3:0] state, next_state; // current and next state registers
89
        // TODO: not sure if this will be 4 bits wide. as of march 9th this was 4bit wide.
90
 
91
        // wiring that simplifies the FSM logic
92
        reg absolute;
93
        reg absolute_indexed;
94
        reg accumulator;
95
        reg immediate;
96
        reg implied;
97
        reg indirect;
98
        reg relative;
99
        reg zero_page;
100
        reg zero_page_indexed;
101
 
102
        // regs that store the type of operation. again, this simplifies the FSM a lot.
103
        reg read;
104
        reg read_modify_write;
105
        reg write;
106
        reg jump;
107
 
108
        reg enable;
109
 
110
        wire [12:0] next_pc;
111
        assign next_pc = pc + 1'b1;
112
 
113
        always @ (posedge clk_in or negedge n_rst_in) begin
114
                if (n_rst_in == 1'b0) begin
115
                        // TODO: all registers must assume default values
116
 
117
                        pc <= {13{1'b0}}; // TODO: this is written somewhere. something about a reset vector. must be checked.
118
                        sp <= 8'h00; // TODO: the default is not 0. maybe $0100 or something like that. must be checked.
119
                        ir <= 8'h00;
120
                        temp_add <= {13{1'b0}};
121
                        temp_data <= {8{1'b0}};
122
                        state <= FETCH_OP;
123
 
124
                        //address <= {13{1'b0}};
125
                        //control <= 1'b0;
126
                        //data_out <= {8{1'b0}};
127
                        //alu_opcode <= {8{1'b0}};
128
                        //alu_a <= {8{1'b0}};
129
                end
130
                else begin
131
                        state <= next_state;
132
 
133
                        address <= pc; // this secures the pipelining will happen by default
134
 
135
                        case (state)
136
                                FETCH_OP: begin // this state is the simplest one. it is a simple fetch that must be done when the cpu was reset or
137
                                                // the last cycle was a memory write.
138
                                        pc <= next_pc;
139
                                end
140
                                FETCH_LOW: begin // in this state the opcode is already known so truly execution begins
141
                                        pc <= next_pc;
142
                                        ir <= data_in; // opcode must be saved in the instruction register. this is not necessary for the IMP and ACC modes.
143
                                end
144
                                FETCH_HIGH: begin
145
                                        pc <= next_pc;
146
 
147
                                        temp_add <= {5'b00000, data_in}; // data from previous cycle (lowbyte) is ready and must be saved
148
                                end
149
                                SET_PC: begin
150
                                        pc <= {data_in[4:0], temp_add[7:0]};
151
                                end
152
                                READ_EFFECTIVE: begin
153
                                        if (zero_page) begin
154
                                                temp_add <= {5'b00000, data_in}; // this is necessary for the write_effective state
155
                                                address <= {5'b00000, data_in};
156
                                        end
157
                                        else if (zero_page_indexed) begin
158
                                                temp_add <= {5'b00000, alu_result}; // this is necessary for the write_effective state
159
                                                address <= {5'b00000, alu_result};
160
                                        end
161
                                        else begin
162
                                                temp_add[12:8] <= data_in;
163
                                                address <= {data_in[4:0], temp_add[7:0]};
164
                                        end
165
                                end
166
                                DO_OPERATION, CALCULATE_INDEX: begin
167
                                end
168
                                WRITE_DUMMY: begin
169
                                        //if (zero_page) begin // i believe this works fine
170
 
171
                                        address <= temp_add;
172
                                        //control <= WRITE; // just for compatibility
173
                                        //alu_opcode <= ir;
174
                                        //alu_a <= data_in;
175
                                end
176
                                WRITE_EFFECTIVE: begin
177
                                        if (zero_page) begin
178
                                                address <= temp_add;
179
                                        end
180
                                        else if (zero_page_indexed) begin
181
                                                address <= {5'b00000, alu_result};
182
                                        end
183
                                        else begin // maybe this could be rearenged for better synth
184
                                                if (write) begin
185
                                                        address <= {data_in[4:0], temp_add[7:0]};
186
                                                end
187
                                                else begin
188
                                                        address <= temp_add;
189
                                                end
190
                                        end
191
 
192
                                        //data_out <= alu_result;
193
                                        //control <= WRITE;
194
                                end
195
                                CHECK_FOR_PAGE_CROSS: begin
196
                                        temp_add[12:8] <= data_in;
197
                                        address <= {data_in[4:0], temp_add[7:0]};
198
                                end
199
                                default: begin
200
                                        state <= FETCH_OP;              // TODO: this prevents the system from halting but may trigger strange behavior.
201
                                        $finish("UNKNOWN STATE!");      // TODO: check if synth really ignores this line. Otherwise wrap it with a `ifdef 
202
                                end
203
 
204
                        endcase
205
                end
206
        end
207
 
208
        always @(posedge clk_in) begin // combinational block that handles the outputs
209
                enable <= 1'b0;
210
                control <= MEM_READ;
211
                alu_opcode <= 8'h00;
212
                alu_a <= 8'h00;
213
                data_out <= 8'h00;
214
 
215
                case (state)
216
                        FETCH_OP, SET_PC, READ_EFFECTIVE: begin
217
                                //enable = 0;
218
                        end
219
                        FETCH_LOW: begin
220
                                if (accumulator || implied) begin // the ALU must be used
221
                                        enable <= 1'b1;
222
                                        alu_opcode <= data_in;
223
                                end
224
                        end
225
                        FETCH_HIGH: begin
226
                                if (immediate || write || absolute_indexed) begin
227
                                        enable <= 1'b1;
228
                                        alu_opcode <= ir;
229
                                        alu_a <= data_in;
230
                                end
231
                        end
232
                        DO_OPERATION, CALCULATE_INDEX: begin
233
                                enable <= 1'b1;
234
                                alu_opcode <= ir;
235
                                alu_a <= data_in;
236
                        end
237
                        WRITE_DUMMY: begin
238
                                //if (zero_page) begin // i believe this works fine
239
                                control <= MEM_WRITE;   // just for compatibility
240
                                data_out <= data_in;    // just for compatibility
241
                                alu_opcode <= ir;
242
                                alu_a <= data_in;
243
                        end
244
                        WRITE_EFFECTIVE: begin
245
                                control <= MEM_WRITE;
246
                                data_out <= alu_result;
247
                        end
248
                endcase
249
        end
250
 
251
        always @ (*) begin // this is the next_state always
252
 
253
                next_state = FETCH_OP; // this should avoid latch inferring
254
 
255
                begin
256
                        case (state)
257
                                FETCH_OP: begin
258
                                        next_state = FETCH_LOW;
259
                                end
260
                                FETCH_LOW: begin
261
                                        if (accumulator  || implied) begin
262
                                                next_state = FETCH_OP; // not sure
263
                                        end
264
                                        else if (zero_page) begin // zero page behaves exactly as absolute except that it has only the first fetch
265
                                                if (read || read_modify_write) begin
266
                                                        next_state = READ_EFFECTIVE;
267
                                                end
268
                                                else if (write) begin
269
                                                        next_state = WRITE_EFFECTIVE;
270
                                                end
271
                                        end
272
                                        else if (zero_page_indexed) begin
273
                                                next_state = CALCULATE_INDEX;
274
                                        end
275
                                        else begin
276
                                                next_state = FETCH_HIGH;
277
                                        end
278
                                end
279
                                FETCH_HIGH: begin
280
                                        if (immediate) begin
281
                                                next_state = FETCH_LOW;
282
                                        end
283
                                        else if (absolute) begin
284
                                                if (jump) begin
285
                                                        next_state = SET_PC;
286
                                                end
287
                                                else if (read || read_modify_write) begin // TODO: verify if this should stay like this 
288
                                                        // (LDA, LDX, LDY, EOR, AND, ORA, ADC, SBC, CMP, BIT, LAX, NOP) reads
289
                                                        // (ASL, LSR, ROL, ROR, INC, DEC, SLO, SRE, RLA, RRA, ISB, DCP) modifs
290
                                                        // (STA, STX, STY, SAX) writes
291
                                                        next_state = READ_EFFECTIVE;
292
                                                end
293
                                                else if (write) begin
294
                                                        next_state = WRITE_EFFECTIVE;
295
                                                end
296
                                        end
297
                                        else if (absolute_indexed) begin
298
                                                next_state = CHECK_FOR_PAGE_CROSS;
299
                                        end
300
                                end
301
                                SET_PC, DO_OPERATION: begin
302
                                        next_state = FETCH_LOW;
303
                                end
304
                                READ_EFFECTIVE: begin
305
                                        if (read) begin
306
                                                next_state = DO_OPERATION;
307
                                        end
308
                                        else if (read_modify_write) begin
309
                                                next_state = WRITE_DUMMY;
310
                                        end
311
                                end
312
                                WRITE_EFFECTIVE: begin
313
                                        next_state = FETCH_OP;
314
                                end
315
                                CALCULATE_INDEX: begin
316
                                        if (read || read_modify_write) begin
317
                                                next_state = READ_EFFECTIVE;
318
                                        end
319
                                        else if (write) begin
320
                                                next_state = WRITE_EFFECTIVE;
321
                                        end
322
                                end
323
                                CHECK_FOR_PAGE_CROSS: begin
324
                                        if (alu_status[V] == 1'b0) begin // check the overflow bit
325
                                                if (read || read_modify_write) begin
326
                                                        next_state = READ_EFFECTIVE;
327
                                                end
328
                                                else begin
329
                                                        next_state = WRITE_EFFECTIVE;
330
                                                end
331
                                        end
332
                                        else begin // TODO: this is totally uncertain. absolute indexed mode must be reviewed
333
                                                if (read || read_modify_write) begin
334
                                                        next_state = DO_OPERATION;
335
                                                end
336
                                                else begin
337
                                                        next_state = WRITE_EFFECTIVE;
338
                                                end
339
                                        end
340
 
341
                                        end
342
                                //end
343
 
344
                        endcase
345
                end
346
        end
347
 
348
        // this always block is responsible for updating the address mode
349
        always @ (*) begin // TODO: the sensitivity may not be correct 
350
 
351
                absolute = 1'b0;
352
                absolute_indexed = 1'b0;
353
                accumulator = 1'b0;
354
                immediate = 1'b0;
355
                implied = 1'b0;
356
                indirect = 1'b0;
357
                relative = 1'b0;
358
                zero_page = 1'b0;
359
                zero_page_indexed = 1'b0;
360
 
361
                read = 1'b0;
362
                read_modify_write = 1'b0;
363
                write = 1'b0;
364
                jump = 1'b0;
365
 
366
                if (state == FETCH_LOW) begin // TODO: does this works?
367
                        case (data_in)
368
                                BRK_IMP, CLC_IMP, CLD_IMP, CLI_IMP, CLV_IMP, DEX_IMP, DEY_IMP, INX_IMP, INY_IMP, NOP_IMP, PHA_IMP, PHP_IMP, PLA_IMP,
369
                                PLP_IMP, RTI_IMP, RTS_IMP, SEC_IMP, SED_IMP, SEI_IMP, TAX_IMP, TAY_IMP, TSX_IMP, TXA_IMP, TXS_IMP, TYA_IMP: begin
370
                                        implied = 1'b1;
371
                                end
372
                                ASL_ACC, LSR_ACC, ROL_ACC, ROR_ACC: begin
373
                                        accumulator = 1'b1;
374
                                end
375
                                ADC_IMM, AND_IMM, CMP_IMM, CPX_IMM, CPY_IMM, EOR_IMM, LDA_IMM, LDX_IMM, LDY_IMM, ORA_IMM, SBC_IMM: begin
376
                                        immediate = 1'b1;
377
                                end
378
                                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,
379
                                LSR_ZPG, ORA_ZPG, ROL_ZPG, ROR_ZPG, SBC_ZPG, STA_ZPG, STX_ZPG, STY_ZPG: begin
380
                                        zero_page = 1'b1;
381
                                end
382
                                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,
383
                                SBC_ZPX, STA_ZPX, LDX_ZPY, STX_ZPY, STY_ZPX: begin
384
                                        zero_page_indexed = 1'b1;
385
                                end
386
                                BCC_REL, BCS_REL, BEQ_REL, BMI_REL, BNE_REL, BPL_REL, BVC_REL, BVS_REL: begin
387
                                        relative = 1'b1;
388
                                end
389
                                ADC_ABS, AND_ABS, ASL_ABS, BIT_ABS, CMP_ABS, CPX_ABS, CPY_ABS, DEC_ABS, EOR_ABS, INC_ABS, JMP_ABS, JSR_ABS, LDA_ABS,
390
                                LDX_ABS, LDY_ABS, LSR_ABS, ORA_ABS, ROL_ABS, ROR_ABS, SBC_ABS, STA_ABS, STX_ABS, STY_ABS: begin
391
                                        absolute = 1'b1;
392
                                end
393
                                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,
394
                                SBC_ABX, STA_ABX, ADC_ABY, AND_ABY, CMP_ABY, EOR_ABY, LDA_ABY, LDX_ABY, ORA_ABY, SBC_ABY, STA_ABY: begin
395
                                        absolute_indexed = 1'b1;
396
                                end
397
                                ADC_IDX, AND_IDX, CMP_IDX, EOR_IDX, LDA_IDX, ORA_IDX, SBC_IDX, STA_IDX, ADC_IDY, AND_IDY, CMP_IDY, EOR_IDY, LDA_IDY,
398
                                ORA_IDY, SBC_IDY, STA_IDY: begin // all these opcodes are 8'hX1; TODO: optimize this
399
                                        indirect = 1'b1;
400
                                end
401
                        endcase
402
 
403
                        if (data_in == JMP_ABS || data_in == JMP_IND) begin // the opcodes are 8'h4C and 8'h6C
404
                                jump = 1'b1;
405
                        end
406
 
407
                //      if (data_in == )
408
 
409
/*LDA_IMM = 8'hA9,
410
LDA_ZPG = 8'hA5,
411
LDA_ZPX = 8'hB5,
412
LDA_ABS = 8'hAD,
413
LDA_ABX = 8'hBD,
414
LDA_ABY = 8'hB9,
415
LDA_IDX = 8'hA1,
416
LDA_IDY = 8'hB1;
417
LDX_IMM = 8'hA2,
418
LDX_ZPG = 8'hA6,
419
LDX_ZPY = 8'hB6,
420
LDX_ABS = 8'hAE,
421
LDX_ABY = 8'hBE;
422
LDY_IMM = 8'hA0,
423
LDY_ZPG = 8'hA4,
424
LDY_ZPX = 8'hB4,
425
LDY_ABS = 8'hAC,
426
LDY_ABX = 8'hBC;
427
*/
428
 
429
 
430
                end
431
        end
432
endmodule
433
 
434
 
435
 

powered by: WebSVN 2.1.0

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