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

Subversion Repositories t6507lp

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

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 86 creep
module t6507lp_fsm(clk, reset_n, alu_result, alu_status, data_in, address, control, data_out, alu_opcode, alu_a, alu_enable, alu_x, alu_y);
52 82 creep
        parameter DATA_SIZE = 4'h8;
53
        parameter ADDR_SIZE = 4'hd;
54 68 creep
 
55 83 creep
        localparam DATA_SIZE_ = DATA_SIZE - 4'b0001;
56
        localparam ADDR_SIZE_ = ADDR_SIZE - 4'b0001;
57 82 creep
 
58 71 creep
        input clk;
59
        input reset_n;
60 82 creep
        input [DATA_SIZE_:0] alu_result;
61
        input [DATA_SIZE_:0] alu_status;
62
        input [DATA_SIZE_:0] data_in;
63
        output reg [ADDR_SIZE_:0] address;
64 61 creep
        output reg control; // one bit is enough? read = 0, write = 1
65 82 creep
        output reg [DATA_SIZE_:0] data_out;
66
        output reg [DATA_SIZE_:0] alu_opcode;
67
        output reg [DATA_SIZE_:0] alu_a;
68 68 creep
        output reg alu_enable;
69 61 creep
 
70 86 creep
        input [DATA_SIZE_:0] alu_x;
71
        input [DATA_SIZE_:0] alu_y;
72 68 creep
 
73 86 creep
 
74 61 creep
        // FSM states
75 68 creep
        localparam RESET = 4'b1111;
76 63 creep
        localparam FETCH_OP = 4'b0000;
77 68 creep
        localparam FETCH_OP_CALC = 4'b0001;
78
        localparam FETCH_LOW = 4'b0010;
79
        localparam FETCH_HIGH = 4'b0011;
80 71 creep
        localparam READ_MEM = 4'b0100;
81
        localparam DUMMY_WRT_CALC = 4'b0101;
82
        localparam WRITE_MEM = 4'b0110;
83
        localparam FETCH_OP_CALC_PARAM = 4'b0111;
84 86 creep
        localparam READ_MEM_CALC_INDEX = 4'b1000;
85 61 creep
 
86
        // OPCODES TODO: verify how this get synthesised
