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

Subversion Repositories m65c02

[/] [m65c02/] [trunk/] [Src/] [RTL/] [M65C02_MPCv3.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 MichaelA
`timescale 1ns / 1ps
2
///////////////////////////////////////////////////////////////////////////////
3
//
4
//  Copyright 2009-2012 by Michael A. Morris, dba M. A. Morris & Associates
5
//
6
//  All rights reserved. The source code contained herein is publicly released
7
//  under the terms and conditions of the GNU Lesser Public License. No part of
8
//  this source code may be reproduced or transmitted in any form or by any
9
//  means, electronic or mechanical, including photocopying, recording, or any
10
//  information storage and retrieval system in violation of the license under
11
//  which the source code is released.
12
//
13
//  The source code contained herein is free; it may be redistributed and/or 
14
//  modified in accordance with the terms of the GNU Lesser General Public
15
//  License as published by the Free Software Foundation; either version 2.1 of
16
//  the GNU Lesser General Public License, or any later version.
17
//
18
//  The source code contained herein is freely released WITHOUT ANY WARRANTY;
19
//  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
20
//  PARTICULAR PURPOSE. (Refer to the GNU Lesser General Public License for
21
//  more details.)
22
//
23
//  A copy of the GNU Lesser General Public License should have been received
24
//  along with the source code contained herein; if not, a copy can be obtained
25
//  by writing to:
26
//
27
//  Free Software Foundation, Inc.
28
//  51 Franklin Street, Fifth Floor
29
//  Boston, MA  02110-1301 USA
30
//
31
//  Further, no use of this source code is permitted in any form or means
32
//  without inclusion of this banner prominently in any derived works. 
33
//
34
//  Michael A. Morris
35
//  Huntsville, AL
36
//
37
///////////////////////////////////////////////////////////////////////////////
38
 
39
`timescale 1ns / 1ps
40
 
41
///////////////////////////////////////////////////////////////////////////////
42
// Company:         M. A. Morris & Associates
43
// Engineer:        Michael A. Morris
44
// 
45
// Create Date:     12:02:40 10/28/2012 
46
// Design Name:     Microprogram Controller (Version 3)
47
// Module Name:     MPCv3.v
48
// Project Name:    C:\XProjects\VerilogComponents\MPCv3
49
// Target Devices:  Generic SRAM-based FPGA
50
// Tool versions:   Xilinx ISE 10.1i SP3
51
// 
52
// Description:
53
//
54
// This module implements a simple microprogram sequencer based on the Fair-
55
// child F9408. The sequencer provides:
56
//
57
//          (1) 4-bit instruction input
58
//          (2) four-level LIFO stack;
59
//          (3) program counter and incrementer;
60
//          (4) 4-bit registered test input;
61
//          (5) 8-way multi-way branch control input;
62
//          (6) branch address input;
63
//          (7) 4-way branch address select output;
64
//          (8) next address output.
65
//
66
// These elements provide a relatively flexible general purpose microprogram
67
// controller without a complex instruction set. The sixteen instructions can
68
// be categorized into three classes: (1) fetch, (2) unconditional branches,
69
// and (3) conditional branches. The fetch instruction class, a single instruc-
70
// tion class, simply increments the program counter and outputs the current
71
// value of the program counter on the next address bus. The unconditional 
72
// branch instruction class provides instructions to select the next instruc-
73
// tion using the Via[1:0] outputs and output that value on the next address
74
// bus and simultaneously load the program counter. The unconditional branch
75
// instruction class also provides for 8-way multiway branching using an exter-
76
// nal (priority) encoder/branch selector, and microprogram subroutine call and 
77
// return instructions.
78
//
79
// The instruction encodings of the F9408, as provided in "Principles of Firm-
80
// ware Engineering in Microprogram Control" by Michael Andrews. The instruc-
81
// tion set and operation map for the implementation is given below:
82
//
83
//  I[3:0] MNEM Definition       T[3:0]      MA[m:0]      Via Inh  Operation
84
//   0000  RTS  Return            xxxx      TOS[m:0]       00  0  PC<=MA;Pop
85
//   0001  BSR  Call Subroutine   xxxx       BA[m:0]       00  1  PC<=MA;Push
86
//   0010  FTCH Next Instruction  xxxx        PC+1         00  0  PC<=MA[m:0]
87
//   0011  BMW  Multi-way Branch  xxxx  {BA[m:3],MW[2:0]}  00  1  PC<=MA[m:0]
88
//   0100  BRV0 Branch Via 0      xxxx       BA[m:0]       00  1  PC<=MA[m:0]
89
//   0101  BRV1 Branch Via 1      xxxx       BA[m:0]       01  1  PC<=MA[m:0]
90
//   0110  BRV2 Branch Via 2      xxxx       BA[m:0]       10  1  PC<=MA[m:0]
91
//   0111  BRV3 Branch Via 3      xxxx       BA[m:0]       11  1  PC<=MA[m:0]
92
//   1000  BTH0 Branch T0 High    xxx1  {T0?BA[m:0]:PC+1}  00  1  PC<=MA[m:0]
93
//   1001  BTH1 Branch T1 High    xx1x  {T1?BA[m:0]:PC+1}  00  1  PC<=MA[m:0]
94
//   1010  BTH2 Branch T2 High    x1xx  {T2?BA[m:0]:PC+1}  00  1  PC<=MA[m:0]
95
//   1011  BTH3 Branch T3 High    1xxx  {T2?BA[m:0]:PC+1}  00  1  PC<=MA[m:0]
96
//   1100  BTL0 Branch T0 Low     xxx0  {T0?PC+1:BA[m:0]}  00  1  PC<=MA[m:0]
97
//   1101  BTL1 Branch T1 Low     xx0x  {T1?PC+1:BA[m:0]}  00  1  PC<=MA[m:0]
98
//   1110  BTL2 Branch T2 Low     x0xx  {T2?PC+1:BA[m:0]}  00  1  PC<=MA[m:0]
99
//   1111  BTL3 Branch T3 Low     0xxx  {T3?PC+1:BA[m:0]}  00  1  PC<=MA[m:0]
100
//
101
// Dependencies:    none.
102
//
103
// Revision: 
104
//
105
//  0.01    12J28   MAM     File Created
106
//
107
//  1.00    12K12   MAM     Modified MA multiplexer to either present next
108
//                          address or hold current address. This is required
109
//                          when the next microcycle has a length greater than
110
//                          one. To perform this adjustment/extension of the
111
//                          microcycle, two signals track the current and next
112
//                          microcycle length: CurLenZ, and NxtLenZ. Also, added
113
//                          register MPC_En to control the MPC registers and
114
//                          MA multiplexer. Removed non-pipelined mode control
115
//                          input because the typical usage of the MPC is with
116
//                          Block RAM, which will only work with the pipelined
117
//                          mode.
118
//
119
//  1.10    12K20   MAM     Changed reset for the microcycle length controller
120
//                          portion from MPC_Rst to Rst, which releases the
121
//                          microcycle length controller one cycle ahead of the
122
//                          MPC logic of the module. This is required to ensure
123
//                          that MPC_En and the microcycle length controller SM
124
//                          are properly conditioned before the start of micro-
125
//                          program execution. Removed the multiplexer on MA.
126
//                          The multiplexer was used to hold the address of the
127
//                          MPC when a delay cycle was required. It was put into
128
//                          implementation to correct an issue with BCD instruc-
129
//                          tions during testing with single cycle memory. The
130
//                          same issue reappeared when multi-cycle microcycles
131
//                          were tested. The issue was corrected by removing the
132
//                          MA multiplexer, and properly conditioning the PSW,
133
//                          interrupt handler update and the microprogram ROMs
134
//                          with the Rdy signal. The original fix, adding the MA
135
//                          multiplexer, fixed the issue because the PSW ISR
136
//                          update logic and microprogram ROMs were not condi-
137
//                          tioned with Rdy. The multiplexer added a microcycle
138
//                          delay which couldn't be sustained for multi-cycle
139
//                          microcycles; the required microprogram address delay
140
//                          could only be sustained for one cycle without adding
141
//                          the enable, i.e. Rdy, to the microprogram ROM.
142
//
143
// Additional Comments: 
144
//
145
//  The Version 3 Microprogram Controller (MPCv3) is based on the Fairchild
146
//  F9408 MPC. It extends that microprogram controller by incorporating a micro-
147
//  cycle controller directly into the module, a al Am2925, which allows each
148
//  microcycle to be controlled by a field in the microprogram, or by external
149
//  logic.
150
//
151
//  The purpose of these extensions is to allow easy implementation of a varia-
152
//  ble length microprogram cycle, i.e. microcycle. In turn, this simplifies the
153
//  implementation of microprogrammed state machines which interface to synchro-
154
//  nous memories found in most FPGAs, or to external synchronous/asynchronous
155
//  memories.
156
//
157
//  When a microprogrammed state machine interfaces to a synchronous memory,
158
//  there is a one cycle delay between the presentation of the address and the
159
//  output of the data at that address. In many instances, the microprogram is
160
//  unable to perform any useful work during the first cycle. Thus, the micro-
161
//  program must perform an explicit delay operation, which generally requires
162
//  a state to be added to every read of these memories. If there are a signifi-
163
//  cant number of these read operations in the microprogram, then there is an
164
//  opportunity for the microprogram to be incorrectly programmed when one or
165
//  more of the delay cycles are not included in the microprogram. Isolating
166
//  the resulting fault in the state machine may be difficult.
167
//
168
//  To avoid errors of this type, microcycles which read from or write to 
169
//  devices, such as memories, can be automatically extended explicitly by a
170
//  microprogram field or logic. Using this type of facility reduces the number
171
//  of states required to interface a microprogrammed state machine to these
172
//  types of devices. It also makes the microprogram less tedious to develop and
173
//  improves overall productivity, which is a prime reason for choosing a micro-
174
//  programmed approach for developing complex state machines.
175
//
176
//  The objective of the embedded microcyle length controller is not to incor-
177
//  porate the full functionality of the Am2925 Microcycle Controller. Instead,
178
//  it is to add a simple microcycle length control function which can be used
179
//  to simplify the microprogram and provide a easy mechanism for interfacing
180
//  the microprogrammed state machine to devices which require more than one
181
//  clock cycle to access. The embedded microcycle length controller included in
182
//  this module allows the microcycle length of the F9408 to be set to 1 , 2,
183
//  or 4 cycles. When extended to 2 cycles, the cycle cannot be extended using
184
//  an external wait state request. When extended to 4 cycles, an external wait
185
//  state generator can be used to add any number of wait states to the micro-
186
//  cycle of the F9408.
187
//
188
///////////////////////////////////////////////////////////////////////////////
189
 
190
module M65C02_MPCv3 #(
191
    parameter pAddrWidth = 10,          // Original F9408 => 10-bit Address
192
    parameter pRst_Addrs = 0            // Reset Address
193
)(
194
    input   Rst,                        // Module Reset (Synchronous)
195
    input   Clk,                        // Module Clock
196
 
197
    input   [1:0] uLen,                 // Microcycle Length Select
198
    input   Wait,                       // Microcycle Wait State Request Input
199
 
200
    output  reg [1:0] MC,               // Microcycle State outputs
201
 
202
    input   [3:0] I,                    // Instruction (see description)
203
    input   [3:0] T,                    // Conditional Test Inputs
204
    input   [2:0] MW,                   // Multi-way Branch Address Select
205
    input   [(pAddrWidth-1):0] BA,      // Microprogram Branch Address Field
206
    output  [1:0] Via,                  // Unconditional Branch Address Select
207
 
208
 
209
    output  reg [(pAddrWidth-1):0] MA   // Microprogram Address
210
);
211
 
