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

Subversion Repositories next186

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

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 16 ndumitrach
// 07Jul2013 - fixed OV/CY flags for IMUL
76 2 ndumitrach
//////////////////////////////////////////////////////////////////////////////////
77
`timescale 1ns / 1ps
78
 
79
module Next186_ALU(
80
    input [15:0] RA,
81
    input [15:0] RB,
82
         input [15:0] TMP16,
83
         input [15:0] FETCH23,
84
         input [15:0]FIN,
85
         input [4:0]ALUOP,
86
         input [2:0]EXOP,
87
         input [3:0]FLAGOP,
88
         input WORD,
89
         input INC2,
90
         output reg [15:0]FOUT,
91
    output reg [15:0]ALUOUT,
92 20 ndumitrach
    output [15:0]ALUOUTA,
93 2 ndumitrach
         output reg ALUCONT,
94
         output NULLSHIFT,
95
         output COUT,
96
         input [2:0]STAGE,
97
         input CLK
98
    );
99
 
100
        reg CPLOP2;
101
        wire [15:0]SUMOP1 = ALUOP[3:1] == 3'b101 ? 16'h0000 : RA;        // NEG, NOT
102
        reg [15:0]SUMOP21;
103
        wire [15:0]SUMOP2 = CPLOP2 ? ~SUMOP21 : SUMOP21;
104
        wire SCIN1 = ALUOP[3:1] == 3'b001 ? FIN[0] : ALUOP[3:0] == 4'b1010 ? 1'b1 : 1'b0;         //ADD/ADC, NOT
105
        wire SCIN = CPLOP2 ? ~SCIN1 : SCIN1;    // carry in
106
        wire SC16OUT;
107
        wire SC8OUT;
108
        wire AF;
109
        wire [15:0]SUMOUT;
110
        wire parity = ~^ALUOUT[7:0];
111
        wire zero8 = ~|ALUOUT[7:0];
112
        wire zero = ~|ALUOUT[15:0];
113
        wire overflow8 = (SUMOP1[7] & SUMOP2[7] & !SUMOUT[7]) | (!SUMOP1[7] & !SUMOP2[7] & SUMOUT[7]);
114
        wire overflow = (SUMOP1[15] & SUMOP2[15] & !SUMOUT[15]) | (!SUMOP1[15] & !SUMOP2[15] & SUMOUT[15]);
115 9 ndumitrach
        wire LONIBBLE = (RA[3:0] > 4'h9)  || FIN[4];
116
        wire HINIBBLE = (RA[7:0] > 8'h99) || FIN[0];
117 2 ndumitrach
 
118
// ADDER                
119
        assign {AF, SUMOUT[3:0]} = SUMOP1[3:0] + SUMOP2[3:0] + SCIN;
120
        assign {SC8OUT, SUMOUT[7:4]} = SUMOP1[7:4] + SUMOP2[7:4] + AF;
121
        assign {SC16OUT, SUMOUT[15:8]} = SUMOP1[15:8] + SUMOP2[15:8] + SC8OUT;
122
        assign COUT = (WORD ? SC16OUT : SC8OUT) ^ CPLOP2;
123 20 ndumitrach
        assign ALUOUTA = ALUOP == 5'b11111 ? RB : SUMOUT;
124 2 ndumitrach
 
125
// SHIFTER
126
        reg [4:0]SHNOPT; // optimized shift
127
        wire [4:0]SHN = {STAGE[2:1] ^ SHNOPT[4:3], SHNOPT[2:0]};
128
        assign NULLSHIFT = ~|SHNOPT;
129
        wire [2:0]COUNT = |SHN[4:3] ? 0 : SHN[2:0];
130
        wire [2:0]SCOUNT = (EXOP[0] ? COUNT[2:0] : 3'b000) - (EXOP[0] ? 3'b001 : COUNT[2:0]);
131
        reg [7:0]SHEX;
132
        wire [17:0]SHBAR = (EXOP[0] ? {1'bx, SHEX, WORD ? RA[15:8]: SHEX, RA[7:0]} : {RA, SHEX, 1'bx}) >> SCOUNT;
133
 
134
// MULTIPLIER
135
        wire signed [16:0]MULOP1 = WORD ? {ALUOP[0] & TMP16[15], TMP16} : {ALUOP[0] ? {9{TMP16[7]}} : 9'b000000000, TMP16[7:0]};
136
        wire signed [16:0]MULOP2 = WORD ? {ALUOP[0] & FETCH23[15], FETCH23} : {ALUOP[0] ? {9{FETCH23[7]}} : 9'b000000000, FETCH23[7:0]};
137
        wire signed [31:0]MUL = MULOP1 * MULOP2;
138
 
139
        always @* begin
140
                FOUT[15:8] = {4'bxxxx, WORD ? overflow : overflow8, FIN[10:8]};
141
                FOUT[7] = WORD ? ALUOUT[15] : ALUOUT[7];
142
                FOUT[6] = WORD ? zero : zero8;
143
                FOUT[5] = 1'bx;
144
                FOUT[4] = AF ^ CPLOP2;
145
                FOUT[3] = 1'bx;
146
                FOUT[2] = parity;
147
                FOUT[1] = 1'bx;
148
                FOUT[0] = COUT;
149
                ALUOUT = 16'hxxxx;
150
                ALUCONT = 1'bx;
151
 
152
                case(ALUOP[3:0]) // complement second operand
153
                        4'b0000, 4'b0010, 4'b1000, 4'b1100, 4'b1110: CPLOP2 = 1'b0;     // ADD, ADC, INC, DEC, DAA, AAA
154
                        default: CPLOP2 = 1'b1;
155
                endcase
156
 
157
                case(ALUOP[3:0])
158
                        4'b1000, 4'b1001:       SUMOP21 = INC2 && WORD ? 2 : 1; // INC/DEC
159
                        4'b1100, 4'b1101:       SUMOP21 = {9'b000000000, HINIBBLE, HINIBBLE, 2'b00, LONIBBLE, LONIBBLE, 1'b0};
160
                        4'b1110, 4'b1111:       SUMOP21 = {7'b0000000, LONIBBLE, 5'b00000, LONIBBLE, LONIBBLE, 1'b0};
161
                        default: SUMOP21 = RB;
162
                endcase
163
 
164
                if(ALUOP[0])
165
                        case({WORD, EXOP[2:1]})
166
                                3'b000: SHNOPT = {2'b00, RB[2:0]};
167
                                3'b001, 3'b101:  SHNOPT = RB[4:0];
168
                                3'b010, 3'b011: SHNOPT = |RB[4:3] ? 5'b01000 : RB[4:0];
169
                                3'b100: SHNOPT = {1'b0, RB[3:0]};
170
                                3'b110, 3'b111: SHNOPT = RB[4] ? 5'b10000 : RB[4:0];
171
                        endcase
172
                else SHNOPT = 5'b00001;
173
 
174
                case({WORD, EXOP})
175
                        4'b1000:        SHEX = RA[15:8];                                        // ROL16
176
                        4'b0010: SHEX = {FIN[0], RA[7:1]};               // RCL8
177
                        4'b0011, 4'b1011:       SHEX = {RA[6:0], FIN[0]};         // RCR8, RCR16
178
                        4'b0111:        SHEX = {8{RA[7]}};                              // SAR8
179
                        4'b0000, 4'b0001, 4'b1001:      SHEX = RA[7:0];          // ROL8, ROR8, ROR16
180
                        4'b1010: SHEX = {FIN[0], RA[15:9]};              // RCL16
181
                        4'b1111:        SHEX = {8{RA[15]}};                             // SAR16
182
                        default: SHEX = 8'h00;                                          // SHL16, SHR16, SHL8, SHR8
183
                endcase
184
 
185
                case(ALUOP)
186
                        5'b00000, 5'b00010, 5'b00011, 5'b00101, 5'b00111, 5'b01010, 5'b01011: ALUOUT = SUMOUT;  // ADD, ADC, SBB, SUB, CMP, NOT, NEG
187
                        5'b00001: begin // OR
188
                                ALUOUT = RA | RB;
189
                                FOUT[0] = 1'b0;
190
                                FOUT[11] = 1'b0;
191
                                FOUT[4] = FIN[4];
192
                        end
193
                        5'b00100: begin // AND
194
                                ALUOUT = RA & RB;
195
                                FOUT[0] = 1'b0;
196
                                FOUT[11] = 1'b0;
197
                                FOUT[4] = FIN[4];
198
                        end
199
                        5'b00110: begin // XOR
200
                                ALUOUT = RA ^ RB;
201
                                FOUT[0] = 1'b0;
202
                                FOUT[11] = 1'b0;
203
                                FOUT[4] = FIN[4];
204
                        end
205
                        5'b01000, 5'b01001: begin       // INC, DEC
206
                                ALUOUT = SUMOUT;
207
                                FOUT[0] = FIN[0];
208
                        end
209
                        5'b01100, 5'b01101: begin       // DAA, DAS
210
                                ALUOUT = SUMOUT;
211 9 ndumitrach
                                FOUT[0] = HINIBBLE;
212
                                FOUT[4] = LONIBBLE;
213 2 ndumitrach
                        end
214
                        5'b01110, 5'b01111: begin       // AAA, AAS
215
                                ALUOUT = {SUMOUT[15:8], 4'b0000, SUMOUT[3:0]};
216
                                FOUT[0] = LONIBBLE;
217
                                FOUT[4] = LONIBBLE;
218
                        end
219
                        5'b10000, 5'b10001 : begin      // MUL, IMUL
220
                                ALUOUT = STAGE[1] ? MUL[31:16] : MUL[15:0];
221 17 ndumitrach
//07Jul2013 - fixed OV/CY flags for IMUL
222 18 ndumitrach
                                FOUT[0] = WORD ? MUL[31:16] != {16{MUL[15] & ALUOP[0]}} : MUL[15:8] != {8{MUL[7] & ALUOP[0]}};
223 2 ndumitrach
                                FOUT[11] = FOUT[0];
224
                        end
225
                        5'b11001: begin         // flag op
226
                                FOUT[11:8] = FIN[11:8];
227
                                FOUT[7] = FIN[7];
228
                                FOUT[6] = FIN[6];
229
                                FOUT[4] = FIN[4];
230
                                FOUT[2] = FIN[2];
231
                                FOUT[0] = FIN[0];
232
                                case(FLAGOP)
233
                                        4'b1000: FOUT[0] = 1'b0;         // CLC
234
                                        4'b0101: FOUT[0] = !FIN[0];       // CMC
235
                                        4'b1001: FOUT[0] = 1'b1;         // STC
236
                                        4'b1100: FOUT[10] = 1'b0;               // CLD
237
                                        4'b1101: FOUT[10] = 1'b1;               // STD
238
                                        4'b1010:        FOUT[9] = 1'b0;         // CLI
239
                                        default: FOUT[9] = 1'b1;                // STI
240
                                endcase
241
                        end
242
                        5'b11010: ALUOUT[7:0] = {8{RB[7]}};
243
                        5'b11011: ALUOUT[15:0] = {16{RB[15]}};
244
                        5'b11100, 5'b11101: begin       // ROT/SHF
245
                                ALUOUT = SHBAR[16:1];
246
                                FOUT[0] = EXOP[0] ? SHBAR[0] : WORD ? SHBAR[17] : SHBAR[9];
247
                                FOUT[11] = WORD ? RA[15] ^ ALUOUT[15] : RA[7] ^ ALUOUT[7]; // OF is defined only for 1bit rotate/shift
248
                                if(!EXOP[2]) begin      // ROT
249
                                        FOUT[7] = FIN[7];
250
                                        FOUT[6] = FIN[6];
251
                                        FOUT[4] = FIN[4];
252
                                        FOUT[2] = FIN[2];
253
                                end
254
                                case({SHN[4:3], STAGE[2:1]})
255
                                        4'b0100, 4'b1101, 4'b0110: ALUCONT = |SHN[2:0];
256
                                        4'b1000, 4'b1100, 4'b1001: ALUCONT = 1'b1;
257
                                        default: ALUCONT = 1'b0;
258
                                endcase
259
                        end
260
 
261
                        5'b11110:       begin
262
                                ALUOUT = FIN;
263
                                FOUT[11] = FIN[11];
264
                                FOUT[9] = 1'b0; // IF
265
                                FOUT[8] = 1'b0; // TF
266
                                FOUT[7] = FIN[7];
267
                                FOUT[6] = FIN[6];
268
                                FOUT[4] = FIN[4];
269
                                FOUT[2] = FIN[2];
270
                                FOUT[0] = FIN[0];
271
                        end
272
                        5'b11111:       begin
273
                                ALUOUT = RB;
274
                                FOUT = {WORD ? RA[15:8] : FIN[15:8], RA[7:0]};
275
                        end
276
                endcase
277
        end
278
 
279
endmodule
280
 
281
// 0000 - BX+SI+DISP
282
// 0001 - BX+DI+DISP
283
// 0010 - BP+SI+DISP
284
// 0011 - BP+DI+DISP
285
// 0100 - SI+DISP
286
// 0101 - DI+DISP
287
// 0110 - BP+DISP
288
// 0111 - BX+DISP
289
// 1000 - SP-2
290
// 1001 - SP+2
291
// 1010 - BX+AL
292
// 1011 - TMP16+2
293
// 1100 - 
294
// 1101 - SP+2+DISP
295
// 1110 - DISP[7:0]<<2
296 20 ndumitrach
// 1111 - 
297 2 ndumitrach
module Next186_EA(
298
    input [15:0] SP,
299
    input [15:0] BX,
300
    input [15:0] BP,
301
    input [15:0] SI,
302
    input [15:0] DI,
303
         input [15:0] TMP16,
304
         input [7:0]  AL,
305
    input [15:0] AIMM,
306
         input [3:0]EAC,
307
    output [15:0] ADDR16
308
    );
309
 
310
        reg [15:0]OP1;
311
        reg [15:0]OP2;
312
        reg [15:0]OP3;
313
 
314
        always @* begin
315
                case(EAC)
316
                        4'b0000, 4'b0001, 4'b0111, 4'b1010: OP1 = BX;
317
                        4'b0010, 4'b0011, 4'b0110:  OP1 = BP;
318
                        4'b1000, 4'b1001, 4'b1101: OP1 = SP;
319
                        4'b1011: OP1 = TMP16;
320
                        default: OP1 = 16'h0000;
321
                endcase
322
                case(EAC)
323
                        4'b0000, 4'b0010, 4'b0100: OP2 = SI;
324
                        4'b0001, 4'b0011, 4'b0101: OP2 = DI;
325
                        4'b1001, 4'b1011, 4'b1101:      OP2 = 16'h0002; // SP/TMP16 + 2
326
                        default: OP2 = 16'h0000;
327
                endcase
328
                case(EAC)
329
                        4'b1000: OP3 = 16'hfffe;        // SP - 2
330
                        4'b1010: OP3 = {8'b00000000, AL};       // XLAT
331
                        4'b1001, 4'b1011:       OP3 = 16'h0000; // SP/TMP16 + 2
332
                        4'b1110: OP3 = {6'b000000, AIMM[7:0], 2'b00};    // int
333
                        default: OP3 = AIMM;
334
                endcase
335
        end
336
 
337
        assign ADDR16 = OP1 + OP2 + OP3;
338
endmodule

powered by: WebSVN 2.1.0

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