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

Subversion Repositories oms8051mini

[/] [oms8051mini/] [trunk/] [rtl/] [8051/] [oc8051_alu.v] - Blame information for rev 14

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

Line No. Rev Author Line
1 2 dinesha
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
//// alu for 8051 Core                                            ////
4
////                                                              ////
5
//// This file is part of the 8051 cores project                  ////
6
////  http://www.opencores.org/cores/oms8051mini/                 ////
7
////                                                              ////
8
//// Description                                                  ////
9
//// Implementation of aritmetic unit  according to               ////
10
//// 8051 IP core specification document. Uses divide.v and       ////
11
//// multiply.v                                                   ////
12
////                                                              ////
13
//// To Do:                                                       ////
14
////  pc signed add                                               ////
15
////                                                              ////
16
//// Author(s):                                                   ////
17
////      - Simon Teran, simont@opencores.org                     ////
18
////      - Dinesh Annayya, dinesha@opencores.org                 ////
19
////                                                              ////
20
//////////////////////////////////////////////////////////////////////
21
////                                                              ////
22
//// Copyright (C) 2001 Authors and OPENCORES.ORG                 ////
23
////                                                              ////
24
//// This source file may be used and distributed without         ////
25
//// restriction provided that this copyright statement is not    ////
26
//// removed from the file and that any derivative work contains  ////
27
//// the original copyright notice and the associated disclaimer. ////
28
////                                                              ////
29
//// This source file is free software; you can redistribute it   ////
30
//// and/or modify it under the terms of the GNU Lesser General   ////
31
//// Public License as published by the Free Software Foundation; ////
32
//// either version 2.1 of the License, or (at your option) any   ////
33
//// later version.                                               ////
34
////                                                              ////
35
//// This source is distributed in the hope that it will be       ////
36
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
37
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
38
//// PURPOSE. See the GNU Lesser General Public License for more  ////
39
//// details.                                                     ////
40
////                                                              ////
41
//// You should have received a copy of the GNU Lesser General    ////
42
//// Public License along with this source; if not, download it   ////
43
//// from http://www.opencores.org/lgpl.shtml                     ////
44
////                                                              ////
45
//////////////////////////////////////////////////////////////////////
46
//
47
// CVS Revision History
48
//
49
// $Log: not supported by cvs2svn $
50
// Revision 1.18  2003/07/01 18:51:11  simont
51
// x replaced with 0.
52
//
53
// Revision 1.17  2003/06/09 16:51:16  simont
54
// fix bug in DA operation.
55
//
56
// Revision 1.16  2003/06/03 17:15:06  simont
57
// sub_result output added.
58
//
59
// Revision 1.15  2003/05/07 12:31:53  simont
60
// add wire sub_result, conect it to des_acc and des1.
61
//
62
// Revision 1.14  2003/05/05 15:46:36  simont
63
// add aditional alu destination to solve critical path.
64
//
65
// Revision 1.13  2003/04/29 08:35:12  simont
66
// fix bug in substraction.
67
//
68
// Revision 1.12  2003/04/25 17:15:51  simont
69
// change branch instruction execution (reduse needed clock periods).
70
//
71
// Revision 1.11  2003/04/14 14:29:42  simont
72
// fiz bug iv pcs operation.
73
//
74
// Revision 1.10  2003/01/13 14:14:40  simont
75
// replace some modules
76
//
77
// Revision 1.9  2002/09/30 17:33:59  simont
78
// prepared header
79
//
80
//
81
 
