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

Subversion Repositories t6507lp

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

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

powered by: WebSVN 2.1.0

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