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

Subversion Repositories 8051

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

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 179 simont
// Revision 1.18  2003/07/01 18:51:11  simont
50
// x replaced with 0.
51
//
52 178 simont
// Revision 1.17  2003/06/09 16:51:16  simont
53
// fix bug in DA operation.
54
//
55 171 simont
// Revision 1.16  2003/06/03 17:15:06  simont
56
// sub_result output added.
57
//
58 152 simont
// Revision 1.15  2003/05/07 12:31:53  simont
59
// add wire sub_result, conect it to des_acc and des1.
60
//
61 143 simont
// Revision 1.14  2003/05/05 15:46:36  simont
62
// add aditional alu destination to solve critical path.
63
//
64 139 simont
// Revision 1.13  2003/04/29 08:35:12  simont
65
// fix bug in substraction.
66
//
67 133 simont
// Revision 1.12  2003/04/25 17:15:51  simont
68
// change branch instruction execution (reduse needed clock periods).
69
//
70 132 simont
// Revision 1.11  2003/04/14 14:29:42  simont
71
// fiz bug iv pcs operation.
72
//
73 123 simont
// Revision 1.10  2003/01/13 14:14:40  simont
74
// replace some modules
75
//
76 82 simont
// Revision 1.9  2002/09/30 17:33:59  simont
77
// prepared header
78
//
79
//
80
 
81
// synopsys translate_off
82
`include "oc8051_timescale.v"
83
// synopsys translate_on
84
 
85
`include "oc8051_defines.v"
86
 
87
 
88
 
89 139 simont
module oc8051_alu (clk, rst, op_code, src1, src2, src3, srcCy, srcAc, bit_in,
90 152 simont
                  des1, des2, des_acc, desCy, desAc, desOv, sub_result);
91 82 simont
//
92
// op_code      (in)  operation code [oc8051_decoder.alu_op -r]
93
// src1         (in)  first operand [oc8051_alu_src1_sel.des]
94
// src2         (in)  second operand [oc8051_alu_src2_sel.des]
95
// src3         (in)  third operand [oc8051_alu_src3_sel.des]
96
// srcCy        (in)  carry input [oc8051_cy_select.data_out]
97
// srcAc        (in)  auxiliary carry input [oc8051_psw.data_out[6] ]
98
// bit_in       (in)  bit input, used for logic operatins on bits [oc8051_ram_sel.bit_out]
99
// des1         (out)
100
// des2         (out)
101
// 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]
102
// desAc        (out) auxiliary carry output [oc8051_psw.ac_in]
103
// desOv        (out) Overflow output [oc8051_psw.ov_in]
104
//
105
 
106 139 simont
input        srcCy, srcAc, bit_in, clk, rst;
107
input  [3:0] op_code;
108
input  [7:0] src1, src2, src3;
109
output       desCy, desAc, desOv;
110 152 simont
output [7:0] des1, des2, des_acc, sub_result;
111 82 simont
 
112
reg desCy, desAc, desOv;
113 139 simont
reg [7:0] des1, des2, des_acc;
114 82 simont
 
115
 
116
//
117
//add
118
//
119
wire [4:0] add1, add2, add3, add4;
120
wire [3:0] add5, add6, add7, add8;
121
wire [1:0] add9, adda, addb, addc;
122
 
123
//
124
//sub
125
//
126
wire [4:0] sub1, sub2, sub3, sub4;
127
wire [3:0] sub5, sub6, sub7, sub8;
128
wire [1:0] sub9, suba, subb, subc;
129 143 simont
wire [7:0] sub_result;
130 82 simont
 
131
//
132
//mul
133
//
134
  wire [7:0] mulsrc1, mulsrc2;
135
  wire mulOv;
136
  reg enable_mul;
137
 
138
//
139
//div
140
//
141
wire [7:0] divsrc1,divsrc2;
142
wire divOv;
143
reg enable_div;
144
 
145
//
146
//da
147
//
148 171 simont
reg da_tmp, da_tmp1;
149 82 simont
//reg [8:0] da1;
150
 
151 139 simont
//
152
// inc
153
//
154
wire [15:0] inc, dec;
155
 
156 82 simont
oc8051_multiply oc8051_mul1(.clk(clk), .rst(rst), .enable(enable_mul), .src1(src1), .src2(src2), .des1(mulsrc1), .des2(mulsrc2), .desOv(mulOv));
157
oc8051_divide oc8051_div1(.clk(clk), .rst(rst), .enable(enable_div), .src1(src1), .src2(src2), .des1(divsrc1), .des2(divsrc2), .desOv(divOv));
158
 