87
        `include "../T6507LP_Package.v"
88
 
89
        // control signals
90
        localparam MEM_READ = 1'b0;
91
        localparam MEM_WRITE = 1'b1;
92
 
93 82 creep
        reg [ADDR_SIZE_:0] pc;           // program counter
94
        reg [DATA_SIZE_:0] sp;           // stack pointer
95
        reg [DATA_SIZE_:0] ir;           // instruction register
96
        reg [ADDR_SIZE_:0] temp_addr;    // temporary address
97
        reg [DATA_SIZE_:0] temp_data;    // temporary data
98 61 creep
 
99
        reg [3:0] state, next_state; // current and next state registers
100
        // TODO: not sure if this will be 4 bits wide. as of march 9th this was 4bit wide.
101
 
102
        // wiring that simplifies the FSM logic
103
        reg absolute;
104
        reg absolute_indexed;
105
        reg accumulator;
106
        reg immediate;
107
        reg implied;
108
        reg indirect;
109
        reg relative;
110
        reg zero_page;
111
        reg zero_page_indexed;
112 86 creep
        reg [DATA_SIZE_:0] index; // will be assigned with either X or Y
113 61 creep
 
114
        // regs that store the type of operation. again, this simplifies the FSM a lot.
115
        reg read;
116
        reg read_modify_write;
117
        reg write;
118
        reg jump;
119
 
120 82 creep
        wire [ADDR_SIZE_:0] next_pc;
121 63 creep
        assign next_pc = pc + 13'b0000000000001;
122 61 creep
 
123 86 creep
        wire [ADDR_SIZE_:0] address_plus_index; // this would update more times than actually needed, consuming power.
124
                                                // so the assign was changed to conditional.
125
        assign address_plus_index = (zero_page_indexed == 1'b1 && state == READ_MEM_CALC_INDEX)? (temp_addr + index): 0;
126
 
127 71 creep
        always @ (posedge clk or negedge reset_n) begin // sequencial always block
128
                if (reset_n == 1'b0) begin
129
                        // all registers must assume default values
130 68 creep
                        pc <= 0; // TODO: this is written somewhere. something about a reset vector. must be checked.
131
                        sp <= 0; // TODO: the default is not 0. maybe $0100 or something like that. must be checked.
132 82 creep
                        ir <= 8'h00;
133 71 creep
                        temp_addr <= 0;
134 82 creep
                        temp_data <= 8'h00;
135 68 creep
                        state <= RESET;
136 71 creep
                        // registered outputs also receive default values
137
                        address <= 0;
138 82 creep
                        control <= MEM_READ;
139
                        data_out <= 8'h00;
140 61 creep
                end
141
                else begin
142
                        state <= next_state;
143 83 creep
 
144 61 creep
                        case (state)
145 68 creep
                                RESET: begin
146 82 creep
                                        // The processor was reset
147
                                        $write("under reset");
148 68 creep
                                end
149 61 creep
                                FETCH_OP: begin // this state is the simplest one. it is a simple fetch that must be done when the cpu was reset or
150
                                                // the last cycle was a memory write.
151
                                        pc <= next_pc;
152 71 creep
                                        address <= next_pc;
153 83 creep
                                        control <= MEM_READ;
154 70 creep
                                        ir <= data_in;
155 61 creep
                                end
156 71 creep
                                FETCH_OP_CALC, FETCH_OP_CALC_PARAM: begin // this is the pipeline happening!
157 61 creep
                                        pc <= next_pc;
158 71 creep
                                        address <= next_pc;
159 83 creep
                                        control <= MEM_READ;
160 70 creep
                                        ir <= data_in;
161 61 creep
                                end
162 68 creep
                                FETCH_LOW: begin // in this state the opcode is already known so truly execution begins
163
                                        if (accumulator || implied) begin
164 70 creep
                                                pc <= pc; // is this better?
165 71 creep
                                                address <= pc;
166 83 creep
                                                control <= MEM_READ;
167 61 creep
                                        end
168 70 creep
                                        else if (immediate) begin
169 68 creep
                                                pc <= next_pc;
170 71 creep
                                                address <= next_pc;
171 83 creep
                                                control <= MEM_READ;
172 70 creep
                                                temp_data <= data_in; // the follow-up byte is saved in temp_data 
173 61 creep
                                        end
174 71 creep
                                        else if (absolute) begin
175
                                                pc <= next_pc;
176
                                                address <= next_pc;
177 83 creep
                                                control <= MEM_READ;
178 71 creep
                                                temp_addr[7:0] <= data_in;
179
                                        end
180 77 creep
                                        else if (zero_page) begin
181
                                                pc <= next_pc;
182
                                                address <= {{5{1'b0}},data_in};
183 78 creep
                                                temp_addr <= {{5{1'b0}},data_in};
184
 
185 77 creep
                                                if (write) begin
186
                                                        control <= MEM_WRITE;
187 78 creep
                                                        data_out <= alu_result;
188 77 creep
                                                end
189 83 creep
                                                else begin
190
                                                        control <= MEM_READ;
191
                                                        data_out <= 8'h00;
192
                                                end
193 77 creep
                                        end
194 86 creep
                                        else if (zero_page_indexed) begin
195
                                                pc <= next_pc;
196
                                                address <= {{5{1'b0}},data_in};
197
                                                temp_addr <= {{5{1'b0}},data_in};
198
                                                control <= MEM_READ;
199
                                        end
200 61 creep
                                end
201 71 creep
                                FETCH_HIGH: begin
202
                                        if (jump) begin
203 83 creep
                                                pc <= {data_in[4:0], temp_addr[7:0]}; // PCL <= first byte, PCH <= second byte
204
                                                address <= {data_in[4:0], temp_addr[7:0]};
205
                                                control <= MEM_READ;
206
                                                data_out <= 8'h00;
207 71 creep
                                        end
208
                                        else begin
209
                                                if (write) begin
210
                                                        pc <= next_pc;
211
                                                        temp_addr[12:8] <= data_in[4:0];
212
                                                        address <= {data_in[4:0],temp_addr[7:0]};
213
                                                        control <= MEM_WRITE;
214 77 creep
                                                        data_out <= alu_result;
215 71 creep
                                                end
216
                                                else begin // read_modify_write or just read
217
                                                        pc <= next_pc;
218
                                                        temp_addr[12:8] <= data_in[4:0];
219
                                                        address <= {data_in[4:0],temp_addr[7:0]};
220 83 creep
                                                        control <= MEM_READ;
221
                                                        data_out <= 8'h00;
222 71 creep
                                                end
223
                                        end
224
                                        //else begin
225
                                        //      $write("FETCHHIGH PROBLEM"); 
226
                                        //      $finish(0); 
227
                                        //end
228 61 creep
                                end
229 71 creep
                                READ_MEM: begin
230
                                        if (read_modify_write) begin
231
                                                pc <= pc;
232
                                                address <= temp_addr;
233
                                                control <= MEM_WRITE;
234
                                                temp_data <= data_in;
235
                                                data_out <= data_in; // writeback the same value
236
                                        end
237
                                        else begin
238
                                                pc <= pc;
239
                                                address <= pc;
240
                                                temp_data <= data_in;
241 83 creep
                                                control <= MEM_READ;
242
                                                data_out <= 8'h00;
243 71 creep
                                        end
244 70 creep
                                end
245 86 creep
                                READ_MEM_CALC_INDEX: begin
246
                                                //pc <= next_pc; // pc was  already updated in the previous cycle
247
                                                address <= address_plus_index;
248
                                                temp_addr <= address_plus_index;
249
 
250
                                                if (write) begin
251
                                                        control <= MEM_WRITE;
252
                                                        data_out <= alu_result;
253
                                                end
254
                                                else begin
255
                                                        control <= MEM_READ;
256
                                                        data_out <= 8'h00;
257
                                                end
258
 
259
                                end
260 71 creep
                                DUMMY_WRT_CALC: begin
261
                                        pc <= pc;
262
                                        address <= temp_addr;
263
                                        control <= MEM_WRITE;
264
                                        data_out <= alu_result;
265 70 creep
                                end
266 71 creep
                                WRITE_MEM: begin
267
                                        pc <= pc;
268
                                        address <= pc;
269 83 creep
                                        control <= MEM_READ;
270
                                        data_out <= 8'h00;
271 70 creep
                                end
272
                                default: begin
273
                                        $write("unknown state");        // TODO: check if synth really ignores this 2 lines. Otherwise wrap it with a `ifdef 
