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

Subversion Repositories p16c5x

[/] [p16c5x/] [trunk/] [RTL/] [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
// Additional Comments:
68
//
69
//  The ALU data output, DO, has been registered to support a higher operating
70
//  speed when a multi-cycle instruction cycle is used. Parameterization of this
71
//  may be added in the future, but the current module must be edited to remove
72
//  the DO register and the un-registered multiplexer, which has been commented
73
//  out, added back in when single cycle operation is desired.
74
//
75
////////////////////////////////////////////////////////////////////////////////
76
 
77
module P16C5x_ALU (
78
    input   Rst,
79
    input   Clk,
80
    input   CE,
81
 
82
    input   [11:0] ALU_Op,              // ALU Control Word
83
    input   WE_PSW,                     // Write Enable for {Z, DC, C} from DI
84
 
85
    input   [7:0] DI,                   // Data Input
86
    input   [7:0] KI,                   // Literal Input
87
 
88
    output  reg [7:0] DO,               // ALU Output
89
    output  Z_Tst,                      // ALU Zero Test Output
90
    output  g,                          // Bit Test Condition
91
 
92
    output  reg [7:0] W,                // Working Register 
93
 
94
    output  reg Z,                      // Z(ero) ALU Status Output
95
    output  reg DC,                     // Digit Carry ALU Status Output
96
    output  reg C                       // Carry Flag ALU Status Output
97
);
98
 
99
////////////////////////////////////////////////////////////////////////////////
100
//
101
//  Declarations
102
//
103
 
104
wire    [7:0] A, B, Y;
105
 
106
wire    [7:0] X;
107
wire    C3, C7;
108
 
109
wire    [1:0] LU_Op;
110
reg     [7:0] V;
111
 
112
wire    [1:0] S_Sel;
113
reg     [7:0] S;
114
 
115
wire    [2:0] Bit;
116
reg     [7:0] Msk;
117
 
118
wire    [7:0] U;
119
wire    [7:0] T;
120
 
121
wire    [1:0] D_Sel;
122
 
123
////////////////////////////////////////////////////////////////////////////////
124
//
125
//  ALU Implementation - ALU[3:0] are overloaded for the four ALU elements:
126
//                          Arithmetic Unit, Logic Unit, Shift Unit, and Bit
127
//                          Processor.
128
//
129
//  ALU Operations - Arithmetic, Logic, and Shift Units
130
//
131
//  ALU_Op[1:0] = ALU Unit Operation Code
132
//
133
//      Arithmetic Unit (AU): 00 => Y = A +  B;
134
//                            01 => Y = A +  B + 1;
135
//                            10 => Y = A + ~B     = A - B - 1;
136
//                            11 => Y = A + ~B + 1 = A - B;
137
//
138
//      Logic Unit (LU):      00 => V = ~A;
139
//                            01 => V =  A & B;
140
//                            10 => V =  A | B;
141
//                            11 => V =  A ^ B;
142
//
143
//      Shift Unit (SU):      00 => S = W;                // MOVWF
144
//                            01 => S = {A[3:0], A[7:4]}; // SWAPF
145
//                            10 => S = {C, A[7:1]};      // RRF
146
//                            11 => S = {A[6:0], C};      // RLF
147
//
148
//  ALU_Op[3:2] = ALU Operand:
149
//                  A      B
150
//          00 =>  File    0
151
//          01 =>  File    W
152
//          10 => Literal  0
153
//          11 => Literal  W;
154
//
155
//  ALU Operations - Bit Processor (BP)
156
//
157
//  ALU_Op[2:0] = Bit Select: 000 => Bit 0;
158
//                            001 => Bit 1;
159
//                            010 => Bit 2;
160
//                            011 => Bit 3;
161
//                            100 => Bit 4;
162
//                            101 => Bit 5;
163
//                            110 => Bit 6;
164
//                            111 => Bit 7;
165
//
166
//  ALU_Op[3] = Set: 0 - Clr Selected Bit;
167
//                   1 - Set Selected Bit;
168
//
169
//  ALU_Op[5:4] = Status Flag Update Select
170
//
171
//          00 => None
172
//          01 => C
173
//          10 => Z
174
//          11 => Z,DC,C
175
//
176
//  ALU_Op[7:6] = ALU Output Data Multiplexer
177
//
178
//          00 => AU
179
//          01 => LU
180
//          10 => SU
181
//          11 => BP
182
//
183
//  ALU_Op[8]  = Tst: 0 - Normal Operation
184
//                    1 - Test: INCFSZ/DECFSZ/BTFSC/BTFSS
185
//
186
//  ALU_Op[9]  = Write Enable Working Register (W)
187
//
188
//  ALU_Op[10] = Indirect Register, INDF, Selected
189
//
190
//  ALU_Op[11] = Write Enable File {RAM | Special Function Registers}
191
//
192
 
193
assign C_In  = ALU_Op[0];  // Adder Carry input
194
assign B_Inv = ALU_Op[1];  // B Bus input invert
195
assign B_Sel = ALU_Op[2];  // B Bus select
196
assign A_Sel = ALU_Op[3];  // A Bus select
197
 
198
//  AU Input Bus Multiplexers
199
 
200
assign A = ((A_Sel) ? KI : DI);
201
assign B = ((B_Sel) ?  W : 0 );
202
assign Y = ((B_Inv) ? ~B : B );
203
 
204
//  AU Adder
205
 
206
assign {C3, X[3:0]} = A[3:0] + Y[3:0] + C_In;
207
assign {C7, X[7:4]} = A[7:4] + Y[7:4] + C3;
208
 
209
//  Logic Unit (LU)
210
 
211
assign LU_Op = ALU_Op[1:0];
212
 
213
always @(*)
214
begin
215
    case (LU_Op)
216
        2'b00 : V <= ~A;
217
        2'b01 : V <=  A | B;
218
        2'b10 : V <=  A & B;
219
        2'b11 : V <=  A ^ B;
220
    endcase
221
end
222
 
223
//  Shifter and W Multiplexer
224
 
225
assign S_Sel = ALU_Op[1:0];
226
 
227
always @(*)
228
begin
229
    case (S_Sel)
230
        2'b00 : S <= B;                  // Pass Working Register (MOVWF)
231
        2'b01 : S <= {A[3:0], A[7:4]};   // Swap Nibbles (SWAPF)
232
        2'b10 : S <= {C, A[7:1]};        // Shift Right (RRF)
233
        2'b11 : S <= {A[6:0], C};        // Shift Left (RLF)
234
    endcase
235
end
236
 
237
//  Bit Processor
238
 
239
assign Bit = ALU_Op[2:0];
240
assign Set = ALU_Op[3];
241
assign Tst = ALU_Op[8];
242
 
243
always @(*)
244
begin
245
    case(Bit)
246
        3'b000  : Msk <= 8'b0000_0001;
247
        3'b001  : Msk <= 8'b0000_0010;
248
        3'b010  : Msk <= 8'b0000_0100;
249
        3'b011  : Msk <= 8'b0000_1000;
250
        3'b100  : Msk <= 8'b0001_0000;
251
        3'b101  : Msk <= 8'b0010_0000;
252
        3'b110  : Msk <= 8'b0100_0000;
253
        3'b111  : Msk <= 8'b1000_0000;
254
    endcase
255
end
256
 
257
assign U = ((Set) ? (DI | Msk) : (DI & ~Msk));
258
 
259
assign T = DI & Msk;
260
assign g = ((Tst) ? ((Set) ? |T : ~|T)
261
                  : 1'b0              );
262
 
263
//  Output Data Mux
264
 
265
assign D_Sel = ALU_Op[7:6];
266
 
267
always @(posedge Clk)
268
begin
269
    if(Rst)
270
        DO <= #1 0;
271
    else
272
        case (D_Sel)
273
            2'b00 : DO <= #1 X;     // Arithmetic Unit Output
274
            2'b01 : DO <= #1 V;     // Logic Unit Output
275
            2'b10 : DO <= #1 S;     // Shifter Output
276
            2'b11 : DO <= #1 U;     // Bit Processor Output
277
        endcase
278
end
279
 
280
//always @(*)
281
//begin
282
//    case (D_Sel)
283
//        2'b00 : DO <= X;     // Arithmetic Unit Output
284
//        2'b01 : DO <= V;     // Logic Unit Output
285
//        2'b10 : DO <= S;     // Shifter Output
286
//        2'b11 : DO <= U;     // Bit Processor Output
287
//    endcase
288
//end
289
 
290
//  Working Register
291
 
292
assign WE_W = ALU_Op[9];
293
 
294
always @(posedge Clk)
295
begin
296
    if(Rst)
297
        W <= #1 8'b0;
298
    else if(CE)
299
        W <= #1 ((WE_W) ? DO : W);
300
end
301
 
302
//  Z Register
303
 
304
assign Z_Sel = ALU_Op[5];
305
assign Z_Tst = ~|DO;
306
 
307
always @(posedge Clk)
308
begin
309
    if(Rst)
310
        Z <= #1 1'b0;
311
    else if(CE)
312
        Z <= #1 ((Z_Sel) ? Z_Tst
313
                         : ((WE_PSW) ? DO[2] : Z));
314
end
315
 
316
//  Digit Carry (DC) Register
317
 
318
assign DC_Sel = ALU_Op[5] & ALU_Op[4];
319
 
320
always @(posedge Clk)
321
begin
322
    if(Rst)
323
        DC <= #1 1'b0;
324
    else if(CE)
325
        DC <= #1 ((DC_Sel) ? C3
326
                           : ((WE_PSW) ? DO[1] : DC));
327
end
328
 
329
//  Carry (C) Register
330
 
331
assign C_Sel = ALU_Op[4];
332
assign S_Dir = ALU_Op[1] & ALU_Op[0];
333
assign C_Drv = ((~ALU_Op[7] & ~ALU_Op[6]) ? C7
334
                                          : ((S_Dir) ? A[7] : A[0]));
335
 
336
always @(posedge Clk)
337
begin
338
    if(Rst)
339
        C <= #1 1'b0;
340
    else if(CE)
341
        C <= #1 ((C_Sel) ? C_Drv
342
                         : ((WE_PSW) ? DO[0] : C));
343
end
344
 
345
endmodule

powered by: WebSVN 2.1.0

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