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

Subversion Repositories m65c02

[/] [m65c02/] [trunk/] [Src/] [RTL/] [M65C02_Core.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:     (See additional comments section below)
52
//
53
// Dependencies:    M65C02_MPCv3.v
54
//                      M65C02_uPgm_V3a.coe (M65C02_uPgm_V3a.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    12K12   MAM     Cleaned up, and replaced Wait signal in variable
248
//                          microcode with a ZP control signal. When asserted,
249
//                          ZP forces a % 256 address calculation. Applies to
250
//                          zp,X; zp,Y; (zp,X); and (zp),Y addressing modes. In
251
//                          zp,X and zp,Y addressing modes, the indexed zp value
252
//                          must wrap araund the 256 boundary. In (zp,X), both
253
//                          the low and the high byte of the 16-bit pointer are
254
//                          in page 0. The 8-bit index operation must be wrapp-
255
//                          ed on page 0, and so must the second, the high byte
256
//                          of the address. In (zp),Y, the index operation is
257
//                          allowed to cross a page boundary, i.e. not % 256.
258
//                          But both bytes of the pointer must be fetched from
259
//                          page 0. Therefore, the increment operation to get
260
//                          the second byte must be wrapped to page 0.
261
//
262
//  3.00    12K20   MAM     Renamed signal Last to Rdy. Rdy is asserted
263
//                          on the last cycle of a multi-cycle microcycle. Added
264
//                          (Rdy | Rst) as a ROM enable for the microprogram
265
//                          ROM to ensure that the microprogram word is constant
266
//                          during a multi-cycle microcycle. Rst is included to
267
//                          allow the first microword to be fetched during Rst
268
//                          in support of the MPC's pipelined operation. (For
269
//                          additional clarification refer to comment 1.6 of the
270
//                          M65C02_ALU module.)
271
//
272
//  3.10    12L09   MAM     Added capability to support WAI instruction. Needed
273
//                          signal, xIRQ, that indicates an active low external
274
//                          interrupt request is asserted but the interrupt mask
275
//                          is set so the processor will not take the interrupt.
276
//                          Under these conditions, the WAI continues with the
277
//                          next sequential instruction. In addition to adding
278
//                          xIRQ to the input ports of the core, the multi-way
279
//                          branch multiplexer required a change to support a 
280
//                          4-way branch table when WAI is executing, and a
281
//                          2-way for all other instructions. To support the
282
//                          detection of the WAI instruction, changed the Mode
283
//                          vector to identify the WAI and STP instructions.
284
//
285
//  3.20    12L13   MAM     Renamed, previously unused and reserved fixed micro-
286
//                          word Opcode field to Msk, and ported into the ALU.
287
//                          The new field provides the bit mask needed for the
288
//                          implementation of the Rockwell instructions.
289
//
290
//  3.21    13B16   MAM     Added ISR signal to port list to easily allow the
291
//                          external logic to generate the vector pull signal.
292
//
293
//  3.30    13C02   MAM     Changed MPC from M65C02_MPCv3 to M65C02_MPCv4. V4
294
//                          includes a wait state generator to maintain a cons-
295
//                          tant external Phi1O/Phi2O duty cycle. Because of new
296
//                          wait state generator, the BUFGMUX instantiated and
297
//                          used for clock stretching is removed.
298
//
299
//  3.40    13H04   MAM     Removed unused code. Changed DO bus to simple OR
300
//                          gate instead of multiplxer. Added decode ROM to sup-
301
//                          port one-hot select of various DO bus sources. Used
302
//                          microcycle control signal in place of internal Rdy
303
//                          signal. Changed MPC_En to Rdy, and deleted internal
304
//                          ready 16:1 decoder.
305
//
306
// Additional Comments:
307
//
308
//  This module is derived from the first implementation which assummed it was
309
//  the top level implementation, i.e. its ports would be connected to IO pins.
310
//  The pipelining of the control signals, instruction and operand addresses,
311
//  and the data proved a bit cumbersome to deal with. The intention was to al-
312
//  ways have that first implementation function as a core around which other
313
//  components and capabilities could be added. With the incorporation of the
314
//  memory interface directly in the core, interactions between the memory in-
315
//  terface and the core logic hindered the development of the microprogram.
316
//
317
//  Thus, the decision was made to sever the core functions from that of the
318
//  memory interface. A single signal, Ack, would force the core logic to wait
319
//  in the event that the required read data was unavailable or the write
320
//  buffers were full. This design decision allows the memory interface and its
321
//  interaction with the core logic to be separated at a clean boundary. The
322
//  result is that timing on the core's external address and data busses can be
323
//  treated as single cycle operations. That is, memory read and memory write
324
//  transactions are completed in the same cycle, i.e no (pipeline) delays.
325
//
326
//  This simplified core architecture must be coupled to an external memory
327
//  controller at the next higher level that implements the required memory
328
//  transactions and provides the Ack signal to control the execution of the 
329
//  core logic state machine. With the core's memory interface, it would be
330
//  easy to add a simple cache memory module to provide data at a rate high to
331
//  the core to achieve as high a clocks per instruction (CPI) metric as possi-
332
//  ble for the complex addressing of the 6502 core.
333
//
334
//  Furthermore, the core must be coupled to logic to handle the edge-sensitive
335
//  NMI, and level sensitive IRQ interrupts. The core, as currently iplemented,
336
//  accepts a vector from this external module for Rst, NMI, IRQ, and/or BRK.
337
//  (In some implementations of the 6502, notably the WDC W65C802, the IRQ vec-
338
//  tor is not shared with the BRK interrupt. In that implementation, a sepa-
339
//  rate BRK vector is allowed. This core indicates to external logic that a
340
//  BRK instruction is being processed, so it is possible for the BRK vector to
341
//  be separated from the IRQ vector. In addition, the vector supplied is not
342
//  the vector address through which the W65C02 perform an indirect jump. In-
343
//  stead, the vector supplied is the content of the indirect jump address.)
344
//
345
///////////////////////////////////////////////////////////////////////////////
346
 
347
module M65C02_Core #(
348
    parameter pStkPtr_Rst  = 8'hFF, // Stk Ptr Value after Reset
349
    parameter pInt_Hndlr   = 0,     // _Int microroutine address, Reset default
350
    parameter pM65C02_uPgm = "M65C02_uPgm_V3a.coe",
351
    parameter pM65C02_IDec = "M65C02_Decoder_ROM.coe"
352
)(
353
    input   Rst,            // System Reset Input
354
    input   Clk,            // System Clock Input
355
 
356
    //  Processor Core Interrupt Interface
357
 
358
    output  IRQ_Msk,        // Interrupt mask from P to Interrupt Handler
359
    input   xIRQ,           // External Maskable Interrupt Request Input
360
    input   Int,            // Interrupt input from Interrupt Handler
361
    input   [15:0] Vector,  // ISR Vector from Interrupt Handler
362
 
363
    //  Processor Core Status Interface
364
 
365
    output  Done,           // Instruction Complete/Fetch Strobe
366
    output  SC,             // Single Cycle Instruction
367
    output  [2:0] Mode,     // Mode - Instruction Type/Mode
368
    output  RMW,            // Read-Modify-Write Operation
369
    output  reg IntSvc,     // Interrupt Service Start Indicator
370
    output  ISR,            // Interrupt Vector Pull Start Flag
371
 
372
    //  Processor Core Memory Controller Interface
373
 
374
    output  [2:0] MC,       // Microcycle state:   2-C1; 3-C4; 1-C3; 0-C4;
375
    output  [1:0] MemTyp,   // Memory access Type: 0-Pgm Memory; 1-Page 0;
376
                            //                     2-Page 1;     3-Data Memory;
377
    input   Wait,           // Wait Input (in C3, adds wait state sequence)
378
    output  Rdy,            // Internal Ready
379
 
380
    //  Processor Core Memory Cycle Interface    
381
 
382
    output  [ 1:0] IO_Op,   // Instruction Fetch Strobe
383
    output  [15:0] AO,      // External Address
384
    input   [ 7:0] DI,      // External Data In
385
    output  reg [7:0] DO,   // External Data Out
386
 
387
    // Processor Core Internal Registers
388
 
389
    output  [ 7:0] A,       // Accumulator
390
    output  [ 7:0] X,       // Index Register X
391
    output  [ 7:0] Y,       // Index Register Y
392
    output  [ 7:0] S,       // Stack Pointer
393
    output  [ 7:0] P,       // Processor Status Word
394
    output  [15:0] PC,      // Program Counter
395
 
396
    output  reg [7:0] IR,   // Instruction Register
397
    output  reg [7:0] OP1,  // Operand Register 1
398
    output  reg [7:0] OP2   // Operand Register 2
399
);
400
 