159
/* Add */
160
assign add1 = {1'b0,src1[3:0]};
161
assign add2 = {1'b0,src2[3:0]};
162
assign add3 = {3'b000,srcCy};
163
assign add4 = add1+add2+add3;
164
 
165
assign add5 = {1'b0,src1[6:4]};
166
assign add6 = {1'b0,src2[6:4]};
167
assign add7 = {1'b0,1'b0,1'b0,add4[4]};
168
assign add8 = add5+add6+add7;
169
 
170
assign add9 = {1'b0,src1[7]};
171
assign adda = {1'b0,src2[7]};
172
assign addb = {1'b0,add8[3]};
173
assign addc = add9+adda+addb;
174
 
175
/* Sub */
176
assign sub1 = {1'b1,src1[3:0]};
177
assign sub2 = {1'b0,src2[3:0]};
178
assign sub3 = {1'b0,1'b0,1'b0,srcCy};
179
assign sub4 = sub1-sub2-sub3;
180
 
181
assign sub5 = {1'b1,src1[6:4]};
182
assign sub6 = {1'b0,src2[6:4]};
183
assign sub7 = {1'b0,1'b0,1'b0, !sub4[4]};
184
assign sub8 = sub5-sub6-sub7;
185
 
186
assign sub9 = {1'b1,src1[7]};
187
assign suba = {1'b0,src2[7]};
188
assign subb = {1'b0,!sub8[3]};
189
assign subc = sub9-suba-subb;
190
 
191 143 simont
assign sub_result = {subc[0],sub8[2:0],sub4[3:0]};
192
 
193 139 simont
/* inc */
194
assign inc = {src2, src1} + {15'h0, 1'b1};
195
assign dec = {src2, src1} - {15'h0, 1'b1};
196 82 simont
 
197 139 simont
always @(op_code or src1 or src2 or srcCy or srcAc or bit_in or src3 or mulsrc1
198
      or mulsrc2 or mulOv or divsrc1 or divsrc2 or divOv or addc or add8 or add4
199 143 simont
      or sub4 or sub8 or subc or da_tmp or inc or dec or sub_result)
200 82 simont
begin
201
 
202 179 simont
  case (op_code) /* synopsys full_case parallel_case */
203 82 simont
//operation add
204
    `OC8051_ALU_ADD: begin
205 139 simont
      des_acc = {addc[0],add8[2:0],add4[3:0]};
206
      des1 = src1;
207 82 simont
      des2 = src3+ {7'b0, addc[1]};
208
      desCy = addc[1];
209
      desAc = add4[4];
210
      desOv = addc[1] ^ add8[3];
211
 
212
      enable_mul = 1'b0;
213
      enable_div = 1'b0;
214
    end
215
//operation subtract
216
    `OC8051_ALU_SUB: begin
217 143 simont
      des_acc = sub_result;
218 152 simont
//      des1 = sub_result;
219
      des1 = 8'h00;
220 82 simont
      des2 = 8'h00;
221
      desCy = !subc[1];
222
      desAc = !sub4[4];
223 133 simont
      desOv = !subc[1] ^ !sub8[3];
224 82 simont
 
225
      enable_mul = 1'b0;
226
      enable_div = 1'b0;
227
    end
228
//operation multiply
229
    `OC8051_ALU_MUL: begin
230 139 simont
      des_acc = mulsrc1;
231
      des1 = src1;
232 82 simont
      des2 = mulsrc2;
233
      desOv = mulOv;
234
      desCy = 1'b0;
235 178 simont
      desAc = 1'b0;
236 82 simont
      enable_mul = 1'b1;
237
      enable_div = 1'b0;
238
    end
239
//operation divide
240
    `OC8051_ALU_DIV: begin
241 139 simont
      des_acc = divsrc1;
242
      des1 = src1;
243 82 simont
      des2 = divsrc2;
244
      desOv = divOv;
245 178 simont
      desAc = 1'b0;
246 82 simont
      desCy = 1'b0;
247
      enable_mul = 1'b0;
248
      enable_div = 1'b1;
249
    end
250
//operation decimal adjustment
251
    `OC8051_ALU_DA: begin
252
 
253 139 simont
      if (srcAc==1'b1 | src1[3:0]>4'b1001) {da_tmp, des_acc[3:0]} = {1'b0, src1[3:0]}+ 5'b00110;
254
      else {da_tmp, des_acc[3:0]} = {1'b0, src1[3:0]};
255 82 simont
 
256 171 simont
      if (srcCy | da_tmp | src1[7:4]>4'b1001)
257
        {da_tmp1, des_acc[7:4]} = {srcCy, src1[7:4]}+ 5'b00110 + {4'b0, da_tmp};
258
      else {da_tmp1, des_acc[7:4]} = {srcCy, src1[7:4]} + {4'b0, da_tmp};
259 82 simont
 
260 171 simont
      desCy = da_tmp | da_tmp1;
261 139 simont
      des1 = src1;
262 82 simont
      des2 = 8'h00;
263
      desAc = 1'b0;
264
      desOv = 1'b0;
265
      enable_mul = 1'b0;
266
      enable_div = 1'b0;
267
    end
268
//operation not
269
// bit operation not
270
    `OC8051_ALU_NOT: begin
271 139 simont
      des_acc = ~src1;
272 82 simont
      des1 = ~src1;
273
      des2 = 8'h00;
274
      desCy = !srcCy;
275 178 simont
      desAc = 1'b0;
276
      desOv = 1'b0;
277 82 simont
      enable_mul = 1'b0;
278
      enable_div = 1'b0;
279
    end
280
//operation and
281
//bit operation and
282
    `OC8051_ALU_AND: begin
283 139 simont
      des_acc = src1 & src2;
284 82 simont
      des1 = src1 & src2;
285
      des2 = 8'h00;
286
      desCy = srcCy & bit_in;
287 178 simont
      desAc = 1'b0;
288
      desOv = 1'b0;
289 82 simont
      enable_mul = 1'b0;
290
      enable_div = 1'b0;
291
    end
292
//operation xor
293
// bit operation xor
294
    `OC8051_ALU_XOR: begin
295 139 simont
      des_acc = src1 ^ src2;
296 82 simont
      des1 = src1 ^ src2;
297
      des2 = 8'h00;
298
      desCy = srcCy ^ bit_in;
299 178 simont
      desAc = 1'b0;
300
      desOv = 1'b0;
301 82 simont
      enable_mul = 1'b0;
302
      enable_div = 1'b0;
303
    end
304
//operation or
305
// bit operation or
306
    `OC8051_ALU_OR: begin
307 139 simont
      des_acc = src1 | src2;
308 82 simont
      des1 = src1 | src2;
309
      des2 = 8'h00;
310
      desCy = srcCy | bit_in;
311 178 simont
      desAc = 1'b0;
312
      desOv = 1'b0;
313 82 simont
      enable_mul = 1'b0;
314
      enable_div = 1'b0;
315
    end
316
//operation rotate left
317
// bit operation cy= cy or (not ram)
318
    `OC8051_ALU_RL: begin
319 139 simont
      des_acc = {src1[6:0], src1[7]};
320
      des1 = src1 ;
321 82 simont
      des2 = 8'h00;
322
      desCy = srcCy | !bit_in;
323 178 simont
      desAc = 1'b0;
324
      desOv = 1'b0;
325 82 simont
      enable_mul = 1'b0;
326
      enable_div = 1'b0;
327
    end
328
//operation rotate left with carry and swap nibbles
329
    `OC8051_ALU_RLC: begin
330 139 simont
      des_acc = {src1[6:0], srcCy};
331
      des1 = src1 ;
332 82 simont
      des2 = {src1[3:0], src1[7:4]};
333
      desCy = src1[7];
334
      desAc = 1'b0;
335
      desOv = 1'b0;
336
      enable_mul = 1'b0;
337
      enable_div = 1'b0;
338
    end
339
//operation rotate right
340
    `OC8051_ALU_RR: begin
341 139 simont
      des_acc = {src1[0], src1[7:1]};
342
      des1 = src1 ;
343 82 simont
      des2 = 8'h00;
344
      desCy = srcCy & !bit_in;
345
      desAc = 1'b0;
346
      desOv = 1'b0;
347
      enable_mul = 1'b0;
348
      enable_div = 1'b0;
349
    end
350
//operation rotate right with carry
351
    `OC8051_ALU_RRC: begin
352 139 simont
      des_acc = {srcCy, src1[7:1]};
353
      des1 = src1 ;
354 82 simont
      des2 = 8'h00;
355
      desCy = src1[0];
356
      desAc = 1'b0;
357
      desOv = 1'b0;
358
      enable_mul = 1'b0;
359
      enable_div = 1'b0;
360
    end
361
//operation pcs Add
362 139 simont
    `OC8051_ALU_INC: begin
363
      if (srcCy) begin
364
        des_acc = dec[7:0];
365
        des1 = dec[7:0];
366
        des2 = dec[15:8];
367
      end else begin
368
        des_acc = inc[7:0];
369
        des1 = inc[7:0];
370
        des2 = inc[15:8];
371
      end
372 82 simont
      desCy = 1'b0;
373
      desAc = 1'b0;
374
      desOv = 1'b0;
375
      enable_mul = 1'b0;
376
      enable_div = 1'b0;
377 139 simont
    end
378 82 simont
//operation exchange
379
//if carry = 0 exchange low order digit
380
    `OC8051_ALU_XCH: begin
381
      if (srcCy)
382
      begin
383 139 simont
        des_acc = src2;
384 82 simont
        des1 = src2;
385
        des2 = src1;
386
      end else begin
387 139 simont
        des_acc = {src1[7:4],src2[3:0]};
388 82 simont
        des1 = {src1[7:4],src2[3:0]};
389
        des2 = {src2[7:4],src1[3:0]};
390
      end
391
      desCy = 1'b0;
392
      desAc = 1'b0;
393
      desOv = 1'b0;
394
      enable_mul = 1'b0;
395
      enable_div = 1'b0;
396
    end
397 179 simont
    `OC8051_ALU_NOP: begin
398 139 simont
      des_acc = src1;
399 82 simont
      des1 = src1;
400
      des2 = src2;
401
      desCy = srcCy;
402
      desAc = srcAc;
403 123 simont
      desOv = 1'b0;
404 82 simont
      enable_mul = 1'b0;
405
      enable_div = 1'b0;
406
    end
407
  endcase
408
end
409
 
410
endmodule

powered by: WebSVN 2.1.0

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