274
                                        $finish(0);
275
                                end
276
 
277
                        endcase
278
                end
279
        end
280
 
281 71 creep
        always @ (*) begin // this is the next_state logic and the output logic always block
282
                alu_opcode = 8'h00;
283
                alu_a = 8'h00;
284
                alu_enable = 1'b0;
285 70 creep
 
286 71 creep
                next_state = RESET; // this prevents the latch
287 68 creep
 
288 71 creep
                case (state)
289
                        RESET: begin
290
                                next_state = FETCH_OP;
291
                        end
292
                        FETCH_OP: begin
293
                                next_state = FETCH_LOW;
294
                        end
295 82 creep
                        //FETCH_OP_CALC: begin // so far no addressing mode required the use of this state
296
                        //      next_state = FETCH_LOW;
297
                        //      alu_opcode = ir;
298
                        //      alu_enable = 1'b1;
299
                        //end
300 71 creep
                        FETCH_OP_CALC_PARAM: begin
301
                                next_state = FETCH_LOW;
302
                                alu_opcode = ir;
303
                                alu_enable = 1'b1;
304
                                alu_a = temp_data;
305
                        end
306
                        FETCH_LOW: begin
307
                                if (accumulator  || implied) begin
308
                                        alu_opcode = ir;
309
                                        alu_enable = 1'b1;
310
                                        next_state = FETCH_OP;
311
                                end
312
                                else if (immediate) begin
313
                                        next_state = FETCH_OP_CALC_PARAM;
314
                                end
315 77 creep
                                else if (zero_page) begin
316
                                        if (read || read_modify_write) begin
317
                                                next_state = READ_MEM;
318
                                        end
319
                                        else if (write) begin
320
                                                next_state = WRITE_MEM;
321 86 creep
                                                alu_opcode = ir;
322
                                                alu_enable = 1'b1;
323
                                                alu_a = 8'h00;
324 77 creep
                                        end
325
                                        else begin
326
                                                $write("unknown behavior");
327
                                                $finish(0);
328
                                        end
329
                                end
330 86 creep
                                else if (zero_page_indexed) begin
331
                                        next_state = READ_MEM_CALC_INDEX;
332
                                end
333 71 creep
                                else begin // at least the absolute address mode falls here
334
                                        next_state = FETCH_HIGH;
335 86 creep
                                        if (write) begin // this is being done one cycle early?
336
                                                alu_opcode = ir;
337
                                                alu_enable = 1'b1;
338
                                                alu_a = 8'h00;
339
                                        end
340 71 creep
                                end
341
                        end
342
                        FETCH_HIGH: begin
343
                                if (jump) begin
344 68 creep
                                        next_state = FETCH_OP;
345 61 creep
                                end
346 71 creep
                                else if (read || read_modify_write) begin
347
                                        next_state = READ_MEM;
348 61 creep
                                end
349 71 creep
                                else if (write) begin
350
                                        next_state = WRITE_MEM;
351 68 creep
                                end
352 71 creep
                                else begin
353
                                        $write("unknown behavior");
354
                                        $finish(0);
355 61 creep
                                end
356 71 creep
                        end
357 86 creep
                        READ_MEM_CALC_INDEX: begin
358
                                if (read || read_modify_write) begin
359
                                        next_state = READ_MEM;
360
                                end
361
                                else if (write) begin
362
                                        alu_opcode = ir;
363
                                        alu_enable = 1'b1;
364
                                        next_state = WRITE_MEM;
365
                                end
366
                                else begin
367
                                        $write("unknown behavior");
368
                                        $finish(0);
369
                                end
370
                        end
