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

Subversion Repositories next186

[/] [next186/] [trunk/] [Next186_ALU.v] - Blame information for rev 12

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ndumitrach
//////////////////////////////////////////////////////////////////////////////////
2
//
3
// This file is part of the Next186 project
4
// http://opencores.org/project,next186
5
//
6
// Filename: Next186_ALU.v
7
// Description: Part of the Next186 CPU project, arithmetic-logic unit and effective address unit implementation
8
// Version 1.0
9
// Creation date: 11Apr2011 - 07Jun2011
10
//
11
// Author: Nicolae Dumitrache 
12
// e-mail: ndumitrache@opencores.org
13
//
14
/////////////////////////////////////////////////////////////////////////////////
15
// 
16
// Copyright (C) 2011 Nicolae Dumitrache
17
// 
18
// This source file may be used and distributed without 
19
// restriction provided that this copyright statement is not 
20
// removed from the file and that any derivative work contains 
21
// the original copyright notice and the associated disclaimer.
22
// 
23
// This source file is free software; you can redistribute it 
24
// and/or modify it under the terms of the GNU Lesser General 
25
// Public License as published by the Free Software Foundation;
26
// either version 2.1 of the License, or (at your option) any 
27
// later version. 
28
// 
29
// This source is distributed in the hope that it will be 
30
// useful, but WITHOUT ANY WARRANTY; without even the implied 
31
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
32
// PURPOSE. See the GNU Lesser General Public License for more 
33
// details. 
34
// 
35
// You should have received a copy of the GNU Lesser General 
36
// Public License along with this source; if not, download it 
37
// from http://www.opencores.org/lgpl.shtml 
38
// 
39
///////////////////////////////////////////////////////////////////////////////////
40
// Additional Comments: 
41
//
42
//      ADD                     00_000
43
//      OR                              00_001
44
//      ADC                     00_010
45
//      SBB                     00_011
46
//      AND                     00_100
47
//      SUB                     00_101
48
//      XOR                     00_110
49
//      CMP                     00_111
50
//
51
//      INC                     01_000
52
//      DEC                     01_001
53
//      NOT                     01_010
54
//      NEG                     01_011
55
//      DAA                     01_100  // +0066h
56
//      DAS                     01_101  // -0066h
57
//      AAA                     01_110  // +0106h
58
//      AAS                     01_111  // -0106h
59
//
60
//      MUL                     10_000
61
//      IMUL                    10_001
62
//
63
//      FLAGOP          11_001
64
// CBW                  11_010
65
//      CWD                     11_011
66
//      SHF/ROT 1       11_100
67
// SHF/ROT n    11_101
68
//      PASS FLAGS      11_110  // ALUOP <- FLAGS, clear TF, IF
69
//      PASS RB         11_111  // ALUOP <- RB, FLAGS <- RA
70
//
71
//
72
//  FLAGS:              X X X X OF DF IF TF  |  SF ZF X AF X PF X CF
73
//
74 9 ndumitrach
// 09Feb2013 - fixed DAA,DAS bug
75 2 ndumitrach
//////////////////////////////////////////////////////////////////////////////////
76
`timescale 1ns / 1ps
77
 
78
module Next186_ALU(
79
    input [15:0] RA,
80
    input [15:0] RB,
81
         input [15:0] TMP16,
82
         input [15:0] FETCH23,
83
         input [15:0]FIN,
84
         input [4:0]ALUOP,
85
         input [2:0]EXOP,
86
         input [3:0]FLAGOP,
87
         input WORD,
88
         input INC2,
89
         output reg [15:0]FOUT,
90
    output reg [15:0]ALUOUT,
91
         output reg ALUCONT,
92
         output NULLSHIFT,
93
         output COUT,
94
         input [2:0]STAGE,
95
         input CLK
96
    );
97
 
98
        reg CPLOP2;
99
        wire [15:0]SUMOP1 = ALUOP[3:1] == 3'b101 ? 16'h0000 : RA;        // NEG, NOT
100
        reg [15:0]SUMOP21;
101
        wire [15:0]SUMOP2 = CPLOP2 ? ~SUMOP21 : SUMOP21;
102
        wire SCIN1 = ALUOP[3:1] == 3'b001 ? FIN[0] : ALUOP[3:0] == 4'b1010 ? 1'b1 : 1'b0;         //ADD/ADC, NOT
103
        wire SCIN = CPLOP2 ? ~SCIN1 : SCIN1;    // carry in
104
        wire SC16OUT;
105
        wire SC8OUT;
106
        wire AF;
107
        wire [15:0]SUMOUT;
108
        wire parity = ~^ALUOUT[7:0];
109
        wire zero8 = ~|ALUOUT[7:0];
110
        wire zero = ~|ALUOUT[15:0];
111
        wire overflow8 = (SUMOP1[7] & SUMOP2[7] & !SUMOUT[7]) | (!SUMOP1[7] & !SUMOP2[7] & SUMOUT[7]);
112
        wire overflow = (SUMOP1[15] & SUMOP2[15] & !SUMOUT[15]) | (!SUMOP1[15] & !SUMOP2[15] & SUMOUT[15]);
113 9 ndumitrach
        wire LONIBBLE = (RA[3:0] > 4'h9)  || FIN[4];
114
        wire HINIBBLE = (RA[7:0] > 8'h99) || FIN[0];
115 2 ndumitrach
 
116
// ADDER                
117
        assign {AF, SUMOUT[3:0]} = SUMOP1[3:0] + SUMOP2[3:0] + SCIN;
118
        assign {SC8OUT, SUMOUT[7:4]} = SUMOP1[7:4] + SUMOP2[7:4] + AF;
119
        assign {SC16OUT, SUMOUT[15:8]} = SUMOP1[15:8] + SUMOP2[15:8] + SC8OUT;
120
        assign COUT = (WORD ? SC16OUT : SC8OUT) ^ CPLOP2;
121
 
122
// SHIFTER
123
        reg [4:0]SHNOPT; // optimized shift
124
        wire [4:0]SHN = {STAGE[2:1] ^ SHNOPT[4:3], SHNOPT[2:0]};
125
        assign NULLSHIFT = ~|SHNOPT;
126
        wire [2:0]COUNT = |SHN[4:3] ? 0 : SHN[2:0];
127
        wire [2:0]SCOUNT = (EXOP[0] ? COUNT[2:0] : 3'b000) - (EXOP[0] ? 3'b001 : COUNT[2:0]);
128
        reg [7:0]SHEX;
129
        wire [17:0]SHBAR = (EXOP[0] ? {1'bx, SHEX, WORD ? RA[15:8]: SHEX, RA[7:0]} : {RA, SHEX, 1'bx}) >> SCOUNT;
130
 
131
// MULTIPLIER
132
        wire signed [16:0]MULOP1 = WORD ? {ALUOP[0] & TMP16[15], TMP16} : {ALUOP[0] ? {9{TMP16[7]}} : 9'b000000000, TMP16[7:0]};
133
        wire signed [16:0]MULOP2 = WORD ? {ALUOP[0] & FETCH23[15], FETCH23} : {ALUOP[0] ? {9{FETCH23[7]}} : 9'b000000000, FETCH23[7:0]};
134
        wire signed [31:0]MUL = MULOP1 * MULOP2;
135
 
136
        always @* begin
137
                FOUT[15:8] = {4'bxxxx, WORD ? overflow : overflow8, FIN[10:8]};
138
                FOUT[7] = WORD ? ALUOUT[15] : ALUOUT[7];
139
                FOUT[6] = WORD ? zero : zero8;
140
                FOUT[5] = 1'bx;
141
                FOUT[4] = AF ^ CPLOP2;
142
                FOUT[3] = 1'bx;
143
                FOUT[2] = parity;
144
                FOUT[1] = 1'bx;
145
                FOUT[0] = COUT;
146
                ALUOUT = 16'hxxxx;
147
                ALUCONT = 1'bx;
148
 
149
                case(ALUOP[3:0]) // complement second operand
150
                        4'b0000, 4'b0010, 4'b1000, 4'b1100, 4'b1110: CPLOP2 = 1'b0;     // ADD, ADC, INC, DEC, DAA, AAA
151
                        default: CPLOP2 = 1'b1;
152
                endcase
153
 
154
                case(ALUOP[3:0])
155
                        4'b1000, 4'b1001:       SUMOP21 = INC2 && WORD ? 2 : 1; // INC/DEC
156
                        4'b1100, 4'b1101:       SUMOP21 = {9'b000000000, HINIBBLE, HINIBBLE, 2'b00, LONIBBLE, LONIBBLE, 1'b0};
157
                        4'b1110, 4'b1111:       SUMOP21 = {7'b0000000, LONIBBLE, 5'b00000, LONIBBLE, LONIBBLE, 1'b0};
158
                        default: SUMOP21 = RB;
159
                endcase
160
 
161
                if(ALUOP[0])
162
                        case({WORD, EXOP[2:1]})
163
                                3'b000: SHNOPT = {2'b00, RB[2:0]};
164
                                3'b001, 3'b101:  SHNOPT = RB[4:0];
165
                                3'b010, 3'b011: SHNOPT = |RB[4:3] ? 5'b01000 : RB[4:0];
166
                                3'b100: SHNOPT = {1'b0, RB[3:0]};
167
                                3'b110, 3'b111: SHNOPT = RB[4] ? 5'b10000 : RB[4:0];
168
                        endcase
169
                else SHNOPT = 5'b00001;
170
 
171
                case({WORD, EXOP})
172
                        4'b1000:        SHEX = RA[15:8];                                        // ROL16
173
                        4'b0010: SHEX = {FIN[0], RA[7:1]};               // RCL8
174
                        4'b0011, 4'b1011:       SHEX = {RA[6:0], FIN[0]};         // RCR8, RCR16
175
                        4'b0111:        SHEX = {8{RA[7]}};                              // SAR8
176
                        4'b0000, 4'b0001, 4'b1001:      SHEX = RA[7:0];          // ROL8, ROR8, ROR16
177
                        4'b1010: SHEX = {FIN[0], RA[15:9]};              // RCL16
178
                        4'b1111:        SHEX = {8{RA[15]}};                             // SAR16
179
                        default: SHEX = 8'h00;                                          // SHL16, SHR16, SHL8, SHR8
180
                endcase
181
 
182
                case(ALUOP)
183
                        5'b00000, 5'b00010, 5'b00011, 5'b00101, 5'b00111, 5'b01010, 5'b01011: ALUOUT = SUMOUT;  // ADD, ADC, SBB, SUB, CMP, NOT, NEG
184
                        5'b00001: begin // OR
185
                                ALUOUT = RA | RB;
186
                                FOUT[0] = 1'b0;
187
                                FOUT[11] = 1'b0;
188
                                FOUT[4] = FIN[4];
189
                        end
190
                        5'b00100: begin // AND
191
                                ALUOUT = RA & RB;
192
                                FOUT[0] = 1'b0;
193
                                FOUT[11] = 1'b0;
194
                                FOUT[4] = FIN[4];
195
                        end
196
                        5'b00110: begin // XOR
197
                                ALUOUT = RA ^ RB;
198
                                FOUT[0] = 1'b0;
199
                                FOUT[11] = 1'b0;
200
                                FOUT[4] = FIN[4];
201
                        end
202
                        5'b01000, 5'b01001: begin       // INC, DEC
203
                                ALUOUT = SUMOUT;
204
                                FOUT[0] = FIN[0];
205
                        end
206
                        5'b01100, 5'b01101: begin       // DAA, DAS
207
                                ALUOUT = SUMOUT;
208 9 ndumitrach
                                FOUT[0] = HINIBBLE;
209
                                FOUT[4] = LONIBBLE;
210 2 ndumitrach
                        end
211
                        5'b01110, 5'b01111: begin       // AAA, AAS
212
                                ALUOUT = {SUMOUT[15:8], 4'b0000, SUMOUT[3:0]};
213
                                FOUT[0] = LONIBBLE;
214
                                FOUT[4] = LONIBBLE;
215
                        end
216
                        5'b10000, 5'b10001 : begin      // MUL, IMUL
217
                                ALUOUT = STAGE[1] ? MUL[31:16] : MUL[15:0];
218
                                FOUT[0] = WORD ? !zero : |MUL[15:8];
219
                                FOUT[11] = FOUT[0];
220
                        end
221
                        5'b11001: begin         // flag op
222
                                FOUT[11:8] = FIN[11:8];
223
                                FOUT[7] = FIN[7];
224
                                FOUT[6] = FIN[6];
225
                                FOUT[4] = FIN[4];
226
                                FOUT[2] = FIN[2];
227
                                FOUT[0] = FIN[0];
228
                                case(FLAGOP)
229
                                        4'b1000: FOUT[0] = 1'b0;         // CLC
230
                                        4'b0101: FOUT[0] = !FIN[0];       // CMC
231
                                        4'b1001: FOUT[0] = 1'b1;         // STC
232
                                        4'b1100: FOUT[10] = 1'b0;               // CLD
233
                                        4'b1101: FOUT[10] = 1'b1;               // STD
234
                                        4'b1010:        FOUT[9] = 1'b0;         // CLI
235
                                        default: FOUT[9] = 1'b1;                // STI
236
                                endcase
237
                        end
238
                        5'b11010: ALUOUT[7:0] = {8{RB[7]}};
239
                        5'b11011: ALUOUT[15:0] = {16{RB[15]}};
240
                        5'b11100, 5'b11101: begin       // ROT/SHF
241
                                ALUOUT = SHBAR[16:1];
242
                                FOUT[0] = EXOP[0] ? SHBAR[0] : WORD ? SHBAR[17] : SHBAR[9];
243
                                FOUT[11] = WORD ? RA[15] ^ ALUOUT[15] : RA[7] ^ ALUOUT[7]; // OF is defined only for 1bit rotate/shift
244
                                if(!EXOP[2]) begin      // ROT
245
                                        FOUT[7] = FIN[7];
246
                                        FOUT[6] = FIN[6];
247
                                        FOUT[4] = FIN[4];
248
                                        FOUT[2] = FIN[2];
249
                                end
250
                                case({SHN[4:3], STAGE[2:1]})
251
                                        4'b0100, 4'b1101, 4'b0110: ALUCONT = |SHN[2:0];
252
                                        4'b1000, 4'b1100, 4'b1001: ALUCONT = 1'b1;
253
                                        default: ALUCONT = 1'b0;
254
                                endcase
255
                        end
256
 
257
                        5'b11110:       begin
258
                                ALUOUT = FIN;
259
                                FOUT[11] = FIN[11];
260
                                FOUT[9] = 1'b0; // IF
261
                                FOUT[8] = 1'b0; // TF
262
                                FOUT[7] = FIN[7];
263
                                FOUT[6] = FIN[6];
264
                                FOUT[4] = FIN[4];
265
                                FOUT[2] = FIN[2];
266
                                FOUT[0] = FIN[0];
267
                        end
268
                        5'b11111:       begin
269
                                ALUOUT = RB;
270
                                FOUT = {WORD ? RA[15:8] : FIN[15:8], RA[7:0]};
271
                        end
272
                endcase
273
        end
274
 
275
endmodule
276
 
277
// 0000 - BX+SI+DISP
278
// 0001 - BX+DI+DISP
279
// 0010 - BP+SI+DISP
280
// 0011 - BP+DI+DISP
281
// 0100 - SI+DISP
282
// 0101 - DI+DISP
283
// 0110 - BP+DISP
284
// 0111 - BX+DISP
285
// 1000 - SP-2
286
// 1001 - SP+2
287
// 1010 - BX+AL
288
// 1011 - TMP16+2
289
// 1100 - 
290
// 1101 - SP+2+DISP
291
// 1110 - DISP[7:0]<<2
292
// 1111 - PIO
293
module Next186_EA(
294
    input [15:0] SP,
295
    input [15:0] BX,
296
    input [15:0] BP,
297
    input [15:0] SI,
298
    input [15:0] DI,
299
         input [15:0] PIO,
300
         input [15:0] TMP16,
301
         input [7:0]  AL,
302
    input [15:0] AIMM,
303
         input [3:0]EAC,
304
    output [15:0] ADDR16
305
    );
306
 
307
        reg [15:0]OP1;
308
        reg [15:0]OP2;
309
        reg [15:0]OP3;
310
 
311
        always @* begin
312
                case(EAC)
313
                        4'b0000, 4'b0001, 4'b0111, 4'b1010: OP1 = BX;
314
                        4'b0010, 4'b0011, 4'b0110:  OP1 = BP;
315
                        4'b1000, 4'b1001, 4'b1101: OP1 = SP;
316
                        4'b1011: OP1 = TMP16;
317
                        default: OP1 = 16'h0000;
318
                endcase
319
                case(EAC)
320
                        4'b0000, 4'b0010, 4'b0100: OP2 = SI;
321
                        4'b0001, 4'b0011, 4'b0101: OP2 = DI;
322
                        4'b1001, 4'b1011, 4'b1101:      OP2 = 16'h0002; // SP/TMP16 + 2
323
                        default: OP2 = 16'h0000;
324
                endcase
325
                case(EAC)
326
                        4'b1000: OP3 = 16'hfffe;        // SP - 2
327
                        4'b1010: OP3 = {8'b00000000, AL};       // XLAT
328
                        4'b1001, 4'b1011:       OP3 = 16'h0000; // SP/TMP16 + 2
329
                        4'b1110: OP3 = {6'b000000, AIMM[7:0], 2'b00};    // int
330
                        4'b1111: OP3 = PIO;     // in,out
331
                        default: OP3 = AIMM;
332
                endcase
333
        end
334
 
335
        assign ADDR16 = OP1 + OP2 + OP3;
336
endmodule

powered by: WebSVN 2.1.0

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