212
///////////////////////////////////////////////////////////////////////////////
213
///////////////////////////////////////////////////////////////////////////////
214
//
215
//  Local Parameters
216
//
217
 
218
localparam pRTS  =  0;  // Return from Subroutine
219
localparam pBSR  =  1;  // Branch to Subroutine
220
localparam pFTCH =  2;  // Fetch Next Instruction
221
localparam pBMW  =  3;  // Multi-way Branch
222
localparam pBRV0 =  4;  // Branch Via External Branch Address Source #0
223
localparam pBRV1 =  5;  // Branch Via External Branch Address Source #1
224
localparam pBRV2 =  6;  // Branch Via External Branch Address Source #2
225
localparam pBRV3 =  7;  // Branch Via External Branch Address Source #3
226
localparam pBTH0 =  8;  // Branch if T[0] is Logic 1, else fetch next instr.
227
localparam pBTH1 =  9;  // Branch if T[1] is Logic 1, else fetch next instr.
228
localparam pBTH2 = 10;  // Branch if T[2] is Logic 1, else fetch next instr.
229
localparam pBTH3 = 11;  // Branch if T[3] is Logic 1, else fetch next instr.
230
localparam pBTL0 = 12;  // Branch if T[0] is Logic 0, else fetch next instr.
231
localparam pBTL1 = 13;  // Branch if T[1] is Logic 0, else fetch next instr.
232
localparam pBTL2 = 14;  // Branch if T[2] is Logic 0, else fetch next instr.
233
localparam pBTL3 = 15;  // Branch if T[3] is Logic 0, else fetch next instr.
234
 