401
///////////////////////////////////////////////////////////////////////////////
402
//
403
// Local Parameter Declarations
404
//
405
 
406
localparam  pROM_AddrWidth = 8'd9;
407
localparam  pROM_Width     = 8'd32;
408
localparam  pROM_Depth     = (2**pROM_AddrWidth);
409
 
410
localparam  pDEC_AddrWidth = 8'd8;
411
localparam  pDEC_Width     = 8'd32;
412
localparam  pDEC_Depth     = (2**pDEC_AddrWidth);
413
 
414
//
415
 
416
localparam  pBA_Fill = (pROM_AddrWidth - pDEC_AddrWidth);
417
 
418
localparam  pBRV1    = 2'b01;   // MPC Via[1:0] code for BRV1 instruction
419
localparam  pBRV2    = 2'b10;   // MPC Via[1:0] code for BRV2 instruction
420
localparam  pBRV3    = 2'b11;   // MPC Via[1:0] code for BRV3 instruction
421
localparam  pBMW     = 4'b0011; // MPC I[3:0] code for BMW instruction
422
 
423
localparam  pNOP     = 8'hEA;   // NOP opcode
424
 
425
localparam  pPC_Pls  = 2'b01;   // PC Increment
426
localparam  pPC_Jmp  = 2'b10;   // PC Absolute Jump
427
localparam  pPC_Rel  = 2'b11;   // PC Conditional Branch
428
 