82
`include "top_defines.v"
83
 
84
 
85
 
86
module oc8051_alu (clk, rst, op_code, src1, src2, src3, srcCy, srcAc, bit_in,
87
                  des1, des2, des_acc, desCy, desAc, desOv, sub_result);
88
//
89
// op_code      (in)  operation code [oc8051_decoder.alu_op -r]
90
// src1         (in)  first operand [oc8051_alu_src1_sel.des]
91
// src2         (in)  second operand [oc8051_alu_src2_sel.des]
92
// src3         (in)  third operand [oc8051_alu_src3_sel.des]
93
// srcCy        (in)  carry input [oc8051_cy_select.data_out]
94
// srcAc        (in)  auxiliary carry input [oc8051_psw.data_out[6] ]
95
// bit_in       (in)  bit input, used for logic operatins on bits [oc8051_ram_sel.bit_out]
96
// des1         (out)
97
// des2         (out)
98
// desCy        (out) carry output [oc8051_ram_top.bit_data_in, oc8051_acc.bit_in, oc8051_b_register.bit_in, oc8051_psw.cy_in, oc8051_ports.bit_in]
99
// desAc        (out) auxiliary carry output [oc8051_psw.ac_in]
100
// desOv        (out) Overflow output [oc8051_psw.ov_in]
101
//
102
 
103
input        srcCy, srcAc, bit_in, clk, rst;
104
input  [3:0] op_code;
105
input  [7:0] src1, src2, src3;
106
output       desCy, desAc, desOv;
107
output [7:0] des1, des2, des_acc, sub_result;
108
 
109
reg desCy, desAc, desOv;
110
reg [7:0] des1, des2, des_acc;
111
 
112
 
113
//
114
//add
115
//
116
wire [4:0] add1, add2, add3, add4;
117
wire [3:0] add5, add6, add7, add8;
118
wire [1:0] add9, adda, addb, addc;
119
 
120
//
121
//sub
122
//
123
wire [4:0] sub1, sub2, sub3, sub4;
124
wire [3:0] sub5, sub6, sub7, sub8;
125
wire [1:0] sub9, suba, subb, subc;
126
wire [7:0] sub_result;
127
 
128
//
129
//mul
130
//
131
  wire [7:0] mulsrc1, mulsrc2;
132
  wire mulOv;
133
  reg enable_mul;
134
 
135
//
136
//div
137
//
138
wire [7:0] divsrc1,divsrc2;
139
wire divOv;
140
reg enable_div;
141
 
142
//
143
//da
144
//
145
reg da_tmp, da_tmp1;
146
//reg [8:0] da1;
147
 
148
//
149
// inc
150
//
151
wire [15:0] inc, dec;
152
 
153
 
154
oc8051_multiply oc8051_mul1(.clk(clk), .rst(rst), .enable(enable_mul), .src1(src1), .src2(src2), .des1(mulsrc1), .des2(mulsrc2), .desOv(mulOv));
155
 
156
 
157
 
158
 
159
 
160
 
161
 
162
oc8051_divide oc8051_div1(.clk(clk), .rst(rst), .enable(enable_div), .src1(src1), .src2(src2), .des1(divsrc1), .des2(divsrc2), .desOv(divOv));
163
 
164
/* Add */
165
assign add1 = {1'b0,src1[3:0]};
166
assign add2 = {1'b0,src2[3:0]};
167
assign add3 = {3'b000,srcCy};
168
assign add4 = add1+add2+add3;
169
 
170
assign add5 = {1'b0,src1[6:4]};
171
assign add6 = {1'b0,src2[6:4]};
172
assign add7 = {1'b0,1'b0,1'b0,add4[4]};
173
assign add8 = add5+add6+add7;
174
 
175
assign add9 = {1'b0,src1[7]};
176
assign adda = {1'b0,src2[7]};
177
assign addb = {1'b0,add8[3]};
178
assign addc = add9+adda+addb;
179
 
180
/* Sub */
181
assign sub1 = {1'b1,src1[3:0]};
182
assign sub2 = {1'b0,src2[3:0]};
183
assign sub3 = {1'b0,1'b0,1'b0,srcCy};
184
assign sub4 = sub1-sub2-sub3;
185
 
186
assign sub5 = {1'b1,src1[6:4]};
187
assign sub6 = {1'b0,src2[6:4]};
188
assign sub7 = {1'b0,1'b0,1'b0, !sub4[4]};
189
assign sub8 = sub5-sub6-sub7;
190
 
191
assign sub9 = {1'b1,src1[7]};
192
assign suba = {1'b0,src2[7]};
193
assign subb = {1'b0,!sub8[3]};
194
assign subc = sub9-suba-subb;
195
 
196
assign sub_result = {subc[0],sub8[2:0],sub4[3:0]};
197
 
198
/* inc */
199
assign inc = {src2, src1} + {15'h0, 1'b1};
200
assign dec = {src2, src1} - {15'h0, 1'b1};
201
 
202
always @(op_code or src1 or src2 or srcCy or srcAc or bit_in or src3 or mulsrc1
203
      or mulsrc2 or mulOv or divsrc1 or divsrc2 or divOv or addc or add8 or add4
204
      or sub4 or sub8 or subc or da_tmp or inc or dec or sub_result)
205
begin
206
 
207
  case (op_code) /* synopsys full_case parallel_case */
208
//operation add
209
    `OC8051_ALU_ADD: begin