235
///////////////////////////////////////////////////////////////////////////////
236
///////////////////////////////////////////////////////////////////////////////
237
//
238
//  Declarations
239
//
240
 
241
wire    NxtLenZ;                          // Next microcycle length is Z
242
reg     MPC_En;                           // MPC register enable
243
 
244
wire    [(pAddrWidth - 1):0] Next;        // Output Program Counter Incrementer
245
reg     [(pAddrWidth - 1):0] PC_In;       // Input to Program Counter
246
reg     [(pAddrWidth - 1):0] PC;          // Program Counter
247
 
248
//reg     [(pAddrWidth - 1):0] A, B, C, D;  // LIFO Stack Registers
249
reg     [(pAddrWidth - 1):0] A;           // LIFO Stack Registers
250
 
251
reg     dRst;                             // Reset stretcher
252
wire    MPC_Rst;                          // Internal MPC Reset signal
253
 
254
///////////////////////////////////////////////////////////////////////////////
255
///////////////////////////////////////////////////////////////////////////////
256
//
257
//  Implementation
258
//
259
 
260
//  Implement module reset generator
261
 
262
always @(posedge Clk)
263
begin
264
    if(Rst)
265
        dRst <= #1 1;
266
    else
267
        dRst <= #1 0;
268
end
269
 
