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

Subversion Repositories m65c02

[/] [m65c02/] [trunk/] [Src/] [RTL/] [M65C02_Base.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 MichaelA
///////////////////////////////////////////////////////////////////////////////
2
//
3
//  Copyright 2012-2013 by Michael A. Morris, dba M. A. Morris & Associates
4
//
5
//  All rights reserved. The source code contained herein is publicly released
6
//  under the terms and conditions of the GNU Lesser Public License. No part of
7
//  this source code may be reproduced or transmitted in any form or by any
8
//  means, electronic or mechanical, including photocopying, recording, or any
9
//  information storage and retrieval system in violation of the license under
10
//  which the source code is released.
11
//
12
//  The source code contained herein is free; it may be redistributed and/or 
13
//  modified in accordance with the terms of the GNU Lesser General Public
14
//  License as published by the Free Software Foundation; either version 2.1 of
15
//  the GNU Lesser General Public License, or any later version.
16
//
17
//  The source code contained herein is freely released WITHOUT ANY WARRANTY;
18
//  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
19
//  PARTICULAR PURPOSE. (Refer to the GNU Lesser General Public License for
20
//  more details.)
21
//
22
//  A copy of the GNU Lesser General Public License should have been received
23
//  along with the source code contained herein; if not, a copy can be obtained
24
//  by writing to:
25
//
26
//  Free Software Foundation, Inc.
27
//  51 Franklin Street, Fifth Floor
28
//  Boston, MA  02110-1301 USA
29
//
30
//  Further, no use of this source code is permitted in any form or means
31
//  without inclusion of this banner prominently in any derived works. 
32
//
33
//  Michael A. Morris
34
//  Huntsville, AL
35
//
36
///////////////////////////////////////////////////////////////////////////////
37
 
38
`timescale 1ns / 1ps
39
 
40
///////////////////////////////////////////////////////////////////////////////
41
// Company:         M. A. Morris & Associates 
42
// Engineer:        Michael A. Morris 
43
// 
44
// Create Date:     06:49:56 02/03/2012 
45
// Design Name:     WDC W65C02 Microprocessor Re-Implementation
46
// Module Name:     M65C02_Core
47
// Project Name:    C:\XProjects\ISE10.1i\M65C02 
48
// Target Devices:  Generic SRAM-based FPGA 
49
// Tool versions:   Xilinx ISE10.1i SP3
50
//
51
// Description: 
52
//
53
// Dependencies:    M65C02_MPC.v
54
//                      M65C02_uPgm_V3.coe (M65C02_uPgm_V3.txt)
55
//                      M65C02_Decoder_ROM.coe (M65C02_Decoder_ROM.txt)
56
//                  M65C02_ALU.v
57
//                      M65C02_Bin.v
58
//                      M65C02_BCD.v 
59
//
60
// Revision: 
61
//
62
//  0.00    12B03   MAM     Initial File Creation
63
//
64
//  0.10    12B04   MAM     Synthesized. All synthesis errors removed. All un-
65
//                          used signals, except those related to the uPgm and
66
//                          Instruction Decode ROMs, removed. Next Address and
67
//                          Program Counter functions optimized.
68
//
69
//  1.00    12B05   MAM     Completed changes to the control structure to in-
70
//                          clude an instruction in the IDEC ROM. Changed basic
71
//                          operation to deal with a RAM, using LUT RAM, having
72
//                          single cycle read/write operations.
73
//
74
//  1.10    12B18   MAM     Added ISR input to ALU and connected to unused bits
75
//                          in the MPC microword. Used to clear D and set I in
76
//                          the PSW after it is pushed onto the stack when an
77
//                          NMI or unmasked IRQ interrupts are being processed.
78
//
79
//  1.11    12B19   MAM     Renamed all source files in a consistent manner.
80
//                          Corrected the equation for interrupt mask output.
81
//                          All modules and parameter files renamed M65C02_xxx.
82
//                          Module renamed: MAM6502_Core => M65C02_Core.
83
//
84
//  1.20    12B19   MAM     Decoded BRV2 MPC instuction. BRV2 added as a load
85
//                          signal to {OP2, OP1} to capture Vector[15:0] during
86
//                          NMI/IRQ interrupt and BRK trap handling.
87
//
88
//  1.30    12B19   MAM     Significantly changed the PSW implementation. Chan-
89
//                          ges implemented to allow the implementation of a
90
//                          better register write mechanism. Microword organi-
91
//                          zation changed to delete separate fields for DI and
92
//                          DO. Fields reorganized and the two bits from DO_Op
93
//                          combined with a third bit to form a 3-bit Reg_WE
94
//                          field. A single bit ISR field was retained. The 
95
//                          field width remains 32, but explicit control of the
96
//                          register write enable allows solution to be imple-
97
//                          mented for separately controlling updates to P and
98
//                          capturing the return address in the same temporary
99
//                          working register, OP1. BRK and RTI now operate as
100
//                          expected, and the common register numbering between
101
//                          the various register control field in the microcode
102
//                          and the fixed control word, allow a ROM-like struc-
103
//                          ture to be used for explicitly controlling writes 
104
//                          to the various registers (especially P). The new
105
//                          scheme improves the decode speed, and the new form
106
//                          of the P (PSW) provides a cleaner structure for
107
//                          future updates/changes. Also requires WSel field
108
//                          in the fixed control word to be updated so that all
109
//                          instructions, which modify memory (and not A, X, or
110
//                          Y) and require a change in a PSW bit, include P as
111
//                          as a write destination. Writes to A, X, or Y are
112
//                          also set to automatically generate a write enable 
113
//                          for P. (See M65C02_ALU for explicit changes to de-
114
//                          code logic for register write enables and PSW chan-
115
//                          ges.)
116
//
117
//                          Also changed the PC multiplexer and next PC adder
118
//                          logic so that a case statement is used to better
119
//                          define the next PC. This changed was required by a
120
//                          problem detected during the BRK instruction testing
121
//                          which indicated that the pipeline delay in the jmp
122
//                          address path was causing the next PC computation to
123
//                          operate on an invalid PCH value. Thus, the PCH of
124
//                          the RTI return address was wrong because it was 
125
//                          delayed one cycle. These two changes result in the
126
//                          100 MHz target clock speed being maitained.
127
//
128
//                          Synthesis indicated that SC (Single Cycle) and Done
129
//                          were being trimmed. Thus added Done and SC to the
130
//                          module port list to avoid the reported trimming of
131
//                          these two signals from the module after the modifi-
132
//                          cations to P and register write enable logic were
133
//                          completed.
134
//
135
//  1.31    12B22   MAM     Modified BA multiplexer to support unconditional
136
//                          instruction decode using BRV1, or conditional
137
//                          decode using BRV3. BRV3 is used by the microprogram
138
//                          to decode the next instruction after a single cycle
139
//                          instruction, or to branch to the interrupt handler.
140
//                          Modified the test inputs to connect Valid to T1,
141
//                          and PSW Decimal mode flag, P.3, to T0. Expect to
142
//                          use this test input, T0, for ADC/SBC instructions
143
//                          to use different microroutines (for all addressing
144
//                          modes) ((problem may arise for ADC/SBC #imm)).
145
//
146
//  1.32    12B23   MAM     Backed out changed to T[3:0] implemented in 1.31.
147
//                          A different method will be used.
148
//
149
//  1.40    12B24   MAM     Solved issue regarding cycle stretch required to
150
//                          perform BCD arithmetic (ADC and SBC only) during an
151
//                          instruction fetch. Normally, all ALU operations 
152
//                          complete during the instruction fetch cycle, thus
153
//                          the registers and PSW are appropriately updated so
154
//                          that a branch instruction can immediately perform a
155
//                          condition code test. The solution is to provide a
156
//                          separate ready signal to the ALU, which then uses
157
//                          the ready signal to gate the register write enables
158
//                          separately from the ALU function enable which acti-
159
//                          vates the various functional units in the ALU. At
160
//                          the core level, the external ready is gated by Wait
161
//                          and an internal ready signal is generated that will
162
//                          stretch the ALU execution cycle only when a BCD add
163
//                          or subtract is performed. Since the only BCD opera-
164
//                          tions to be concerned about are the ADC/SBC opera-
165
//                          tions, only the Accumulator and the PSW are affect-
166
//                          ed. This means that only the RO_?? addressing modes
167
//                          microroutines are involved in these operations. All
168
//                          of the other addressing modes, WO_?? and RMW_??, do
169
//                          not have any BCD mode instructions with which to be
170
//                          concerned.
171
//
172
//                          To implement the solution, a RDY port was added to
173
//                          ALU, all of the core level registers (PC, MAR, OP1,
174
//                          and OP2) write enable instructions were modified to
175
//                          use only Rdy instead of the previous multiplexed 
176
//                          signal. That multiplexer was moved to the begining
177
//                          of the module, and then combined with a ROM-based
178
//                          decoder to form the core-level Rdy signal that is
179
//                          distributed to all registers and modules. The ex-
180
//                          ternal Rdy port on the core was renamed to Ack_In
181
//                          in order to maintain Rdy as the signal name within
182
//                          the core.
183
//
184
//  1.41    12B24   MAM     Simple cleanup of comments and conversion of con-
185
//                          stants used for DO multiplexer control into the
186
//                          local parameters specifically defined for the pur-
187
//                          pose of decoding that microprogram control field.
188
//
189
//  1.50    12B25   MAM     Completed support for interrupt handling. Added a
190
//                          register to capture the last value of the PC of an
191
//                          instruction being interrupted. The automatic adjust
192
//                          provided by RTS/RTI of the return address means
193
//                          the PC pushed on the stack is not the address of
194
//                          the next instruction, but the last byte of the in-
195
//                          struction being completed before vectoring to the
196
//                          interrupt service routine. Added a FF to that is
197
//                          set when an interrupt has been accepted and clear-
198
//                          ed as the first instruction of the interrupt ser-
199
//                          vice routine is fetched. It is used to multiplex
200
//                          {PCH, PCL} or {dPCH, dPCL} onto the output bus. The
201
//                          delayed PC values are pushed onto the stack for in-
202
//                          terrupts, the the normal PC is pushed onto the
203
//                          stack for subroutine calls. Thus, the output data
204
//                          multiplexer was modified to include an additional
205
//                          multiplexer for the delayed or the non-delayed PC.
206
//
207
//                          Also modified the write enables for the IR, OP1,
208
//                          and OP2 registers. As an interrupt is being taken,
209
//                          the instruction being fetched should not loaded 
210
//                          into the IR. As a consequence, BRV1 and BRV3 are 
211
//                          used to update the IR, but only if Int is not
212
//                          asserted during a BRV3 MPC operation.
213
//
214
//  1.60    12C04   MAM     Made change to the internal Rdy signal equations.
215
//                          Added |Reg_WE term to the |Op term. This corrects
216
//                          an issue with RMW instructions where the cycle is
217
//                          complete and ALU Valid deasserts during the fetch
218
//                          of the next instruction. Rdy deasserts as a result
219
//                          and the microprogram stops. Not an issue for all
220
//                          other instructions since the fetch and execute
221
//                          cycles are overlapped. With RMW instructions this
222
//                          is not the case because Reg_WE is asserted one cy-
223
//                          cle before the fetch of the next instruction.
224
//
225
//  1.61    12C06   MAM     Added internal ready, Rdy, to the port list for
226
//                          easier access to the signal by the testbench.
227
//
228
//  2.0     12C30   MAM     Replaced the address generator functions, including
229
//                          the MAR and PC registers and associated logic with
230
//                          a single module that captures all of the address
231
//                          generation. This is done in preparation of changing
232
//                          the address generation to support synchronous Block
233
//                          RAM for use with the M65C02_Core instead of asyn-
234
//                          chronous LUT-based RAM presently used.
235
//
236
//  2.10    12D29   MAM     Per Windfall@forum.6502.org, the DP,X and DP,Y
237
//                          address modes did not wrap at the zero page bounda-
238
//                          ry. Adjusted the AO equation to wrap the address as
239
//                          required.
240
//              
241
//  2.20    12K03   MAM     Cut out the address generator section and created a
242
//                          module, M65C02_AddrGen.
243
//
244
//  2.30    12K03   MAM     Integrated version 3 of the MPC which includes a
245
//                          built-in microcycle length controller.
246
//
247
//  2.40    12K13   MAM     Added DP and rDP signals, and changed the ZP control
248
//                          signal to assert for any of the zero page addressing
249
//                          modes. The rDP signal is used to enable zero page
250
//                          address wrapping when the MAR is used to fetch the
251
//                          second operand after an initial zero page access.
252
//
253
//  3.00    12K20   MAM     Added an enable to the microprogram ROM which keeps
254
//                          the ROM contents constant during multi-cycle micro-
255
//                          cycles. The microprogram ROM enable also includes
256
//                          Rst in order to deal with the initial microprogram
257
//                          word fetch that occurs during reset for pipelined
258
//                          operation of the MPC. Also added a clock enable for
259
//                          rDP so that it remains constant during a multi-cycle
260
//                          microcycle to ensure that all zero page addressing
261
//                          modulo 256 operations are performed correctly. (See
262
//                          comment 1.60 in M65C02_ALU for additional clarifi-
263
//                          cation of the timing implications.)
264
//
265
//  3.10    12L09   MAM     Added capability to support WAI instruction. Needed
266
//                          signal, xIRQ, that indicates an active low external
267
//                          interrupt request is asserted but the interrupt mask
268
//                          is set so the processor will not take the interrupt.
269
//                          Under these conditions, the WAI continues with the
270
//                          next sequential instruction. In addition to adding
271
//                          xIRQ to the input ports of the core, the multi-way
272
//                          branch multiplexer required a change to support a 
273
//                          4-way branch table when WAI is executing, and a
274
//                          2-way for all other instructions. To support the
275
//                          detection of the WAI instruction, changed the Mode
276
//                          vector to identify the WAI and STP instructions. 
277
//
278
//  3.20    12L13   MAM     Renamed, previously unused and reserved fixed micro-
279
//                          word Opcode field to Msk, and ported into the ALU.
280
//                          The new field provides the bit mask needed for the
281
//                          implementation of the Rockwell instructions.
282
//
283
//  3.21    13B16   MAM     Added ISR to module port to easily allow vector pull
284
//                          signal to be generated.
285
//
286
// Additional Comments:
287
//
288
//  This module is derived from the first implementation which assummed it was
289
//  the top level implementation, i.e. its ports would be connected to IO pins.
290
//  The pipelining of the control signals, instruction and operand addresses,
291
//  and the data proved a bit cumbersome to deal with. The intention was to al-
292
//  ways have that first implementation function as a core around which other
293
//  components and capabilities could be added. With the incorporation of the
294
//  memory interface directly in the core, interactions between the memory in-
295
//  terface and the core logic hindered the development of the microprogram.
296
//
297
//  Thus, the decision was made to sever the core functions from that of the
298
//  memory interface. A single signal, Ack, would force the core logic to wait
299
//  in the event that the required read data was unavailable or the write
300
//  buffers were full. This design decision allows the memory interface and its
301
//  interaction with the core logic to be separated at a clean boundary. The
302
//  result is that timing on the core's external address and data busses can be
303
//  treated as single cycle operations. That is, memory read and memory write
304
//  transactions are completed in the same cycle, i.e no (pipeline) delays.
305
//
306
//  This simplified core architecture must be coupled to an external memory
307
//  controller at the next higher level that implements the required memory
308
//  transactions and provides the Ack signal to control the execution of the 
309
//  core logic state machine. With the core's memory interface, it would be
310
//  easy to add a simple cache memory module to provide data at a rate high to
311
//  the core to achieve as high a clocks per instruction (CPI) metric as possi-
312
//  ble for the complex addressing of the 6502 core.
313
//
314
//  Furthermore, the core must be coupled to logic to handle the edge-sensitive
315
//  NMI, and level sensitive IRQ interrupts. The core, as currently iplemented,
316
//  accepts a vector from this external module for Rst, NMI, IRQ, and/or BRK.
317
//  (In some implementations of the 6502, notably the WDC W65C802, the IRQ vec-
318
//  tor is not shared with the BRK interrupt. In that implementation, a sepa-
319
//  rate BRK vector is allowed. This core indicates to external logic that a
320
//  BRK instruction is being processed, so it is possible for the BRK vector to
321
//  be separated from the IRQ vector. In addition, the vector supplied is not
322
//  the vector address through which the W65C02 perform an indirect jump. In-
323
//  stead, the vector supplied is the content of the indirect jump address.)
324
//
325
///////////////////////////////////////////////////////////////////////////////
326
 
327
module M65C02_Base #(
328
    parameter pStkPtr_Rst  = 8'hFF, // Stk Ptr Value after Reset
329
    parameter pInt_Hndlr   = 0,     // _Int microroutine address, Reset default
330
    parameter pM65C02_uPgm = "M65C02_uPgm_V3.coe",
331
    parameter pM65C02_IDec = "M65C02_Decoder_ROM.coe"
332
)(
333
    input   Rst,            // System Reset Input
334
    input   Clk,            // System Clock Input
335
 
336
    output  IRQ_Msk,        // Interrupt mask from P to Interrupt Handler
337
    input   xIRQ,           // External Maskable Interrupt Request Input
338
    input   Int,            // Interrupt input from Interrupt Handler
339
    input   [15:0] Vector,  // ISR Vector from Interrupt Handler
340
 
341
    output  Done,           // Instruction Complete/Fetch Strobe
342
    output  SC,             // Single Cycle Instruction
343
    output  [2:0] Mode,     // Mode - Instruction Type/Mode
344
    output  RMW,            // Read-Modify-Write Operation
345
    output  reg IntSvc,     // Interrupt Service Start Indicator
346
    output  ISR,            // Interrupt Vector Pull Start Indicator
347
 
348
    output  reg Rdy,        // Internal Ready
349
 
350
    output  [1:0] IO_Op,    // Instruction Fetch Strobe
351
    input   Ack_In,         // Transfer Acknowledge
352
    output  [15:0] AO,      // External Address
353
    input   [ 7:0] DI,      // External Data In
354
    output  reg [7:0] DO,   // External Data Out
355
 
356
    output  [ 7:0] A,       // Accumulator
357
    output  [ 7:0] X,       // Index Register X
358
    output  [ 7:0] Y,       // Index Register Y
359
    output  [ 7:0] S,       // Stack Pointer
360
    output  [ 7:0] P,       // Processor Status Word
361
    output  [15:0] PC,      // Program Counter
362
 
363
    output  reg [ 7:0] IR,  // Instruction Register
364
    output  reg [ 7:0] OP1, // Operand Register 1
365
    output  reg [ 7:0] OP2  // Operand Register 2
366
);
367
 
368
///////////////////////////////////////////////////////////////////////////////
369
//
370
// Local Parameter Declarations
371
//
372
 
373
localparam  pROM_AddrWidth = 8'd9;
374
localparam  pROM_Width     = 8'd32;
375
localparam  pROM_Depth     = (2**pROM_AddrWidth);
376
 
377
localparam  pDEC_AddrWidth = 8'd8;
378
localparam  pDEC_Width     = 8'd32;
379
localparam  pDEC_Depth     = (2**pDEC_AddrWidth);
380
 
381
//
382
 
383
localparam  pBA_Fill = (pROM_AddrWidth - pDEC_AddrWidth);
384
 
385
localparam  pBRV1    = 2'b01;   // MPC Via[1:0] code for BRV1 instruction
386
localparam  pBRV2    = 2'b10;   // MPC Via[1:0] code for BRV2 instruction
387
localparam  pBRV3    = 2'b11;   // MPC Via[1:0] code for BRV3 instruction
388
localparam  pBMW     = 4'b0011; // MPC I[3:0] code for BMW instruction
389
 
390
localparam  pNOP     = 8'hEA;   // NOP opcode
391
 
392
localparam  pPC_Pls  = 2'b01;   // PC Increment
393
localparam  pPC_Jmp  = 2'b10;   // PC Absolute Jump
394
localparam  pPC_Rel  = 2'b11;   // PC Conditional Branch
395
 
396
localparam  pIO_IF   = 2'b11;   // Instruction Fetch
397
localparam  pIO_RD   = 2'b10;   // Memory Read
398
localparam  pIO_WR   = 2'b01;   // Memory Write
399
 
400
localparam  pDO_ALU  = 2'b00;   // DO    <= ALU_Out
401
localparam  pDO_PCH  = 2'b01;   // DO    <= PC[15:8]
402
localparam  pDO_PCL  = 2'b10;   // DO    <= PC[ 7:0]
403
localparam  pDO_PSW  = 2'b11;   // DO    <= P (also available on ALU_Out)
404
//
405
localparam  pDI_Mem  = 2'b00;   // ALU_M <= DI
406
localparam  pDI_OP2  = 2'b01;   // OP2   <= DI
407
localparam  pDI_OP1  = 2'b10;   // OP1   <= DI
408
localparam  pDI_IR   = 2'b11;   // IR    <= DI
409
 
410
localparam  pStk_Psh = 2'b10;   // StkPtr <= S;
411
localparam  pStk_Pop = 2'b11;   // StkPtr <= S + 1;
412
 
413
localparam  pNA_Inc  = 4'h1;    // NA <= PC + 1
414
localparam  pNA_MAR  = 4'h2;    // NA <= MAR + 0
415
localparam  pNA_Nxt  = 4'h3;    // NA <= MAR + 1
416
localparam  pNA_Stk  = 4'h4;    // NA <= SP + 0
417
localparam  pNA_DPN  = 4'h5;    // NA <= {0, OP1} + 0
418
localparam  pNA_DPX  = 4'h6;    // NA <= {0, OP1} + {0, X}
419
localparam  pNA_DPY  = 4'h7;    // NA <= {0, OP1} + {0, Y}
420
localparam  pNA_LDA  = 4'h8;    // NA <= {OP2, OP1} + 0
421
//
422
//
423
//
424
//
425
//
426
localparam  pNA_LDAX = 4'hE;    // NA <= {OP2, OP1} + {0, X}
427
localparam  pNA_LDAY = 4'hF;    // NA <= {OP2, OP1} + {0, Y}
428
 
429
localparam  pBCD     = 3;       // Bit number of BCD Mode bit in P
430
localparam  pIntMsk  = 2;       // Bit number of Interrupt mask bit in P
431
 
432
localparam  pADC     = 4;       // ALU Operation Add w/ Carry
433
localparam  pSBC     = 5;       // ALU Operation Subtract w/ Carry
434
 
435
///////////////////////////////////////////////////////////////////////////////
436
//
437
// Local Signal Declarations
438
//
439
 
440
wire    WAI;                            // Instruction Mode Decode for WAI
441
 
442
wire    Ack;                            // External Ack gated by Wait
443
 
444
wire    BRV1;                           // MPC BRV1 Instruction Decode
445
wire    BRV2;                           // MPC BRV2 Instruction Decode
446
wire    BRV3;                           // MPC BRV3 Instruction Decode
447
wire    BMW;                            // MPC BMW Instruction Decode
448
 
449
reg     [(pROM_Width - 1):0] uP_ROM [(pROM_Depth - 1):0]; // Microprogram ROM
450
 
451
wire    [3:0] I;                        // MPC Instruction Input
452
wire    [3:0] T;                        // MPC Test Inputs
453
wire    [2:0] MW;                       // MPC Multi-way Branch Select
454
reg     [(pROM_AddrWidth - 1):0] BA;    // MPC Branch Address Input
455
wire    [1:0] Via;                      // MPC Via Mux Control Output
456
wire    [(pROM_AddrWidth - 1):0] MA;    // MPC uP ROM Address Output
457
//
458
reg     [(pROM_Width - 1):0] uPL;       // MPC uP ROM Pipeline Register
459
//
460
wire    [(pROM_AddrWidth - 1):0] uP_BA; // uP Branch Address Field
461
wire    Wait;
462
wire    [3:0] NA_Op;                    // Memory Address Register Control Fld
463
wire    [1:0] PC_Op;                    // Program Counter Control Field
464
wire    [1:0] DI_Op;                    // Memory Data Input Control Field
465
wire    [1:0] DO_Op;                    // Memory Data Output Control Field
466
wire    [1:0] Stk_Op;                   // Stack Pointer Control Field
467
wire    [2:0] Reg_WE;                   // Register Write Enable Control Field
468
//wire    ISR;                            // Asserted during interrupt entry
469
 
470
reg     En;                             // ALU Enable Control Field
471
 
472
wire    DP;                             // Direct Page addressing mode
473
reg     rDP;                            // Registered DP
474
wire    ZP;                             // Address Generator % 256 Command
475
 
476
//  Instruction Decoder ROM
477
 
478
reg     [(pDEC_Width - 1):0] ID_ROM [(pDEC_Depth - 1):0]; // Inst. Decode ROM
479
 
480
//  Instruction Decoder Pipeline Register (Asynchronous Distributed ROM)
481
 
482
reg     [(pDEC_Width - 1):0] IDEC;  // Instruction Decode ROM Pipeline Reg.
483
 
484
//  Instruction Decoder (Fixed) Output
485
 
486
wire    [3:0] Op;                   // M65C02 ALU Operation Select Field
487
wire    [1:0] QSel;                 // M65C02 ALU Q Operand Select Field
488
wire    RSel;                       // M65C02 ALU R Operand Select Field
489
wire    Sub;                        // M65C02 ALU Adder Control Field
490
wire    CSel;                       // M65C02 ALU Adder Carry In Select Field
491
wire    [2:0] WSel;                 // M65C02 ALU Register Write Select Field
492
wire    [2:0] OSel;                 // M65C02 ALU Output Select Field
493
wire    [4:0] CCSel;                // M65C02 ALU Condition Code Control Field
494
wire    [7:0] Msk;                  // M65C02 Rockwell Instruction Mask Field
495
 
496
wire    [7:0] Out;                  // M65C02 ALU Data Output Bus
497
wire    Valid;                      // M65C02 ALU Output Valid Signal
498
wire    [7:0] StkPtr;               // M65C02 ALU Stack Pointer Logic Output
499
wire    CC;                         // ALU Condition Code Output
500
 
501
wire    [15:0] dPC;                 // Pipeline Compensation Register
502
 
503
wire    CE_IR, CE_OP1, CE_OP2;      // Clock Enables: IR, OP1, and OP2
504
 
505
wire    D;                          // BCD mode bit in P
506
 
507
///////////////////////////////////////////////////////////////////////////////
508
//
509
//  Start Implementation
510
//
511
///////////////////////////////////////////////////////////////////////////////
512
 
513
//  Gate Ack_In
514
 
515
assign Ack = ((Wait) ? Ack_In : 1'b1);
516
 
517
//  Generate Internal Ready Signal
518
 
519
always @(*)
520
begin
521
    case({Done, (|Op & |Reg_WE), Valid, Ack})
522
        4'b0000 : Rdy <= 0;
523
        4'b0001 : Rdy <= 1;     // Non-ALU external cycle ready
524
        4'b0010 : Rdy <= 0;
525
        4'b0011 : Rdy <= 1;     // Non-ALU external cycle ready
526
        4'b0100 : Rdy <= 0;
527
        4'b0101 : Rdy <= 1;     // Operands not ready, external cycle ready
528
        4'b0110 : Rdy <= 0;
529
        4'b0111 : Rdy <= 1;     // Operands not ready, external cycle ready
530
        4'b1000 : Rdy <= 0;
531
        4'b1001 : Rdy <= 1;     // Non-ALU op and external fetch ready
532
        4'b1010 : Rdy <= 0;
533
        4'b1011 : Rdy <= 1;     // Non-ALU op and external fetch ready
534
        4'b1100 : Rdy <= 0;     // ALU op and external fetch not ready
535
        4'b1101 : Rdy <= 0;     // ALU op not ready and external fetch ready
536
        4'b1110 : Rdy <= 0;     // ALU op ready and external fetch not ready
537
        4'b1111 : Rdy <= 1;     // ALU op and external fetch cycle ready
538
    endcase
539
end
540
 
541
///////////////////////////////////////////////////////////////////////////////
542
//
543
//  Microprogram Controller Interface
544
//
545
//  Decode MPC Instructions being used for strobes
546
 
547
assign BRV1 = (Via == pBRV1);
548
assign BRV2 = (Via == pBRV2);
549
assign BRV3 = (Via == pBRV3);
550
assign BMW  = (I   == pBMW );
551
 
552
//  Define the Multi-Way Input Signals
553
//      Implement a 4-way branch when executing WAI, and a 2-way otherwise
554
 
555
assign MW = ((WAI) ? {uP_BA[2], xIRQ, Int} : {uP_BA[2:1], Int});
556
 
557
//  Implement the Branch Address Field Multiplexer for Instruction Decode
558
 
559
always @(*)
560
begin
561
    case(Via)
562
        pBRV1   : BA <= {{pBA_Fill{1'b1}}, DI[3:0], DI[7:4]};
563
        pBRV3   : BA <= ((Int) ? pInt_Hndlr
564
                               : {{pBA_Fill{1'b1}}, DI[3:0], DI[7:4]});
565
        default : BA <= uP_BA;
566
    endcase
567
end
568
 
569
//  Assign Test Input Signals
570
 
571
assign T = {3'b000, Valid};
572
 
573
//  Instantiate Microprogram Controller/Sequencer - modified F9408A MPC
574
 
575
M65C02_MPC #(
576
                .pAddrWidth(pROM_AddrWidth)
577
            ) MPC (
578
                .Rst(Rst),
579
                .Clk(Clk),
580
 
581
                .I(I),                      // Instruction 
582
                .T(T),                      // Test signal input
583
                .MW(MW),                    // Multi-way branch inputs
584
                .BA(BA),                    // Branch address input
585
                .Via(Via),                  // BRVx multiplexer control output
586
 
587
                .En(Wait),                  // Enable Ready Input
588
                .Rdy(Rdy),                  // Ready Input
589
 
590
                .PLS(1'b1),                 // Set for Pipelined Mode 
591
 
592
                .MA(MA)                     // Microprogram ROM address output
593
            );
594
 
595
//  Infer Microprogram ROM and initialize with file created by MCP_Tool
596
 
597
initial
598
    $readmemb(pM65C02_uPgm, uP_ROM, 0, (pROM_Depth - 1));
599
 
600
always @(posedge Clk)
601
begin
602
    if(Rdy | Rst)
603
        uPL <= #1 uP_ROM[MA];
604
end
605
 
606
//  Assign uPL fields
607
 
608
assign I       = uPL[31:28];    // MPC Instruction Field (4)
609
assign uP_BA   = uPL[27:19];    // MPC Branch Address Field (9)
610
assign Wait    = uPL[18];       // When Set, Conditional Execution Required (1)
611
assign SC      = uPL[17];       // Single Cycle Enable (1)
612
assign Done    = uPL[16];       // Multi-cycle Instruction Complete (1)
613
assign NA_Op   = uPL[15:12];    // Next Address Operation (4)
614
assign PC_Op   = uPL[11:10];    // Program Counter Control (2)
615
assign IO_Op   = uPL[9:8];      // IO Operation Control (2)
616
assign DI_Op   = uPL[7:6];      // DI Demultiplexer Control (2)
617
assign DO_Op   = uPL[7:6];      // DO Multiplexer Control (2) (same as DI_Op)
618
assign Stk_Op  = uPL[5:4];      // Stack Pointer Control Field (2)
619
assign Reg_WE  = uPL[3:1];      // Register Write Enable Field (3)
620
assign ISR     = uPL[0];        // Set to clear D and set I on interrupts (1)
621
 
622
//  Decode DI_Op Control Field
623
 
624
assign Ld_OP2 = IO_Op[1] & (DI_Op == pDI_OP2);
625
assign Ld_OP1 = IO_Op[1] & (DI_Op == pDI_OP1);
626
 
627
//  Operand Register 2
628
 
629
assign CE_OP2 = Ld_OP2 & Rdy & ~CE_IR;
630
 
631
always @(posedge Clk)
632
begin
633
    if(Rst)
634
        OP2 <= #1 0;
635
    else if(BRV2)
636
        OP2 <= #1 Vector[15:8];
637
    else if(CE_OP2)
638
        OP2 <= #1 DI;   // Load OP2 from DI
639
end
640
 
641
//  Operand Register 1
642
 
643
assign CE_OP1 = Ld_OP1 & Rdy & ~CE_IR;
644
 
645
always @(posedge Clk)
646
begin
647
    if(Rst)
648
        OP1 <= #1 0;
649
    else if(BRV2)
650
        OP1 <= #1 Vector[7:0];
651
    else if(CE_OP1)
652
        OP1 <= #1 DI;   // Load OP1 from DI
653
end
654
 
655
//  Instruction Register
656
 
657
assign CE_IR = (BRV1 | (BRV3 & ~Int)) & Rdy;  // Load IR from DI
658
 
659
always @(posedge Clk)
660
begin
661
    if(Rst)
662
        IR <= #1 pNOP;
663
    else if(CE_IR)
664
        IR <= #1 DI;
665
end
666
 
667
//  Infer Instruction Decode ROM and initialize with file created by MCP_Tool
668
 
669
initial
670
    $readmemb(pM65C02_IDec, ID_ROM, 0, (pDEC_Depth - 1));
671
 
672
always @(posedge Clk)
673
begin
674
    if(Rst)
675
        IDEC <= #1 ID_ROM[pNOP];
676
    else if(CE_IR)
677
        IDEC <= #1 ID_ROM[DI];
678
end
679
 
680
//  Decode Fixed Microcode Word
681
 
682
assign  Mode  = IDEC[31:29];     // M65C02 Instruction Type/Mode
683
assign  RMW   = IDEC[28];        // M65C02 Read-Modify-Write Instruction
684
assign  Op    = IDEC[27:24];     // M65C02 ALU Operation Select Field
685
assign  QSel  = IDEC[23:22];     // M65C02 ALU AU Q Bus Mux Select Field
686
assign  RSel  = IDEC[21];        // M65C02 ALU AU/SU R Bus Mux Select Field
687
assign  Sub   = IDEC[20];        // M65C02 ALU AU Mode Select Field
688
assign  CSel  = IDEC[19];        // M65C02 ALU AU/SU Carry Mux Select Field
689
assign  WSel  = IDEC[18:16];     // M65C02 ALU Register Write Select Field
690
assign  OSel  = IDEC[15:13];     // M65C02 ALU Register Output Select Field
691
assign  CCSel = IDEC[12: 8];     // M65C02 ALU Condition Code Control Field
692
assign  Msk   = IDEC[ 7: 0];     // M65C02 Rockwell Instruction Mask Field
693
 
694
// Decode Mode for internal signals
695
 
696
assign  WAI =  &Mode;               // Current Instruction is WAI
697
 
698
//  Compute Zero Page command to Address Generator
699
//      A page 0 addressing mode is commanded by the microcode in the NA_Op
700
//      field. Three such address calculations are generated. The zp and the
701
//      zp indexed address modes are the basis of all of the page 0 addressing
702
//      modes. The indirect zp addressing modes are generated using the direct
703
//      zp page addressing modes. The initial page 0 access for the lsb of the
704
//      pointer is followed by an automatic next operation on the MAR. Thus, if
705
//      a DP address mode command is followed by a Nxt address command, then the
706
//      second access is also a page 0 location and it must be wrapped. 
707
 
708
assign DP = ((NA_Op == pNA_DPN) | (NA_Op == pNA_DPX) | (NA_Op == pNA_DPY));
709
 
710
always @(posedge Clk)
711
begin
712
    if(Rst)
713
        rDP <= #1 0;
714
    else if(Rdy)
715
        rDP <= #1 DP;
716
end
717
 
718
assign ZP = (DP | ((NA_Op == pNA_Nxt) & rDP));
719
 
720
//  Next Address Generator
721
 
722
M65C02_AddrGen  AddrGen (
723
                    .Rst(Rst),
724
                    .Clk(Clk),
725
 
726
                    .Vector(Vector),
727
 
728
                    .NA_Op(NA_Op),
729
                    .PC_Op(PC_Op),
730
                    .Stk_Op(Stk_Op),
731
 
732
                    .ZP(ZP),
733
 
734
                    .CC(CC),
735
                    .BRV3(BRV3),
736
                    .Int(Int),
737
 
738
                    .Rdy(Rdy),
739
 
740
                    .DI(DI),
741
                    .OP1(OP1),
742
                    .OP2(OP2),
743
                    .StkPtr(StkPtr),
744
                    .X(X),
745
                    .Y(Y),
746
 
747
                    .AO(AO),
748
 
749
                    .AL(),
750
                    .AR(),
751
                    .NA(),
752
                    .MAR(),
753
 
754
                    .PC(PC),
755
                    .dPC(dPC)
756
                );
757
 
758
//  Interrupt Service Flag
759
 
760
assign CE_IntSvc = (  (Int & (BRV3 | BMW))
761
                    | ((IO_Op == pIO_WR) & (DO_Op == pDO_PSW)));
762
 
763
always @(posedge Clk)
764
begin
765
    if(Rst)
766
        IntSvc <= #1 0;
767
    else if(CE_IntSvc)
768
        IntSvc <= #1 (Int & (BRV3 | BMW));
769
end
770
 
771
//  Instantiate the M65C02 ALU Module
772
 
773
always @(*) En <= (|Reg_WE);
774
 
775
M65C02_ALU  #(
776
                .pStkPtr_Rst(pStkPtr_Rst)
777
            ) ALU (
778
                .Rst(Rst),          // System Reset
779
                .Clk(Clk),          // System Clock
780
 
781
                .Rdy(Rdy),          // Ready
782
 
783
                .En(En),            // M65C02 ALU Enable Strobe Input
784
                .Reg_WE(Reg_WE),    // M65C02 ALU Register Write Enable
785
                .ISR(ISR),          // M65C02 ALU Interrupt Service Rtn Strb
786
 
787
                .Op(Op),            // M65C02 ALU Operation Select Input
788
                .QSel(QSel),        // M65C02 ALU Q Data Mux Select Input
789
                .RSel(RSel),        // M65C02 ALU R Data Mux Select Input
790
                .Sub(Sub),          // M65C02 ALU Adder Function Select Input
791
                .CSel(CSel),        // M65C02 ALU Adder Carry Select Input
792
                .WSel(WSel),        // M65C02 ALU Register Write Select Input
793
                .OSel(OSel),        // M65C02 ALU Output Register Select Input
794
                .CCSel(CCSel),      // M65C02 ALU Condition Code Select Input
795
                .Msk(Msk),          // M65C02 ALU Rockwell Instruction Mask
796
 
797
                .M(OP1),            // M65C02 ALU Memory Operand Input
798
                .Out(Out),          // M65C02 ALU Output Multiplexer
799
                .Valid(Valid),      // M65C02 ALU Output Valid Strobe
800
 
801
                .CC_Out(CC),        // M65C02 ALU Condition Code Mux Output
802
 
803
                .StkOp(Stk_Op),     // M65C02 ALU Stack Pointer Operation
804
                .StkPtr(StkPtr),    // M65C02 ALU Stack Pointer Multiplexer
805
 
806
                .A(A),              // M65C02 ALU Accumulator Register
807
                .X(X),              // M65C02 ALU Pre-Index Register
808
                .Y(Y),              // M65C02 ALU Post-Index Register
809
                .S(S),              // M65C02 ALU Stack Pointer Register
810
 
811
                .P(P)               // M65C02 Processor Status Word Register
812
            );
813
 
814
//  Decode P
815
 
816
assign IRQ_Msk = P[pIntMsk];        // Interrupt Mask Bit
817
assign D       = P[pBCD];           // BCD Mode Bit   
818
 
819
//  External Bus Data Output
820
 
821
always @(*)
822
begin
823
    if(Rst)
824
        DO <= #1 0;
825
    else
826
        case(DO_Op)
827
            pDO_PSW : DO <= P;                                  // M65C02 PSW
828
            pDO_PCL : DO <= ((IntSvc) ? dPC[ 7:0] : PC[ 7:0]);  // M65C02 PCL
829
            pDO_PCH : DO <= ((IntSvc) ? dPC[15:8] : PC[15:8]);  // M65C02 PCH
830
            default : DO <= Out;                                // M65C02 ALU
831
        endcase
832
end
833
 
834
///////////////////////////////////////////////////////////////////////////////
835
//
836
//  End Implementation
837
//
838
///////////////////////////////////////////////////////////////////////////////
839
 
840
endmodule

powered by: WebSVN 2.1.0

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