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

Subversion Repositories m16c5x

[/] [m16c5x/] [trunk/] [RTL/] [Src/] [P16C5x_ALU.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 MichaelA
////////////////////////////////////////////////////////////////////////////////
2
//
3
//  Copyright 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:     14:53:13 06/15/2013 
45
// Design Name:     P16C5x-compatible Synthesizable Processor Core
46
// Module Name:     P16C5x_ALU 
47
// Project Name:    C:\XProjects\ISE10.1i\M16C5x 
48
// Target Devices:  RAM-based FPGAs: XC3S50A-xVQ100, XC3S200A-xVQ100 
49
// Tool versions:   Xilinx ISE 10.1i SP3
50
//
51
// Description:
52
//
53
//  Module implements the ALU of the P16C5x synthesizable processor core. It has
54
//  been taken out of the PIC16C5x synthesizable processor core and made into a 
55
//  separate module. No changes have been made to the ALU code in the process.
56
//
57
// Dependencies: 
58
//
59
// Revision:
60
// 
61
//  1.00    13F15   MAM     Original file creation date.
62
//
63
//  1.10    13F23   MAM     Changed order of ALU_Op[10] and ALU_Op[9]. Now the
64
//                          modules uses ALU_Op[9:0] internally instead of 
65
//                          {ALU_Op[10], ALU_Op[8:0]} as originally constructed.
66
//
67
//  1.20    13J19   MAM     Changed Write Enable/Clock Enable logic to remove
68
//                          multiplexers and make better use of the built-in
69
//                          functionality of the logic blocks in the FPGA.
70
//
71
//  1.30    13J20   MAM     Removed the internal bit mask ROM, and added an bit
72
//                          mask input port. Reconfigured Bit Unit to use the
73
//                          bit mask input port.
74
// 
75
// Additional Comments:
76
//
77
//  The ALU data output, DO, has been registered to support a higher operating
78
//  speed when a multi-cycle instruction cycle is used. Parameterization of this
79
//  may be added in the future, but the current module must be edited to remove
80
//  the DO register and the un-registered multiplexer, which has been commented
81
//  out, added back in when single cycle operation is desired.
82
//
83
////////////////////////////////////////////////////////////////////////////////
84
 
85
module P16C5x_ALU (
86
    input   Rst,
87
    input   Clk,
88
    input   CE,
89
 
90
    input   [9:0] ALU_Op,               // ALU Control Word
91
    input   WE_PSW,                     // Write Enable for {Z, DC, C} from DI
92
 
93
    input   [7:0] DI,                   // Data Input
94
    input   [7:0] KI,                   // Literal Input
95
    input   [7:0] Msk,                  // Bit Mask Input
96
 
97
    output  reg [7:0] DO,               // ALU Output
98
    output  Z_Tst,                      // ALU Zero Test Output
99
    output  g,                          // Bit Test Condition
100
 
101
    output  reg [7:0] W,                // Working Register 
102
 
103
    output  reg Z,                      // Z(ero) ALU Status Output
104
    output  reg DC,                     // Digit Carry ALU Status Output
105
    output  reg C                       // Carry Flag ALU Status Output
106
);
107
 
108
////////////////////////////////////////////////////////////////////////////////
109
//
110
//  Declarations
111
//
112
 
113
wire    [7:0] A, B, Y;
114
 
115
wire    [7:0] X;
116
wire    C3, C7;
117
 
118
wire    [1:0] LU_Op;
119
reg     [7:0] V;
120
 
121
wire    [1:0] S_Sel;
122
reg     [7:0] S;
123
 
124
wire    [7:0] U;
125
wire    [7:0] T;
126
 
127
wire    [1:0] D_Sel;
128
 
129
////////////////////////////////////////////////////////////////////////////////
130
//
131
//  ALU Implementation - ALU[3:0] are overloaded for the four ALU elements:
132
//                          Arithmetic Unit, Logic Unit, Shift Unit, and Bit
133
//                          Processor.
134
//
135
//  ALU Operations - Arithmetic, Logic, and Shift Units
136
//
137
//  ALU_Op[1:0] = ALU Unit Operation Code
138
//
139
//      Arithmetic Unit (AU): 00 => Y = A +  B;
140
//                            01 => Y = A +  B + 1;
141
//                            10 => Y = A + ~B     = A - B - 1;
142
//                            11 => Y = A + ~B + 1 = A - B;
143
//
144
//      Logic Unit (LU):      00 => V = ~A;
145
//                            01 => V =  A & B;
146
//                            10 => V =  A | B;
147
//                            11 => V =  A ^ B;
148
//
149
//      Shift Unit (SU):      00 => S = W;                // MOVWF
150
//                            01 => S = {A[3:0], A[7:4]}; // SWAPF
151
//                            10 => S = {C, A[7:1]};      // RRF
152
//                            11 => S = {A[6:0], C};      // RLF
153
//
154
//  ALU_Op[3:2] = ALU Operand:
155
//                  A      B
156
//          00 =>  File    0
157
//          01 =>  File    W
158
//          10 => Literal  0
159
//          11 => Literal  W;
160
//
161
//  ALU Operations - Bit Processor (BP)
162
//
163
//  ALU_Op[3] = Set: 0 - Clr Selected Bit;
164
//                   1 - Set Selected Bit;
165
//
166
//  ALU_Op[5:4] = Status Flag Update Select
167
//
168
//          00 => None
169
//          01 => C
170
//          10 => Z
171
//          11 => Z,DC,C
172
//
173
//  ALU_Op[7:6] = ALU Output Data Multiplexer
174
//
175
//          00 => AU
176
//          01 => LU
177
//          10 => SU
178
//          11 => BP
179
//
180
//  ALU_Op[8]  = Tst: 0 - Normal Operation
181
//                    1 - Test: INCFSZ/DECFSZ/BTFSC/BTFSS
182
//
183
//  ALU_Op[9]  = Write Enable Working Register (W)
184
//
185
//  ALU_Op[10] = Indirect Register, INDF, Selected
186
//
187
//  ALU_Op[11] = Write Enable File {RAM | Special Function Registers}
188
//
189
 
190
assign C_In  = ALU_Op[0];  // Adder Carry input
191
assign B_Inv = ALU_Op[1];  // B Bus input invert
192
assign B_Sel = ALU_Op[2];  // B Bus select
193
assign A_Sel = ALU_Op[3];  // A Bus select
194
 
195
//  AU Input Bus Multiplexers
196
 
197
assign A = ((A_Sel) ? KI : DI);
198
assign B = ((B_Sel) ?  W : 0 );
199
assign Y = ((B_Inv) ? ~B : B );
200
 
201
//  AU Adder
202
 
203
assign {C3, X[3:0]} = A[3:0] + Y[3:0] + C_In;
204
assign {C7, X[7:4]} = A[7:4] + Y[7:4] + C3;
205
 
206
//  Logic Unit (LU)
207
 
208
assign LU_Op = ALU_Op[1:0];
209
 
210
always @(*)
211
begin
212
    case (LU_Op)
213
        2'b00 : V <= ~A;
214
        2'b01 : V <=  A | B;
215
        2'b10 : V <=  A & B;
216
        2'b11 : V <=  A ^ B;
217
    endcase
218
end
219
 
220
//  Shifter and W Multiplexer
221
 
222
assign S_Sel = ALU_Op[1:0];
223
 
224
always @(*)
225
begin
226
    case (S_Sel)
227
        2'b00 : S <= B;                  // Pass Working Register (MOVWF)
228
        2'b01 : S <= {A[3:0], A[7:4]};   // Swap Nibbles (SWAPF)
229
        2'b10 : S <= {C, A[7:1]};        // Shift Right (RRF)
230
        2'b11 : S <= {A[6:0], C};        // Shift Left (RLF)
231
    endcase
232
end
233
 
234
//  Bit Processor
235
 
236
assign Set = ALU_Op[3];
237
assign Tst = ALU_Op[8];
238
 
239
assign U = ((Set) ? (DI | Msk) : (DI & ~Msk));
240
 
241
assign T = (DI & Msk);
242
assign g = ((Tst) ? ((Set) ? |T : ~|T)
243
                  : 1'b0              );
244
 
245
//  Output Data Mux
246
 
247
assign D_Sel = ALU_Op[7:6];
248
 
249
always @(*)
250
begin
251
    case (D_Sel)
252
        2'b00 : DO <= X;     // Arithmetic Unit Output
253
        2'b01 : DO <= V;     // Logic Unit Output
254
        2'b10 : DO <= S;     // Shifter Output
255
        2'b11 : DO <= U;     // Bit Processor Output
256
    endcase
257
end
258
 
259
//  Working Register
260
 
261
assign WE_W = CE & ALU_Op[9];
262
 
263
always @(posedge Clk)
264
begin
265
    if(Rst)
266
        W <= #1 8'b0;
267
    else if(WE_W)
268
        W <= #1 DO;
269
end
270
 
271
//  Z Register
272
 
273
assign Z_Sel = ALU_Op[5];
274
assign Z_Tst = ~|DO;
275
 
276
assign CE_Z  = CE & (WE_PSW | Z_Sel);
277
 
278
always @(posedge Clk)
279
begin
280
    if(Rst)
281
        Z <= #1 1'b0;
282
    else if(CE_Z)
283
        Z <= #1 ((WE_PSW) ? DO[2] : Z_Tst);
284
end
285
 
286
//  Digit Carry (DC) Register
287
 
288
assign DC_Sel = ALU_Op[5] & ALU_Op[4];
289
assign CE_DC  = CE & (WE_PSW | DC_Sel);
290
 
291
always @(posedge Clk)
292
begin
293
    if(Rst)
294
        DC <= #1 1'b0;
295
    else if(CE_DC)
296
        DC <= #1 ((WE_PSW) ? DO[1] : C3);
297
end
298
 
299
//  Carry (C) Register
300
 
301
assign C_Sel = ALU_Op[4];
302
assign S_Dir = ALU_Op[1] & ALU_Op[0];
303
assign C_Drv = ((~ALU_Op[7] & ~ALU_Op[6]) ? C7 : ((S_Dir) ? A[7] : A[0]));
304
 
305
assign CE_C  = CE & (WE_PSW | C_Sel);
306
 
307
always @(posedge Clk)
308
begin
309
    if(Rst)
310
        C <= #1 1'b0;
311
    else if(CE_C)
312
        C <= #1 ((WE_PSW) ? DO[0] : C_Drv);
313
end
314
 
315
endmodule

powered by: WebSVN 2.1.0

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