270
assign MPC_Rst = (Rst | dRst);
271
 
272
//
273
//  Embedded Microcycle Length Controller
274
//
275
//  Three microcycles are implemented: 1, 2, or 4 clock in length. If word 0 of
276
//  the microprogram, or external logic, sets a different length during reset,
277
//  the microcycle length controller will exit reset in either state 0 or
278
//  state 2. If it exits reset in state 0, a single clock microcycle will be
279
//  performed after reset. If it exits reset in state 2, either a 2 cycle or
280
//  a 4 cycle microcycle will be performed after reset. The microcycle length is
281
//  sampled in state 0. This allows either the microprogram or external logic to
282
//  control the length of each microcycle that the MPCv3 performs.
283
 
284
always @(posedge Clk)
285
begin
286
    if(Rst)
287
        MC <= #1 ((|uLen) ? 2 : 0);
288
    else
289
        case(MC)
290
            2 : MC <= #1 ((uLen[1]) ? 3 : 0);   // First cycle of microcycle
291
            3 : MC <= #1 ((Wait)    ? 3 : 1);   // 2nd of 4 cycle microcycle
292
            1 : MC <= #1 ((Wait)    ? 1 : 0);   // 3rd of 4 cycle microcycle
293
 
294
        endcase
295
end
296
 