429
localparam  pIO_IF   = 2'b11;   // Instruction Fetch
430
localparam  pIO_RD   = 2'b10;   // Memory Read
431
localparam  pIO_WR   = 2'b01;   // Memory Write
432
 
433
localparam  pDO_ALU  = 2'b00;   // DO    <= ALU_Out
434
localparam  pDO_PCH  = 2'b01;   // DO    <= PC[15:8]
435
localparam  pDO_PCL  = 2'b10;   // DO    <= PC[ 7:0]
436
localparam  pDO_PSW  = 2'b11;   // DO    <= P (also available on ALU_Out)
437
//
438
localparam  pDI_Mem  = 2'b00;   // ALU_M <= DI
439
localparam  pDI_OP2  = 2'b01;   // OP2   <= DI
440
localparam  pDI_OP1  = 2'b10;   // OP1   <= DI
441
localparam  pDI_IR   = 2'b11;   // IR    <= DI
442
 
443
localparam  pStk_Psh = 2'b10;   // StkPtr <= S;
444
localparam  pStk_Pop = 2'b11;   // StkPtr <= S + 1;
445
 
446
localparam  pNA_Inc  = 4'h1;    // NA <= PC + 1
447
localparam  pNA_MAR  = 4'h2;    // NA <= MAR + 0
448
localparam  pNA_Nxt  = 4'h3;    // NA <= MAR + 1
449
localparam  pNA_Stk  = 4'h4;    // NA <= SP + 0
450
localparam  pNA_DPN  = 4'h5;    // NA <= {0, OP1} + 0
451
localparam  pNA_DPX  = 4'h6;    // NA <= {0, OP1} + {0, X}
452
localparam  pNA_DPY  = 4'h7;    // NA <= {0, OP1} + {0, Y}
453
localparam  pNA_LDA  = 4'h8;    // NA <= {OP2, OP1} + 0
454
//
455
//
456
//
457
//
458
//
459
localparam  pNA_LDAX = 4'hE;    // NA <= {OP2, OP1} + {0, X}
460
localparam  pNA_LDAY = 4'hF;    // NA <= {OP2, OP1} + {0, Y}
461
 
462
localparam  pBCD     = 3;       // Bit number of BCD Mode bit in P
463
localparam  pIntMsk  = 2;       // Bit number of Interrupt mask bit in P
464
 
