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

Subversion Repositories t6507lp

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

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

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

powered by: WebSVN 2.1.0

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