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
|