465
localparam  pADC     = 4;       // ALU Operation Add w/ Carry
466
localparam  pSBC     = 5;       // ALU Operation Subtract w/ Carry
467
 
468
///////////////////////////////////////////////////////////////////////////////
469
//
470
// Local Signal Declarations
471
//
472
 
473
wire    WAI;                            // Instruction Mode Decode for WAI
474
 
475
wire    BRV1;                           // MPC BRV1 Instruction Decode
476
wire    BRV2;                           // MPC BRV2 Instruction Decode
477
wire    BRV3;                           // MPC BRV3 Instruction Decode
478
wire    BMW;                            // MPC BMW Instruction Decode
479
 
480
reg     [(pROM_Width - 1):0] uP_ROM [(pROM_Depth - 1):0]; // Microprogram ROM
481
 
482
wire    [3:0] I;                        // MPC Instruction Input
483
wire    [3:0] T;                        // MPC Test Inputs
484
wire    [2:0] MW;                       // MPC Multi-way Branch Select
485
reg     [(pROM_AddrWidth - 1):0] BA;    // MPC Branch Address Input
486
wire    [1:0] Via;                      // MPC Via Mux Control Output
487
wire    [(pROM_AddrWidth - 1):0] MA;    // MPC uP ROM Address Output
488
//
489
reg     [(pROM_Width - 1):0] uPL;       // MPC uP ROM Pipeline Register
490
//
491
wire    [(pROM_AddrWidth - 1):0] uP_BA; // uP Branch Address Field
492
wire    ZP;                             // Zero Page Addressing Control Field
493
wire    [3:0] NA_Op;                    // Memory Address Register Control Fld
494
wire    [1:0] PC_Op;                    // Program Counter Control Field
495
wire    [1:0] DI_Op;                    // Memory Data Input Control Field
496
wire    [1:0] DO_Op;                    // Memory Data Output Control Field
497
wire    [1:0] Stk_Op;                   // Stack Pointer Control Field
498
wire    [2:0] Reg_WE;                   // Register Write Enable Control Field
499
 
500
reg     En;                             // ALU Enable Control Field
501
 
502
//  Instruction Decoder ROM
503
 
504
reg     [(pDEC_Width - 1):0] ID_ROM [(pDEC_Depth - 1):0]; // Inst. Decode ROM
505
 
506
//  Instruction Decoder Pipeline Register (Asynchronous Distributed ROM)
507
 
508
reg     [(pDEC_Width - 1):0] IDEC;  // Instruction Decode ROM Pipeline Reg.
509
 
510
//  Instruction Decoder (Fixed) Output
511
 
512
wire    [3:0] Op;                   // M65C02 ALU Operation Select Field
513
wire    [1:0] QSel;                 // M65C02 ALU Q Operand Select Field
514
wire    RSel;                       // M65C02 ALU R Operand Select Field
515
wire    Sub;                        // M65C02 ALU Adder Control Field
516
wire    CSel;                       // M65C02 ALU Adder Carry In Select Field
517
wire    [2:0] WSel;                 // M65C02 ALU Register Write Select Field
518
wire    [2:0] OSel;                 // M65C02 ALU Output Select Field
519
wire    [4:0] CCSel;                // M65C02 ALU Condition Code Control Field
520
wire    [7:0] Msk;                  // M65C02 Rockwell Instruction Mask Field
521
 
522
wire    [7:0] Out;                  // M65C02 ALU Data Output Bus
523
wire    Valid;                      // M65C02 ALU Output Valid Signal
524
wire    [7:0] StkPtr;               // M65C02 ALU Stack Pointer Logic Output
525
wire    CC;                         // ALU Condition Code Output
526
 
527
wire    [15:0] dPC;                 // Pipeline Compensation Register for PC
528
 
529
wire    CE_IR, CE_OP1, CE_OP2;      // Clock Enables: IR, OP1, and OP2
530
 
531
reg     [5:0] DO_Sel;               // Data Output Multiplexer Decode ROM
532
 
533
///////////////////////////////////////////////////////////////////////////////
534
//
535
//  Start Implementation
536
//
537
///////////////////////////////////////////////////////////////////////////////
538
 
539
//  Define Microcycle and Instruction Cycle Status Signals
540
 
