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

Subversion Repositories 8051

[/] [8051/] [trunk/] [rtl/] [verilog/] [oc8051_alu.v] - Blame information for rev 139

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

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

powered by: WebSVN 2.1.0

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