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
|