541
assign Done = (|Via);         // Instruction Complete (1)     - ~BRV0
542
assign SC   = (&Via);         // Single Cycle Instruction (1) -  BRV3             
543
assign Rdy  = (MC == 4);      // Microcycle Complete Signal
544
 
545
///////////////////////////////////////////////////////////////////////////////
546
//
547
//  Microprogram Controller Interface
548
//
549
//  Decode MPC Instructions being used for strobes
550
 
551
assign BRV1 = (Via == pBRV1);
552
assign BRV2 = (Via == pBRV2);
553
assign BRV3 = (Via == pBRV3);
554
assign BMW  = (I   == pBMW );
555
 
556
//  Define the Multi-Way Input Signals
557
//      Implement a 4-way branch when executing WAI, and a 2-way otherwise
558
 
559
assign MW = ((WAI) ? {uP_BA[2], xIRQ, Int} : {uP_BA[2:1], Int});
560
 
561
//  Implement the Branch Address Field Multiplexer for Instruction Decode
562
 
563
always @(*)
564
begin
565
    case(Via)
566
        pBRV1   : BA <= {{pBA_Fill{1'b1}}, DI[3:0], DI[7:4]};
567
        pBRV3   : BA <= ((Int) ? pInt_Hndlr
568
                               : {{pBA_Fill{1'b1}}, DI[3:0], DI[7:4]});
569
        default : BA <= uP_BA;
570
    endcase
571
end
572
 
573
//  Assign Test Input Signals
574
 
575
assign T = {3'b000, Valid};
576
 
577
//  Instantiate Microprogram Controller/Sequencer - modified F9408A MPC
578
 
579
M65C02_MPCv4    #(
580
                    .pAddrWidth(pROM_AddrWidth)
581
                ) MPCv4 (
582
                    .Rst(Rst),
583
                    .Clk(Clk),
584
 
585
                    .Wait(Wait),            // Microcycle Wait state request
586
                    .MC(MC),                // Microcycle State
587
 
588
                    .I(I),                  // Instruction 
589
                    .T(T),                  // Test signal input
590
                    .MW(MW),                // Multi-way branch inputs
591
                    .BA(BA),                // Branch address input
592
                    .Via(Via),              // BRVx multiplexer control output
593
 
594
                    .MA(MA)                 // Microprogram ROM address output
595
                );
596
 
597
//  Infer Microprogram ROM and initialize with file created by MCP_Tool
598
 
599
initial
600
    $readmemb(pM65C02_uPgm, uP_ROM, 0, (pROM_Depth - 1));
601
 
602
always @(posedge Clk)
603
begin
604
    if(Rdy | Rst)
605
        uPL <= #1 uP_ROM[MA];
606
end
607
 
608
//  Assign uPL fields
609
 
610
assign I      = uPL[31:28];     // MPC Instruction Field (4)
611
assign uP_BA  = uPL[27:19];     // MPC Branch Address Field (9)
612
assign ZP     = uPL[18];        // When Set, ZP % 256 addressing required (1)
613
assign MemTyp = uPL[17:16];     // Memory Type (2)
614
assign NA_Op  = uPL[15:12];     // Next Address Operation (4)
615
assign PC_Op  = uPL[11:10];     // Program Counter Control (2)
616
assign IO_Op  = uPL[9:8];       // IO Operation Control (2)
617
assign DI_Op  = uPL[7:6];       // DI Demultiplexer Control (2)
618
assign DO_Op  = uPL[7:6];       // DO Multiplexer Control (2) (same as DI_Op)
619
assign Stk_Op = uPL[5:4];       // Stack Pointer Control Field (2)
620
assign Reg_WE = uPL[3:1];       // Register Write Enable Field (3)
621
assign ISR    = uPL[0];         // Set to clear D and set I on interrupts (1)
622
 
623
//  Decode DI_Op Control Field
624
 
625
assign Ld_OP2 = IO_Op[1] & (DI_Op == pDI_OP2);
626
assign Ld_OP1 = IO_Op[1] & (DI_Op == pDI_OP1);
627
 
628
//  Operand Register 2
629
 
630
assign CE_OP2 = Ld_OP2 & Rdy & ~CE_IR;
631
 
632
always @(posedge Clk)
633
begin
634
    if(Rst)
635
        OP2 <= #1 0;
636
    else if(BRV2)
637
        OP2 <= #1 Vector[15:8];
638
    else if(CE_OP2)
639
        OP2 <= #1 DI;   // Load OP2 from DI
640
end
641
 
642
//  Operand Register 1
643
 
644
assign CE_OP1 = Ld_OP1 & Rdy & ~CE_IR;
645
 
646
always @(posedge Clk)
647
begin
648
    if(Rst)
649
        OP1 <= #1 0;
650
    else if(BRV2)
651
        OP1 <= #1 Vector[7:0];
652
    else if(CE_OP1)
653
        OP1 <= #1 DI;   // Load OP1 from DI
654
end
655
 
656
//  Instruction Register
657
 
658
assign CE_IR = (BRV1 | (BRV3 & ~Int)) & Rdy;  // Load IR from DI
659
 
660
always @(posedge Clk)
661
begin
662
    if(Rst)
663
        IR <= #1 pNOP;
664
    else if(CE_IR)
665
        IR <= #1 DI;
666
end
667
 
668
//  Infer Instruction Decode ROM and initialize with file created by MCP_Tool
669
 
670
initial
671
    $readmemb(pM65C02_IDec, ID_ROM, 0, (pDEC_Depth - 1));
672
 
673
always @(posedge Clk)
674
begin
675
    if(Rst)
676
        IDEC <= #1 ID_ROM[pNOP];
677
    else if(CE_IR)
678
        IDEC <= #1 ID_ROM[DI];
679
end
680
 
681
//  Decode Fixed Microcode Word
682
 
683
assign  Mode  = IDEC[31:29];       // M65C02 Instruction Type/Mode
684
assign  RMW   = IDEC[28];          // M65C02 Read-Modify-Write Instruction
685
assign  Op    = IDEC[27:24];       // M65C02 ALU Operation Select Field
686
assign  QSel  = IDEC[23:22];       // M65C02 ALU AU Q Bus Mux Select Field
687
assign  RSel  = IDEC[21];          // M65C02 ALU AU/SU R Bus Mux Select Field
688
assign  Sub   = IDEC[20];          // M65C02 ALU AU Mode Select Field
689
assign  CSel  = IDEC[19];          // M65C02 ALU AU/SU Carry Mux Select Field
690
assign  WSel  = IDEC[18:16];       // M65C02 ALU Register Write Select Field
691
assign  OSel  = IDEC[15:13];       // M65C02 ALU Register Output Select Field
692
assign  CCSel = IDEC[12: 8];       // M65C02 ALU Condition Code Control Field
693
assign  Msk   = IDEC[ 7: 0];       // M65C02 Rockwell Instruction Mask Field
694
 
695
// Decode Mode for internal signals
696
 
697
assign  WAI =  &Mode;               // Current Instruction is WAI
698
 
699
//  Next Address Generator
700
 
701
M65C02_AddrGen  AddrGen (
702
                    .Rst(Rst),
703
                    .Clk(Clk),
704
 
705
                    .Vector(Vector),
706
 
707
                    .NA_Op(NA_Op),
708
                    .PC_Op(PC_Op),
709
                    .Stk_Op(Stk_Op),
710
 
711
                    .ZP(ZP),
712
 
713
                    .CC(CC),
714
                    .BRV3(BRV3),
715
                    .Int(Int),
716
 
717
                    .Rdy(Rdy),
718
 
719
                    .DI(DI),
720
                    .OP1(OP1),
721
                    .OP2(OP2),
722
                    .StkPtr(StkPtr),
723
                    .X(X),
724
                    .Y(Y),
725
 
726
                    .AO(AO),
727
 
728
                    .AL(),
729
                    .AR(),
730
                    .NA(),
731
                    .MAR(),
732
 
733
                    .PC(PC),
734
                    .dPC(dPC)
735
                );
736
 
737
//  Interrupt Service Flag
738
 
739
assign CE_IntSvc = (  (Int & (BRV3 | BMW))
740
                    | ((IO_Op == pIO_WR) & (DO_Op == pDO_PSW)));
741
 
742
always @(posedge Clk)
743
begin
744
    if(Rst)
745
        IntSvc <= #1 0;
746
    else if(CE_IntSvc)
747
        IntSvc <= #1 (Int & (BRV3 | BMW));
748
end
749
 
750
//  Instantiate the M65C02 ALU Module
751
 
752
always @(*) En <= (|Reg_WE);
753
 
754
M65C02_ALU  #(
755
                .pStkPtr_Rst(pStkPtr_Rst)
756
            ) ALU (
757
                .Rst(Rst),          // System Reset
758
                .Clk(Clk),          // System Clock
759
 
760
                .Rdy(Rdy),          // Ready
761
 
762
                .En(En),            // M65C02 ALU Enable Strobe Input
763
                .Reg_WE(Reg_WE),    // M65C02 ALU Register Write Enable
764
                .ISR(ISR),          // M65C02 ALU Interrupt Service Rtn Strb
765
 
766
                .Op(Op),            // M65C02 ALU Operation Select Input
767
                .QSel(QSel),        // M65C02 ALU Q Data Mux Select Input
768
                .RSel(RSel),        // M65C02 ALU R Data Mux Select Input
769
                .Sub(Sub),          // M65C02 ALU Adder Function Select Input
770
                .CSel(CSel),        // M65C02 ALU Adder Carry Select Input
771
                .WSel(WSel),        // M65C02 ALU Register Write Select Input
772
                .OSel(OSel),        // M65C02 ALU Output Register Select Input
773
                .CCSel(CCSel),      // M65C02 ALU Condition Code Select Input
774
                .Msk(Msk),          // M65C02 ALU Rockwell Instructions Mask
775
 
776
                .M(OP1),            // M65C02 ALU Memory Operand Input
777
                .Out(Out),          // M65C02 ALU Output Multiplexer
778
                .Valid(Valid),      // M65C02 ALU Output Valid Strobe
779
 
780
                .CC_Out(CC),        // M65C02 ALU Condition Code Mux Output
781
 
782
                .StkOp(Stk_Op),     // M65C02 ALU Stack Pointer Operation
783
                .StkPtr(StkPtr),    // M65C02 ALU Stack Pointer Multiplexer
784
 
785
                .A(A),              // M65C02 ALU Accumulator Register
786
                .X(X),              // M65C02 ALU Pre-Index Register
787
                .Y(Y),              // M65C02 ALU Post-Index Register
788
                .S(S),              // M65C02 ALU Stack Pointer Register
789
 
790
                .P(P)               // M65C02 Processor Status Word Register
791
            );
792
 
793
//  Decode P
794
 
795
assign IRQ_Msk = P[pIntMsk];        // Interrupt Mask Bit
796
 
797
//  External Bus Data Output
798
 
799
always @(*)                // P ddPP O
800
begin                      // S PPCC u
801
    case({IntSvc, DO_Op})  // W HLHL t
802
        3'b000 : DO_Sel <= 6'b0_0000_1;
803
        3'b001 : DO_Sel <= 6'b0_0010_0;
804
        3'b010 : DO_Sel <= 6'b0_0001_0;
805
        3'b011 : DO_Sel <= 6'b1_0000_0;
806
        3'b100 : DO_Sel <= 6'b0_0000_1;
807
        3'b101 : DO_Sel <= 6'b0_1000_0;
808
        3'b110 : DO_Sel <= 6'b0_0100_0;
809
        3'b111 : DO_Sel <= 6'b1_0000_0;
810
    endcase
811
end
812
 
813
always @(*) DO <= (  ((DO_Sel[5]) ? P         : 0)
814
                   | ((DO_Sel[4]) ? dPC[15:8] : 0)
815
                   | ((DO_Sel[3]) ? dPC[ 7:0] : 0)
816
                   | ((DO_Sel[2]) ?  PC[15:8] : 0)
817
                   | ((DO_Sel[1]) ?  PC[ 7:0] : 0)
818
                   | ((DO_Sel[0]) ? Out       : 0));
819
 
820
///////////////////////////////////////////////////////////////////////////////
821
//
822
//  End Implementation
823
//
824
///////////////////////////////////////////////////////////////////////////////
825
 
826
endmodule

powered by: WebSVN 2.1.0

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