1 |
2 |
MichaelA |
///////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
//
|
3 |
|
|
// Copyright 2009-2012 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: 10/30/2009
|
45 |
|
|
// Design Name: WDC W65C02 Microprocessor Re-Implementation
|
46 |
|
|
// Module Name: M65C02_MPC
|
47 |
|
|
// Project Name: C:\XProjects\ISE10.1i\MAM6502
|
48 |
|
|
// Target Devices: Generic SRAM-based FPGA
|
49 |
|
|
// Tool versions: Xilinx ISE 10.1i SP3
|
50 |
|
|
//
|
51 |
|
|
// Description:
|
52 |
|
|
//
|
53 |
|
|
// This module implements a simple microprogram sequencer based on the Fair-
|
54 |
|
|
// child F9408. The sequencer provides:
|
55 |
|
|
//
|
56 |
|
|
// (1) 4-bit instruction input
|
57 |
|
|
// (2) four-level LIFO stack;
|
58 |
|
|
// (3) program counter and incrementer;
|
59 |
|
|
// (4) 4-bit registered test input;
|
60 |
|
|
// (5) 8-way multi-way branch control input;
|
61 |
|
|
// (6) branch address input;
|
62 |
|
|
// (7) 4-way branch address select output;
|
63 |
|
|
// (8) next address output.
|
64 |
|
|
//
|
65 |
|
|
// These elements provide a relatively flexible general purpose microprogram
|
66 |
|
|
// controller without a complex instruction set. The sixteen instructions can
|
67 |
|
|
// be categorized into three classes: (1) fetch, (2) unconditional branches,
|
68 |
|
|
// and (3) conditional branches. The fetch instruction class, a single instruc-
|
69 |
|
|
// tion class, simply increments the program counter and outputs the current
|
70 |
|
|
// value of the program counter on the next address bus. The unconditional
|
71 |
|
|
// branch instruction class provides instructions to select the next instruc-
|
72 |
|
|
// tion using the Via[1:0] outputs and output that value on the next address
|
73 |
|
|
// bus and simultaneously load the program counter. The unconditional branch
|
74 |
|
|
// instruction class also provides for 8-way multiway branching using an exter-
|
75 |
|
|
// nal (priority) encoder/branch selector, and microprogram subroutine call and
|
76 |
|
|
// return instructions.
|
77 |
|
|
//
|
78 |
|
|
// The instruction encodings of the F9408, as provided in "Principles of Firm-
|
79 |
|
|
// ware Engineering in Microprogram Control" by Michael Andrews. The instruc-
|
80 |
|
|
// tion set and operation map for the implementation is given below:
|
81 |
|
|
//
|
82 |
|
|
// I[3:0] MNEM Definition T[3:0] MA[m:0] Via Inh Operation
|
83 |
|
|
// 0000 RTS Return xxxx TOS[m:0] 00 0 PC<=MA;Pop
|
84 |
|
|
// 0001 BSR Call Subroutine xxxx BA[m:0] 00 1 PC<=MA;Push
|
85 |
|
|
// 0010 FTCH Next Instruction xxxx PC+1 00 0 PC<=MA[m:0]
|
86 |
|
|
// 0011 BMW Multi-way Branch xxxx {BA[m:3],MW[2:0]} 00 1 PC<=MA[m:0]
|
87 |
|
|
// 0100 BRV0 Branch Via 0 xxxx BA[m:0] 00 1 PC<=MA[m:0]
|
88 |
|
|
// 0101 BRV1 Branch Via 1 xxxx BA[m:0] 01 1 PC<=MA[m:0]
|
89 |
|
|
// 0110 BRV2 Branch Via 2 xxxx BA[m:0] 10 1 PC<=MA[m:0]
|
90 |
|
|
// 0111 BRV3 Branch Via 3 xxxx BA[m:0] 11 1 PC<=MA[m:0]
|
91 |
|
|
// 1000 BTH0 Branch T0 High xxx1 {T0?BA[m:0]:PC+1} 00 1 PC<=MA[m:0]
|
92 |
|
|
// 1001 BTH1 Branch T1 High xx1x {T1?BA[m:0]:PC+1} 00 1 PC<=MA[m:0]
|
93 |
|
|
// 1010 BTH2 Branch T2 High x1xx {T2?BA[m:0]:PC+1} 00 1 PC<=MA[m:0]
|
94 |
|
|
// 1011 BTH3 Branch T3 High 1xxx {T2?BA[m:0]:PC+1} 00 1 PC<=MA[m:0]
|
95 |
|
|
// 1100 BTL0 Branch T0 Low xxx0 {T0?PC+1:BA[m:0]} 00 1 PC<=MA[m:0]
|
96 |
|
|
// 1101 BTL1 Branch T1 Low xx0x {T1?PC+1:BA[m:0]} 00 1 PC<=MA[m:0]
|
97 |
|
|
// 1110 BTL2 Branch T2 Low x0xx {T2?PC+1:BA[m:0]} 00 1 PC<=MA[m:0]
|
98 |
|
|
// 1111 BTL3 Branch T3 Low 0xxx {T3?PC+1:BA[m:0]} 00 1 PC<=MA[m:0]
|
99 |
|
|
//
|
100 |
|
|
// Dependencies: none.
|
101 |
|
|
//
|
102 |
|
|
// Revision:
|
103 |
|
|
//
|
104 |
|
|
// 0.01 09J30 MAM File Created
|
105 |
|
|
//
|
106 |
|
|
// 1.00 10G10 MAM Stack Pop operation modified to load StkD register
|
107 |
|
|
// with 0 during subroutine returns. This will force
|
108 |
|
|
// the microprogram to restart at 0 if the stack is
|
109 |
|
|
// underflowed, or POPed, more the 4 times. Also made
|
110 |
|
|
// a change to the Stack Push operation so that Next
|
111 |
|
|
// is pushed instead of MA.
|
112 |
|
|
//
|
113 |
|
|
// 1.01 10G24 MAM Corrected typos in the instruction table.
|
114 |
|
|
//
|
115 |
|
|
// 1.02 10G25 MAM Removed Test Input Register, Strb input, and Inh
|
116 |
|
|
// output. External logic required to provide synchro-
|
117 |
|
|
// nized inputs for testing.
|
118 |
|
|
//
|
119 |
|
|
// 2.00 10H28 MAM Converted the BRV3 instruction into a conditional
|
120 |
|
|
// branch to subroutine instruction. In this way the
|
121 |
|
|
// BRV3, or CBSR, instruction can be used to take a
|
122 |
|
|
// branch to an interrupt subroutine. The conditional
|
123 |
|
|
// subroutine call is taken if T[3] is a logic 1. Like
|
124 |
|
|
// the BSR instruction, the address of the subroutine
|
125 |
|
|
// is provided by BA field.
|
126 |
|
|
//
|
127 |
|
|
// 2.10 11C05 Simplified return stack implementation. Removed
|
128 |
|
|
// unused code, but retained code commented out that
|
129 |
|
|
// reflects original implementation of BRV3 instruc-
|
130 |
|
|
// tion.
|
131 |
|
|
//
|
132 |
|
|
// 2.11 11C20 Removed CBSR modification
|
133 |
|
|
//
|
134 |
|
|
// 3.00 11C21 Changed module and added support for pipelined op-
|
135 |
|
|
// eration per the connections of the original F9408.
|
136 |
|
|
// Included an internal Reset FF stretcher to insure
|
137 |
|
|
// that an external registered PROM has time to fetch
|
138 |
|
|
// the first microprogram word. Removed the MA_Sel
|
139 |
|
|
// input because really should have been module reset.
|
140 |
|
|
// Without tying MA to 0 with the internal reset, the
|
141 |
|
|
// module in pipelined mode was not executing the same
|
142 |
|
|
// microprogram as non-pipelined mode module and that
|
143 |
|
|
// was unexpected. With these changes, the module per-
|
144 |
|
|
// forms identically to the original F9408 MPC.
|
145 |
|
|
//
|
146 |
|
|
// 4.00 12A29 MAM Changing the behavior of BRV0, BRV1, BRV2, and BMW
|
147 |
|
|
// so that they are all conditional on T0. If T0 is
|
148 |
|
|
// not asserted, these instructions will wait at the
|
149 |
|
|
// current location until T0 is asserted. Renamed the
|
150 |
|
|
// module from F9408A_MPC.v to MAM6502_MPC.v. Para-
|
151 |
|
|
// meterized the reset address.
|
152 |
|
|
//
|
153 |
|
|
// 4.10 12B03 MAM Restored the operation of the BRVx and BMW instruc-
|
154 |
|
|
// tions, but added two inputs to allow the module to
|
155 |
|
|
// respond to an external ready signal. In this manner
|
156 |
|
|
// the module will operate as a single or multi-cycle
|
157 |
|
|
// microprogram controller as determined by external
|
158 |
|
|
// logic, or the microprogram.
|
159 |
|
|
//
|
160 |
|
|
// 4.11 12B19 MAM Renamed module: MAM6502_MPC => M65C02_MPC.
|
161 |
|
|
//
|
162 |
|
|
// Additional Comments:
|
163 |
|
|
//
|
164 |
|
|
// Since this component is expected to be used in a fully synchronous design,
|
165 |
|
|
// the registering of the Test inputs with an external Strb signal and the Inh
|
166 |
|
|
// signal is not desirable since it puts another delay in the signal path. The
|
167 |
|
|
// effect will be to decrease the responsiveness of the system, and possibly
|
168 |
|
|
// require that the test inputs be stretched so that pulsed signals are not
|
169 |
|
|
// missed by the conditional tests in the microprogram. In the partially
|
170 |
|
|
// synchronous design environment in which the original F9408 was used, incor-
|
171 |
|
|
// porating a register internal to the device for the test inputs was very
|
172 |
|
|
// much a requirement to reduce the risk of metastable behaviour of the micro-
|
173 |
|
|
// program. To fully support the test inputs, the microprogram should include
|
174 |
|
|
// an explicit enable for the test input logic in order to control the chang-
|
175 |
|
|
// ing of the test inputs relative to the microroutines.
|
176 |
|
|
//
|
177 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
178 |
|
|
|
179 |
|
|
module M65C02_MPC #(
|
180 |
|
|
parameter pAddrWidth = 10, // Original F9408 => 10-bit Address
|
181 |
|
|
parameter pRst_Addrs = 0 // Reset Address
|
182 |
|
|
)(
|
183 |
|
|
input Rst, // Module Reset (Synchronous)
|
184 |
|
|
input Clk, // Module Clock
|
185 |
|
|
input [3:0] I, // Instruction (see description)
|
186 |
|
|
input [3:0] T, // Conditional Test Inputs
|
187 |
|
|
input [2:0] MW, // Multi-way Branch Address Select
|
188 |
|
|
input [(pAddrWidth-1):0] BA, // Microprogram Branch Address Field
|
189 |
|
|
output [1:0] Via, // Unconditional Branch Address Select
|
190 |
|
|
input En, // Enable Ready
|
191 |
|
|
input Rdy, // Ready
|
192 |
|
|
input PLS, // Pipeline Mode Select
|
193 |
|
|
output reg [(pAddrWidth-1):0] MA // Microprogram Address
|
194 |
|
|
);
|
195 |
|
|
|
196 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
197 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
198 |
|
|
//
|
199 |
|
|
// Local Parameters
|
200 |
|
|
//
|
201 |
|
|
|
202 |
|
|
localparam RTS = 0; // Return from Subroutine
|
203 |
|
|
localparam BSR = 1; // Branch to Subroutine
|
204 |
|
|
localparam FTCH = 2; // Fetch Next Instruction
|
205 |
|
|
localparam BMW = 3; // Multi-way Branch
|
206 |
|
|
localparam BRV0 = 4; // Branch Via External Branch Address Source #0
|
207 |
|
|
localparam BRV1 = 5; // Branch Via External Branch Address Source #1
|
208 |
|
|
localparam BRV2 = 6; // Branch Via External Branch Address Source #2
|
209 |
|
|
localparam BRV3 = 7; // Branch Via External Branch Address Source #3
|
210 |
|
|
localparam BTH0 = 8; // Branch if T[0] is Logic 1, else fetch next instr.
|
211 |
|
|
localparam BTH1 = 9; // Branch if T[1] is Logic 1, else fetch next instr.
|
212 |
|
|
localparam BTH2 = 10; // Branch if T[2] is Logic 1, else fetch next instr.
|
213 |
|
|
localparam BTH3 = 11; // Branch if T[3] is Logic 1, else fetch next instr.
|
214 |
|
|
localparam BTL0 = 12; // Branch if T[0] is Logic 0, else fetch next instr.
|
215 |
|
|
localparam BTL1 = 13; // Branch if T[1] is Logic 0, else fetch next instr.
|
216 |
|
|
localparam BTL2 = 14; // Branch if T[2] is Logic 0, else fetch next instr.
|
217 |
|
|
localparam BTL3 = 15; // Branch if T[3] is Logic 0, else fetch next instr.
|
218 |
|
|
|
219 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
220 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
221 |
|
|
//
|
222 |
|
|
// Declarations
|
223 |
|
|
//
|
224 |
|
|
|
225 |
|
|
wire [(pAddrWidth - 1):0] Next; // Output Program Counter Incrementer
|
226 |
|
|
reg [(pAddrWidth - 1):0] PC_In; // Input to Program Counter
|
227 |
|
|
reg [(pAddrWidth - 1):0] PC; // Program Counter
|
228 |
|
|
|
229 |
|
|
reg [(pAddrWidth - 1):0] A, B, C, D; // LIFO Stack Registers
|
230 |
|
|
|
231 |
|
|
reg dRst; // Reset stretcher
|
232 |
|
|
wire MPC_Rst; // Internal MPC Reset signal
|
233 |
|
|
|
234 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
235 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
236 |
|
|
//
|
237 |
|
|
// Implementation
|
238 |
|
|
//
|
239 |
|
|
|
240 |
|
|
always @(posedge Clk)
|
241 |
|
|
begin
|
242 |
|
|
if(Rst)
|
243 |
|
|
dRst <= #1 1;
|
244 |
|
|
else
|
245 |
|
|
dRst <= #1 0;
|
246 |
|
|
end
|
247 |
|
|
|
248 |
|
|
assign MPC_Rst = ((PLS) ? (Rst | dRst) : Rst);
|
249 |
|
|
|
250 |
|
|
// Implement 4-Level LIFO Stack
|
251 |
|
|
|
252 |
|
|
always @(posedge Clk)
|
253 |
|
|
begin
|
254 |
|
|
if(MPC_Rst)
|
255 |
|
|
{D, C, B, A} <= #1 0;
|
256 |
|
|
else if(I == BSR)
|
257 |
|
|
{D, C, B, A} <= #1 {C, B, A, Next};
|
258 |
|
|
else if(I == RTS)
|
259 |
|
|
{D, C, B, A} <= #1 {{pAddrWidth{1'b0}}, D, C, B};
|
260 |
|
|
end
|
261 |
|
|
|
262 |
|
|
// Program Counter Incrementer
|
263 |
|
|
|
264 |
|
|
assign Next = PC + 1;
|
265 |
|
|
|
266 |
|
|
// Generate Unconditional Branch Address Select
|
267 |
|
|
|
268 |
|
|
assign Via = {((I == BRV2) | (I == BRV3)), ((I == BRV3) | (I == BRV1))};
|
269 |
|
|
|
270 |
|
|
// Generate Program Counter Input Signal
|
271 |
|
|
|
272 |
|
|
always @(*)
|
273 |
|
|
begin
|
274 |
|
|
case({MPC_Rst, I})
|
275 |
|
|
RTS : PC_In <= A;
|
276 |
|
|
BSR : PC_In <= BA;
|
277 |
|
|
FTCH : PC_In <= Next;
|
278 |
|
|
BMW : PC_In <= {BA[(pAddrWidth - 1):3], MW};
|
279 |
|
|
//
|
280 |
|
|
BRV0 : PC_In <= BA;
|
281 |
|
|
BRV1 : PC_In <= BA;
|
282 |
|
|
BRV2 : PC_In <= BA;
|
283 |
|
|
BRV3 : PC_In <= BA;
|
284 |
|
|
//
|
285 |
|
|
BTH0 : PC_In <= (T[0] ? BA : Next);
|
286 |
|
|
BTH1 : PC_In <= (T[1] ? BA : Next);
|
287 |
|
|
BTH2 : PC_In <= (T[2] ? BA : Next);
|
288 |
|
|
BTH3 : PC_In <= (T[3] ? BA : Next);
|
289 |
|
|
//
|
290 |
|
|
BTL0 : PC_In <= (T[0] ? Next : BA );
|
291 |
|
|
BTL1 : PC_In <= (T[1] ? Next : BA );
|
292 |
|
|
BTL2 : PC_In <= (T[2] ? Next : BA );
|
293 |
|
|
BTL3 : PC_In <= (T[3] ? Next : BA );
|
294 |
|
|
default : PC_In <= pRst_Addrs;
|
295 |
|
|
endcase
|
296 |
|
|
end
|
297 |
|
|
|
298 |
|
|
// Generate Microprogram Address (Program Counter)
|
299 |
|
|
|
300 |
|
|
always @(posedge Clk)
|
301 |
|
|
begin
|
302 |
|
|
if(MPC_Rst)
|
303 |
|
|
PC <= #1 pRst_Addrs;
|
304 |
|
|
else
|
305 |
|
|
PC <= #1 ((En) ? ((Rdy) ? PC_In : PC) : PC_In);
|
306 |
|
|
end
|
307 |
|
|
|
308 |
|
|
// Assign Memory Address Bus
|
309 |
|
|
|
310 |
|
|
always @(*)
|
311 |
|
|
begin
|
312 |
|
|
MA <= ((PLS) ? ((En) ? ((Rdy) ? PC_In : PC) : PC_In) : PC);
|
313 |
|
|
end
|
314 |
|
|
|
315 |
|
|
endmodule
|