210
      des_acc = {addc[0],add8[2:0],add4[3:0]};
211
      des1 = src1;
212
      des2 = src3+ {7'b0, addc[1]};
213
      desCy = addc[1];
214
      desAc = add4[4];
215
      desOv = addc[1] ^ add8[3];
216
 
217
      enable_mul = 1'b0;
218
      enable_div = 1'b0;
219
    end
220
//operation subtract
221
    `OC8051_ALU_SUB: begin
222
      des_acc = sub_result;
223
//      des1 = sub_result;
224
      des1 = 8'h00;
225
      des2 = 8'h00;
226
      desCy = !subc[1];
227
      desAc = !sub4[4];
228
      desOv = !subc[1] ^ !sub8[3];
229
 
230
      enable_mul = 1'b0;
231
      enable_div = 1'b0;
232
    end
233
//operation multiply
234
    `OC8051_ALU_MUL: begin
235
      des_acc = mulsrc1;
236
      des1 = src1;
237
      des2 = mulsrc2;
238
      desOv = mulOv;
239
      desCy = 1'b0;
240
      desAc = 1'b0;
241
      enable_mul = 1'b1;
242
      enable_div = 1'b0;
243
    end
244
//operation divide
245
    `OC8051_ALU_DIV: begin
246
      des_acc = divsrc1;
247
      des1 = src1;
248
      des2 = divsrc2;
249
      desOv = divOv;
250
      desAc = 1'b0;
251
      desCy = 1'b0;
252
      enable_mul = 1'b0;
253
      enable_div = 1'b1;
254
    end
255
//operation decimal adjustment
256
    `OC8051_ALU_DA: begin
257
 
258
      if (srcAc==1'b1 | src1[3:0]>4'b1001) {da_tmp, des_acc[3:0]} = {1'b0, src1[3:0]}+ 5'b00110;
259
      else {da_tmp, des_acc[3:0]} = {1'b0, src1[3:0]};
260
 
261
      if (srcCy | da_tmp | src1[7:4]>4'b1001)
262
        {da_tmp1, des_acc[7:4]} = {srcCy, src1[7:4]}+ 5'b00110 + {4'b0, da_tmp};
263
      else {da_tmp1, des_acc[7:4]} = {srcCy, src1[7:4]} + {4'b0, da_tmp};
264
 
265
      desCy = da_tmp | da_tmp1;
266
      des1 = src1;
267
      des2 = 8'h00;
268
      desAc = 1'b0;
269
      desOv = 1'b0;
270
      enable_mul = 1'b0;
271
      enable_div = 1'b0;
272
    end
273
//operation not
274
// bit operation not
275
    `OC8051_ALU_NOT: begin
276
      des_acc = ~src1;
277
      des1 = ~src1;
278
      des2 = 8'h00;
279
      desCy = !srcCy;
280
      desAc = 1'b0;
281
      desOv = 1'b0;
282
      enable_mul = 1'b0;
283
      enable_div = 1'b0;
284
    end
285
//operation and
286
//bit operation and
287
    `OC8051_ALU_AND: begin
288
      des_acc = src1 & src2;
289
      des1 = src1 & src2;
290
      des2 = 8'h00;
291
      desCy = srcCy & bit_in;
292
      desAc = 1'b0;
293
      desOv = 1'b0;
294
      enable_mul = 1'b0;
295
      enable_div = 1'b0;
296
    end
297
//operation xor
298
// bit operation xor
299
    `OC8051_ALU_XOR: begin
300
      des_acc = src1 ^ src2;
301
      des1 = src1 ^ src2;
302
      des2 = 8'h00;
303
      desCy = srcCy ^ bit_in;
304
      desAc = 1'b0;
305
      desOv = 1'b0;
306
      enable_mul = 1'b0;
307
      enable_div = 1'b0;
308
    end
309
//operation or
310
// bit operation or
311
    `OC8051_ALU_OR: begin
312
      des_acc = src1 | src2;
313
      des1 = src1 | src2;
314
      des2 = 8'h00;
315
      desCy = srcCy | bit_in;
316
      desAc = 1'b0;
317
      desOv = 1'b0;
318
      enable_mul = 1'b0;
319
      enable_div = 1'b0;
320
    end
321
//operation rotate left
322
// bit operation cy= cy or (not ram)
323
    `OC8051_ALU_RL: begin
324
      des_acc = {src1[6:0], src1[7]};
325
      des1 = src1 ;
326
      des2 = 8'h00;
327
      desCy = srcCy | !bit_in;
328
      desAc = 1'b0;
329
      desOv = 1'b0;
330
      enable_mul = 1'b0;
331
      enable_div = 1'b0;
332
    end
333
//operation rotate left with carry and swap nibbles
334
    `OC8051_ALU_RLC: begin
335
      des_acc = {src1[6:0], srcCy};
336
      des1 = src1 ;
337
      des2 = {src1[3:0], src1[7:4]};
338
      desCy = src1[7];
339
      desAc = 1'b0;
340
      desOv = 1'b0;
341
      enable_mul = 1'b0;
342
      enable_div = 1'b0;
343
    end
344
//operation rotate right
345
    `OC8051_ALU_RR: begin
346
      des_acc = {src1[0], src1[7:1]};
347
      des1 = src1 ;
348
      des2 = 8'h00;
349
      desCy = srcCy & !bit_in;
350
      desAc = 1'b0;
351
      desOv = 1'b0;
352
      enable_mul = 1'b0;
353
      enable_div = 1'b0;
354
    end
355
//operation rotate right with carry
356
    `OC8051_ALU_RRC: begin
357
      des_acc = {srcCy, src1[7:1]};
358
      des1 = src1 ;
359
      des2 = 8'h00;
360
      desCy = src1[0];
361
      desAc = 1'b0;
362
      desOv = 1'b0;
363
      enable_mul = 1'b0;
364
      enable_div = 1'b0;
365
    end
366
//operation pcs Add
367
    `OC8051_ALU_INC: begin
368
      if (srcCy) begin
369
        des_acc = dec[7:0];
370
        des1 = dec[7:0];
371
        des2 = dec[15:8];
372
      end else begin
373
        des_acc = inc[7:0];
374
        des1 = inc[7:0];
375
        des2 = inc[15:8];
376
      end
377
      desCy = 1'b0;
378
      desAc = 1'b0;
379
      desOv = 1'b0;
380
      enable_mul = 1'b0;
381
      enable_div = 1'b0;
382
    end
383
//operation exchange
384
//if carry = 0 exchange low order digit
385
    `OC8051_ALU_XCH: begin
386
      if (srcCy)
387
      begin
388
        des_acc = src2;
389
        des1 = src2;
390
        des2 = src1;
391
      end else begin
392
        des_acc = {src1[7:4],src2[3:0]};
393
        des1 = {src1[7:4],src2[3:0]};
394
        des2 = {src2[7:4],src1[3:0]};
395
      end
396
      desCy = 1'b0;
397
      desAc = 1'b0;
398
      desOv = 1'b0;
399
      enable_mul = 1'b0;
400
      enable_div = 1'b0;
401
    end
402
    `OC8051_ALU_NOP: begin
403
      des_acc = src1;
404
      des1 = src1;
405
      des2 = src2;
406
      desCy = srcCy;
407
      desAc = srcAc;
408
      desOv = 1'b0;
409
      enable_mul = 1'b0;
410
      enable_div = 1'b0;
411
    end
412
  endcase
413
end
414
 
415
endmodule

powered by: WebSVN 2.1.0

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