297
//  Assign next microcycle length
298
 
299
assign NxtLenZ = (uLen == 0);
300
 
301
//  Determine the MPC Enable signal
302
 
303
always @(posedge Clk)
304
begin
305
    if(Rst)
306
        MPC_En <= #1 ~|uLen;
307
    else
308
        case(MC)
309
            2 : MPC_En <= #1 ((uLen[1]) ? 0 : 1);
310
            3 : MPC_En <= #1 0;
311
            1 : MPC_En <= #1 ~Wait;
312
 
313
        endcase
314
end
315
 
316
////  Implement 4-Level LIFO Stack
317
//
318
//always @(posedge Clk)
319
//begin
320
//    if(MPC_Rst)
321
//        {A, B, C, D} <= #1 0;
322
//    else if(MPC_En)
323
//        if(I == BSR)
324
//            {A, B, C, D} <= #1 {Next, A, B, C};
325
//        else if(I == RTS)
326
//            {A, B, C, D} <= #1 {B, C, D, {pAddrWidth{1'b0}}};
327
//end
328
 
329
//  Implement 1-Level LIFO Stack
330
 
331
always @(posedge Clk)
332
begin
333
    if(MPC_Rst)
334
        A <= #1 0;
335
    else if(MPC_En)
336
        if(I == pBSR)
337
            A <= #1 Next;
338
        else if(I == pRTS)
339
            A <= #1 {pAddrWidth{1'b0}};
340
end
341
 
342
//  Program Counter Incrementer
343
 
344
assign Next = PC + 1;
345
 
346
//  Generate Unconditional Branch Address Select
347
 
348
assign Via = {((I == pBRV2) | (I == pBRV3)), ((I == pBRV3) | (I == pBRV1))};
349
 
350
//  Generate Program Counter Input Signal
351
 
352
always @(*)
353
begin
354
    case({MPC_Rst, I})
355
        pRTS    : PC_In <=  A;
356
        pBSR    : PC_In <=  BA;
357
        pFTCH   : PC_In <=  Next;
358
        pBMW    : PC_In <=  {BA[(pAddrWidth - 1):3], MW};
359
        //
360
        pBRV0   : PC_In <=  BA;
361
        pBRV1   : PC_In <=  BA;
362
        pBRV2   : PC_In <=  BA;
363
        pBRV3   : PC_In <=  BA;
364
        //
365
        pBTH0   : PC_In <=  (T[0] ? BA   : Next);
366
        pBTH1   : PC_In <=  (T[1] ? BA   : Next);
367
        pBTH2   : PC_In <=  (T[2] ? BA   : Next);
368
        pBTH3   : PC_In <=  (T[3] ? BA   : Next);
369
        //
370
        pBTL0   : PC_In <=  (T[0] ? Next : BA  );
371
        pBTL1   : PC_In <=  (T[1] ? Next : BA  );
372
        pBTL2   : PC_In <=  (T[2] ? Next : BA  );
373
        pBTL3   : PC_In <=  (T[3] ? Next : BA  );
374
        default : PC_In <=  pRst_Addrs;
375
    endcase
376
end
377
 
378
//  Generate Microprogram Address (Program Counter)
379
 
380
always @(posedge Clk)
381
begin
382
    if(MPC_Rst)
383
        PC <= #1 pRst_Addrs;
384
    else if(MPC_En)
385
        PC <= #1 PC_In;
386
end
387
 
388
//  Assign Memory Address Bus
389
 
390
always @(*)
391
begin
392
    MA <= PC_In;
393
end
394
 
395
endmodule

powered by: WebSVN 2.1.0

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