371 71 creep
                        READ_MEM: begin
372
                                if (read) begin
373
                                        next_state = FETCH_OP_CALC_PARAM;
374 61 creep
                                end
375 71 creep
                                else if (read_modify_write) begin
376
                                        next_state = DUMMY_WRT_CALC;
377
                                end
378
                        end
379
                        DUMMY_WRT_CALC: begin
380
                                alu_opcode = ir;
381
                                alu_enable = 1'b1;
382
                                alu_a = data_in;
383
                                next_state = WRITE_MEM;
384
                        end
385
                        WRITE_MEM: begin
386
                                next_state = FETCH_OP;
387
                        end
388
                        default: begin
389
                                next_state = RESET;
390
                        end
391
                endcase
392 61 creep
        end
393
 
394 77 creep
        // this always block is responsible for updating the address mode and the type of operation being done
395 68 creep
        always @ (*) begin // 
396 61 creep
                absolute = 1'b0;
397
                absolute_indexed = 1'b0;
398
                accumulator = 1'b0;
399
                immediate = 1'b0;
400
                implied = 1'b0;
401
                indirect = 1'b0;
402
                relative = 1'b0;
403
                zero_page = 1'b0;
404
                zero_page_indexed = 1'b0;
405 86 creep
 
406
                index = 1'b0;
407 61 creep
 
408
                read = 1'b0;
409
                read_modify_write = 1'b0;
410
                write = 1'b0;
411
                jump = 1'b0;
412
 
413 70 creep
                case (ir)
414
                        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,
415
                        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
416
                                implied = 1'b1;
417
                        end
418
                        ASL_ACC, LSR_ACC, ROL_ACC, ROR_ACC: begin
419
                                accumulator = 1'b1;
420
                        end
421
                        ADC_IMM, AND_IMM, CMP_IMM, CPX_IMM, CPY_IMM, EOR_IMM, LDA_IMM, LDX_IMM, LDY_IMM, ORA_IMM, SBC_IMM: begin
422
                                immediate = 1'b1;
423
                        end
424
                        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,
425
                        LSR_ZPG, ORA_ZPG, ROL_ZPG, ROR_ZPG, SBC_ZPG, STA_ZPG, STX_ZPG, STY_ZPG: begin
426
                                zero_page = 1'b1;
427
                        end
428
                        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,
429 86 creep
                        SBC_ZPX, STA_ZPX, STY_ZPX: begin
430 70 creep
                                zero_page_indexed = 1'b1;
431 86 creep
                                index = alu_x;
432 70 creep
                        end
433 86 creep
                        LDX_ZPY, STX_ZPY: begin
434
                                zero_page_indexed = 1'b1;
435
                                index = alu_y;
436
                        end
437 70 creep
                        BCC_REL, BCS_REL, BEQ_REL, BMI_REL, BNE_REL, BPL_REL, BVC_REL, BVS_REL: begin
438
                                relative = 1'b1;
439
                        end
440
                        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,
441
                        LDX_ABS, LDY_ABS, LSR_ABS, ORA_ABS, ROL_ABS, ROR_ABS, SBC_ABS, STA_ABS, STX_ABS, STY_ABS: begin
442
                                absolute = 1'b1;
443
                        end
444
                        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,
445
                        SBC_ABX, STA_ABX, ADC_ABY, AND_ABY, CMP_ABY, EOR_ABY, LDA_ABY, LDX_ABY, ORA_ABY, SBC_ABY, STA_ABY: begin
446
                                absolute_indexed = 1'b1;
447
                        end
448
                        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,
449
                        ORA_IDY, SBC_IDY, STA_IDY: begin // all these opcodes are 8'hX1; TODO: optimize this
450
                                indirect = 1'b1;
451
                        end
452 71 creep
                        default: begin
453 86 creep
                                if (reset_n == 1) begin // the processor is NOT being reset
454
                                        $write("\nunknown OPCODE!!!!! 0x%h\n", ir);
455
                                        $finish();
456
                                end
457 71 creep
                        end
458 70 creep
                endcase
459 71 creep
 
460
                case (ir)
461
                        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,
462
                        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,
463
                        DEC_ABX: begin
464
                                read_modify_write = 1'b1;
465
                        end
466
                        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
467
                                write = 1'b1;
468
                        end
469
                        default: begin // this should work fine since the previous case statement will detect the unknown/undocumented/unsupported opcodes
470
                                read = 1'b1;
471
                        end
472
                endcase
473 61 creep
 
474 71 creep
                if (ir == JMP_ABS || ir == JMP_IND) begin // the opcodes are 8'h4C and 8'h6C
475 70 creep
                        jump = 1'b1;
476
                end
477 86 creep
        end
478 61 creep
endmodule
479
 
480
 
481
 

powered by: WebSVN 2.1.0

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