1 |
2 |
MichaelA |
////////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
//
|
3 |
|
|
// Copyright 2009-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: 08:02:40 03/01/2013
|
45 |
|
|
// Design Name: Microprogram Controller (Version 4)
|
46 |
|
|
// Module Name: MPCv4.v
|
47 |
|
|
// Project Name: C:\XProjects\VerilogComponents\MPCv4
|
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, consisting of a
|
69 |
|
|
// single instruction class, simply increments the program counter and outputs
|
70 |
|
|
// the current value of the program counter on the next address bus. The uncon-
|
71 |
|
|
// ditional branch instruction class provides instructions to select the next
|
72 |
|
|
// instruction using the Via[1:0] outputs and output that value on the next
|
73 |
|
|
// address bus and simultaneously load the program counter. The unconditional
|
74 |
|
|
// branch instruction class also provides for 8-way multiway branching using an
|
75 |
|
|
// external (priority) encoder/branch selector, and microprogram subroutine call
|
76 |
|
|
// and 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 12J28 MAM File Created
|
105 |
|
|
//
|
106 |
|
|
// 1.00 12K12 MAM Modified MA multiplexer to either present next
|
107 |
|
|
// address or hold current address. This is required
|
108 |
|
|
// when the next microcycle has a length greater than
|
109 |
|
|
// one. To perform this adjustment/extension of the
|
110 |
|
|
// microcycle, two signals track the current and next
|
111 |
|
|
// microcycle length: CurLenZ, and NxtLenZ. Also, added
|
112 |
|
|
// register MPC_En to control the MPC registers and
|
113 |
|
|
// MA multiplexer. Removed non-pipelined mode control
|
114 |
|
|
// input because the typical usage of the MPC is with
|
115 |
|
|
// Block RAM, which will only work with the pipelined
|
116 |
|
|
// mode.
|
117 |
|
|
//
|
118 |
|
|
// 1.10 12K20 MAM Changed reset for the microcycle length controller
|
119 |
|
|
// portion from MPC_Rst to Rst, which releases the
|
120 |
|
|
// microcycle length controller one cycle ahead of the
|
121 |
|
|
// MPC logic of the module. This is required to ensure
|
122 |
|
|
// that MPC_En and the microcycle length controller SM
|
123 |
|
|
// are properly conditioned before the start of micro-
|
124 |
|
|
// program execution. Removed the multiplexer on MA.
|
125 |
|
|
// The multiplexer was used to hold the address of the
|
126 |
|
|
// MPC when a delay cycle was required. It was put into
|
127 |
|
|
// implementation to correct an issue with BCD instruc-
|
128 |
|
|
// tions during testing with single cycle memory. The
|
129 |
|
|
// same issue reappeared when multi-cycle microcycles
|
130 |
|
|
// were tested. The issue was corrected by removing the
|
131 |
|
|
// MA multiplexer, and properly conditioning the PSW,
|
132 |
|
|
// interrupt handler update and the microprogram ROMs
|
133 |
|
|
// with the Rdy signal. The original fix, adding the MA
|
134 |
|
|
// multiplexer, fixed the issue because the PSW ISR
|
135 |
|
|
// update logic and microprogram ROMs were not condi-
|
136 |
|
|
// tioned with Rdy. The multiplexer added a microcycle
|
137 |
|
|
// delay which couldn't be sustained for multi-cycle
|
138 |
|
|
// microcycles; the required microprogram address delay
|
139 |
|
|
// could only be sustained for one cycle without adding
|
140 |
|
|
// the enable, i.e. Rdy, to the microprogram ROM.
|
141 |
|
|
//
|
142 |
|
|
// 1.20 13C01 MAM Changed microcycle length controller to fixed length
|
143 |
|
|
// controller of 4 clocks per microcycle. However, add-
|
144 |
|
|
// ed two states to support synchronous wait state in-
|
145 |
|
|
// sertion. If Rdy not asserted during C3 (MC==1), then
|
146 |
|
|
// a wait state of 4 clock cycles is added by inserting
|
147 |
|
|
// two states which return to C2 (MC==3). In these two
|
148 |
|
|
// new cycles, Phi1O should be asserted, and then when
|
149 |
|
|
// the cycle returns to C2 and C3 again, Phi2O is re-
|
150 |
|
|
// asserted high. If on C3, Rdy is not asserted, the
|
151 |
|
|
// wait state cycles resume. If on C3, Rdy is asserted,
|
152 |
|
|
// the the memory cycle terminates, input data is cap-
|
153 |
|
|
// tured, and the microcyle moves to C4 to complete.
|
154 |
|
|
//
|
155 |
|
|
// Additional Comments:
|
156 |
|
|
//
|
157 |
|
|
// The Version 4 Microprogram Controller (MPCv4) is based on the Fairchild
|
158 |
|
|
// F9408 MPC. It extends that microprogram controller by incorporating a micro-
|
159 |
|
|
// cycle controller and wait state generator directly into the module. The
|
160 |
|
|
// microcycle controller sets the length of the microcycle to 4 clock cycles.
|
161 |
|
|
// Although the MPC is able to execute a microprogram in single cycle mode, the
|
162 |
|
|
// version 4 MPC is intended to ease the implementation of processors which use
|
163 |
|
|
// an external memory interface. A four cycle microcycle is about as short an
|
164 |
|
|
// external memory cycle can be implemented to allow reasonably priced devices
|
165 |
|
|
// to be used.
|
166 |
|
|
//
|
167 |
|
|
// The wait state generator function has been built into the microcycle length
|
168 |
|
|
// controller. The typical 4 cycle microcycle will expect that external memory
|
169 |
|
|
// has completed the requested read or write cycle at the end of cycle 3. The
|
170 |
|
|
// expectation is that the address, data, and control signals (A, DB, nOE, and
|
171 |
|
|
// nWr) are asserted as required during cycle 2. The remainder of cycle 2, and
|
172 |
|
|
// cycle 3 are used to read or write external memory. The bus control signals
|
173 |
|
|
// will be deasserted, along with the data bus if a write operation is being
|
174 |
|
|
// performed, at the end of cycle 3/start of cycle 4. This means that read data
|
175 |
|
|
// from memory is registered at the start of cycle 4.
|
176 |
|
|
//
|
177 |
|
|
// If the external address decode logic, after decoding the address, determines
|
178 |
|
|
// that a delay is required, then it must assert the Wait request such that the
|
179 |
|
|
// microcycle controller detects it as asserted at the end of cycle 3 Istart of
|
180 |
|
|
// cycle 4). If Wait is asserted in cycle 3, then the microcycle controller in-
|
181 |
|
|
// serts a 4 cycle wait state cycle. The Wait signal is resampled during the
|
182 |
|
|
// 3rd wait state cycle, and if not asserted, the normal microcycle continues.
|
183 |
|
|
// Otherwise, another 4 cycle wait state is inserted, and this process conti-
|
184 |
|
|
// nues until Wait is not asserted during the 3rd cycle of the wait state se-
|
185 |
|
|
// quence.
|
186 |
|
|
//
|
187 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
188 |
|
|
|
189 |
|
|
module M65C02_MPCv4 #(
|
190 |
|
|
parameter pAddrWidth = 10, // Original F9408 => 10-bit Address
|
191 |
|
|
parameter pRst_Addrs = 0 // Reset Address
|
192 |
|
|
)(
|
193 |
|
|
input Rst, // Module Reset (Synchronous)
|
194 |
|
|
input Clk, // Module Clock
|
195 |
|
|
|
196 |
|
|
input Wait, // Microcycle Wait State Request Input
|
197 |
|
|
|
198 |
|
|
output reg [2:0] MC, // Microcycle State outputs
|
199 |
|
|
|
200 |
|
|
input [3:0] I, // Instruction (see description)
|
201 |
|
|
input [3:0] T, // Conditional Test Inputs
|
202 |
|
|
input [2:0] MW, // Multi-way Branch Address Select
|
203 |
|
|
input [(pAddrWidth-1):0] BA, // Microprogram Branch Address Field
|
204 |
|
|
output [1:0] Via, // Unconditional Branch Address Select
|
205 |
|
|
|
206 |
|
|
|
207 |
|
|
output [(pAddrWidth-1):0] MA // Microprogram Address
|
208 |
|
|
);
|
209 |
|
|
|
210 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
211 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
212 |
|
|
//
|
213 |
|
|
// Local Parameters
|
214 |
|
|
//
|
215 |
|
|
|
216 |
|
|
localparam pRTS = 0; // Return from Subroutine
|
217 |
|
|
localparam pBSR = 1; // Branch to Subroutine
|
218 |
|
|
localparam pFTCH = 2; // Fetch Next Instruction
|
219 |
|
|
localparam pBMW = 3; // Multi-way Branch
|
220 |
|
|
localparam pBRV0 = 4; // Branch Via External Branch Address Source #0
|
221 |
|
|
localparam pBRV1 = 5; // Branch Via External Branch Address Source #1
|
222 |
|
|
localparam pBRV2 = 6; // Branch Via External Branch Address Source #2
|
223 |
|
|
localparam pBRV3 = 7; // Branch Via External Branch Address Source #3
|
224 |
|
|
localparam pBTH0 = 8; // Branch if T[0] is Logic 1, else fetch next instr.
|
225 |
|
|
localparam pBTH1 = 9; // Branch if T[1] is Logic 1, else fetch next instr.
|
226 |
|
|
localparam pBTH2 = 10; // Branch if T[2] is Logic 1, else fetch next instr.
|
227 |
|
|
localparam pBTH3 = 11; // Branch if T[3] is Logic 1, else fetch next instr.
|
228 |
|
|
localparam pBTL0 = 12; // Branch if T[0] is Logic 0, else fetch next instr.
|
229 |
|
|
localparam pBTL1 = 13; // Branch if T[1] is Logic 0, else fetch next instr.
|
230 |
|
|
localparam pBTL2 = 14; // Branch if T[2] is Logic 0, else fetch next instr.
|
231 |
|
|
localparam pBTL3 = 15; // Branch if T[3] is Logic 0, else fetch next instr.
|
232 |
|
|
|
233 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
234 |
|
|
///////////////////////////////////////////////////////////////////////////////
|
235 |
|
|
//
|
236 |
|
|
// Declarations
|
237 |
|
|
//
|
238 |
|
|
|
239 |
|
|
reg MPC_En; // MPC register enable
|
240 |
|
|
|
241 |
|
|
wire [(pAddrWidth - 1):0] Next; // Output Program Counter Increm.
|
242 |
|
|
reg [(pAddrWidth - 1):0] PC_In; // Input to Program Counter
|
243 |
|
|
reg [(pAddrWidth - 1):0] PC; // Program Counter
|
244 |
|
|
|
245 |
|
|
//reg [(pAddrWidth - 1):0] A, B, C, D; // LIFO Stack Registers
|
246 |
|
|
reg [(pAddrWidth - 1):0] A; // LIFO Stack Registers
|
247 |
|
|
|
248 |
|
|
reg dRst; // Reset stretcher
|
249 |
|
|
wire MPC_Rst; // Internal MPC Reset signal
|
250 |
|
|
|
251 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
252 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
253 |
|
|
//
|
254 |
|
|
// Implementation
|
255 |
|
|
//
|
256 |
|
|
|
257 |
|
|
// Implement module reset generator
|
258 |
|
|
|
259 |
|
|
always @(posedge Clk)
|
260 |
|
|
begin
|
261 |
|
|
if(Rst)
|
262 |
|
|
dRst <= #1 1;
|
263 |
|
|
else
|
264 |
|
|
dRst <= #1 0;
|
265 |
|
|
end
|
266 |
|
|
|
267 |
|
|
assign MPC_Rst = (Rst | dRst);
|
268 |
|
|
|
269 |
|
|
//
|
270 |
|
|
// Embedded Microcycle Controller and Wait State Generator
|
271 |
|
|
//
|
272 |
|
|
// The microcycle length is fixed to 4 clock cycles in length when Wait is not
|
273 |
|
|
// asserted in C3. If Wait is asserted in C3, then a 4 cycle wait sequence is
|
274 |
|
|
// inserted. This behavior allows external logic to extend the microcycle
|
275 |
|
|
// length in multiples of 4 clock cycles.
|
276 |
|
|
|
277 |
|
|
always @(posedge Clk)
|
278 |
|
|
begin
|
279 |
|
|
if(Rst)
|
280 |
|
|
MC <= #1 6;
|
281 |
|
|
else
|
282 |
|
|
case(MC)
|
283 |
|
|
// Normal Operation
|
284 |
|
|
4 : MC <= #1 6; // 4th cycle of microcycle (Phi1O)
|
285 |
|
|
6 : MC <= #1 7; // 1st cycle of microcycle (Phi1O)
|
286 |
|
|
7 : MC <= #1 5; // 2nd cycle of microcycle (Phi2O)
|
287 |
|
|
5 : MC <= #1 ((Wait) ? 0 : 4); // 3rd cycle of microcycle (Phi2O)
|
288 |
|
|
// Wait State Operation
|
289 |
|
|
|
290 |
|
|
2 : MC <= #1 3; // 1st cycle of microcycle (Phi1O)
|
291 |
|
|
3 : MC <= #1 1; // 2nd cycle of microcycle (Phi2O)
|
292 |
|
|
1 : MC <= #1 ((Wait) ? 0 : 4); // 3rd cycle of microcycle (Phi2O)
|
293 |
|
|
endcase
|
294 |
|
|
end
|
295 |
|
|
|
296 |
|
|
// Determine the MPC Enable signal
|
297 |
|
|
|
298 |
|
|
always @(posedge Clk) MPC_En <= #1 ((Rst) ? 0 : (~Wait & (MC[1:0] == 1)));
|
299 |
|
|
|
300 |
|
|
//// Implement 4-Level LIFO Stack
|
301 |
|
|
//
|
302 |
|
|
//always @(posedge Clk)
|
303 |
|
|
//begin
|
304 |
|
|
// if(MPC_Rst)
|
305 |
|
|
// {A, B, C, D} <= #1 0;
|
306 |
|
|
// else if(MPC_En)
|
307 |
|
|
// if(I == BSR)
|
308 |
|
|
// {A, B, C, D} <= #1 {Next, A, B, C};
|
309 |
|
|
// else if(I == RTS)
|
310 |
|
|
// {A, B, C, D} <= #1 {B, C, D, {pAddrWidth{1'b0}}};
|
311 |
|
|
//end
|
312 |
|
|
|
313 |
|
|
// Implement 1-Level LIFO Stack
|
314 |
|
|
|
315 |
|
|
always @(posedge Clk)
|
316 |
|
|
begin
|
317 |
|
|
if(MPC_Rst)
|
318 |
|
|
A <= #1 0;
|
319 |
|
|
else if(MPC_En)
|
320 |
|
|
if(I == pBSR)
|
321 |
|
|
A <= #1 Next;
|
322 |
|
|
else if(I == pRTS)
|
323 |
|
|
A <= #1 {pAddrWidth{1'b0}};
|
324 |
|
|
end
|
325 |
|
|
|
326 |
|
|
// Program Counter Incrementer
|
327 |
|
|
|
328 |
|
|
assign Next = PC + 1;
|
329 |
|
|
|
330 |
|
|
// Generate Unconditional Branch Address Select
|
331 |
|
|
|
332 |
|
|
assign Via = {((I == pBRV2) | (I == pBRV3)), ((I == pBRV3) | (I == pBRV1))};
|
333 |
|
|
|
334 |
|
|
// Generate Program Counter Input Signal
|
335 |
|
|
|
336 |
|
|
always @(*)
|
337 |
|
|
begin
|
338 |
|
|
case({MPC_Rst, I})
|
339 |
|
|
pRTS : PC_In <= A;
|
340 |
|
|
pBSR : PC_In <= BA;
|
341 |
|
|
pFTCH : PC_In <= Next;
|
342 |
|
|
pBMW : PC_In <= {BA[(pAddrWidth - 1):3], MW};
|
343 |
|
|
//
|
344 |
|
|
pBRV0 : PC_In <= BA;
|
345 |
|
|
pBRV1 : PC_In <= BA;
|
346 |
|
|
pBRV2 : PC_In <= BA;
|
347 |
|
|
pBRV3 : PC_In <= BA;
|
348 |
|
|
//
|
349 |
|
|
pBTH0 : PC_In <= (T[0] ? BA : Next);
|
350 |
|
|
pBTH1 : PC_In <= (T[1] ? BA : Next);
|
351 |
|
|
pBTH2 : PC_In <= (T[2] ? BA : Next);
|
352 |
|
|
pBTH3 : PC_In <= (T[3] ? BA : Next);
|
353 |
|
|
//
|
354 |
|
|
pBTL0 : PC_In <= (T[0] ? Next : BA );
|
355 |
|
|
pBTL1 : PC_In <= (T[1] ? Next : BA );
|
356 |
|
|
pBTL2 : PC_In <= (T[2] ? Next : BA );
|
357 |
|
|
pBTL3 : PC_In <= (T[3] ? Next : BA );
|
358 |
|
|
default : PC_In <= pRst_Addrs;
|
359 |
|
|
endcase
|
360 |
|
|
end
|
361 |
|
|
|
362 |
|
|
// Generate Microprogram Address (Program Counter)
|
363 |
|
|
|
364 |
|
|
always @(posedge Clk)
|
365 |
|
|
begin
|
366 |
|
|
if(MPC_Rst)
|
367 |
|
|
PC <= #1 pRst_Addrs;
|
368 |
|
|
else if(MPC_En)
|
369 |
|
|
PC <= #1 PC_In;
|
370 |
|
|
end
|
371 |
|
|
|
372 |
|
|
// Assign Memory Address Bus
|
373 |
|
|
|
374 |
|
|
assign MA = PC_In;
|
375 |
|
|
|
376 |
|
|
endmodule
|