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

Subversion Repositories tv80

[/] [tv80/] [trunk/] [rtl/] [core/] [tv80_alu.v] - Blame information for rev 106

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

Line No. Rev Author Line
1 2 ghutchis
//
2
// TV80 8-Bit Microprocessor Core
3
// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org)
4
//
5
// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
6
//
7
// Permission is hereby granted, free of charge, to any person obtaining a 
8
// copy of this software and associated documentation files (the "Software"), 
9
// to deal in the Software without restriction, including without limitation 
10
// the rights to use, copy, modify, merge, publish, distribute, sublicense, 
11
// and/or sell copies of the Software, and to permit persons to whom the 
12
// Software is furnished to do so, subject to the following conditions:
13
//
14
// The above copyright notice and this permission notice shall be included 
15
// in all copies or substantial portions of the Software.
16
//
17
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
18
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
19
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
20
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
21
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
22
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
23
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
 
25
module tv80_alu (/*AUTOARG*/
26
  // Outputs
27
  Q, F_Out,
28
  // Inputs
29
  Arith16, Z16, ALU_Op, IR, ISet, BusA, BusB, F_In
30
  );
31
 
32
  parameter             Mode   = 0;
33
  parameter             Flag_C = 0;
34
  parameter             Flag_N = 1;
35
  parameter             Flag_P = 2;
36
  parameter             Flag_X = 3;
37
  parameter             Flag_H = 4;
38
  parameter             Flag_Y = 5;
39
  parameter             Flag_Z = 6;
40
  parameter             Flag_S = 7;
41
 
42
  input                 Arith16;
43
  input                 Z16;
44
  input [3:0]           ALU_Op ;
45
  input [5:0]           IR;
46
  input [1:0]           ISet;
47
  input [7:0]           BusA;
48
  input [7:0]           BusB;
49
  input [7:0]           F_In;
50
  output [7:0]          Q;
51
  output [7:0]          F_Out;
52
  reg [7:0]             Q;
53
  reg [7:0]             F_Out;
54
 
55
  function [4:0] AddSub4;
56
    input [3:0] A;
57
    input [3:0] B;
58
    input Sub;
59
    input Carry_In;
60
    begin
61 90 ghutchis
      AddSub4 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + {4'h0,Carry_In};
62 2 ghutchis
    end
63
  endfunction // AddSub4
64
 
65
  function [3:0] AddSub3;
66
    input [2:0] A;
67
    input [2:0] B;
68
    input Sub;
69
    input Carry_In;
70
    begin
71 90 ghutchis
      AddSub3 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + {3'h0,Carry_In};
72 2 ghutchis
    end
73
  endfunction // AddSub4
74
 
75
  function [1:0] AddSub1;
76
    input A;
77
    input B;
78
    input Sub;
79
    input Carry_In;
80
    begin
81 90 ghutchis
      AddSub1 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + {1'h0,Carry_In};
82 2 ghutchis
    end
83
  endfunction // AddSub4
84
 
85
  // AddSub variables (temporary signals)
86
  reg UseCarry;
87
  reg Carry7_v;
88
  reg OverFlow_v;
89
  reg HalfCarry_v;
90
  reg Carry_v;
91
  reg [7:0] Q_v;
92
 
93
  reg [7:0] BitMask;
94
 
95
 
96
  always @(/*AUTOSENSE*/ALU_Op or BusA or BusB or F_In or IR)
97
    begin
98
      case (IR[5:3])
99
        3'b000 : BitMask = 8'b00000001;
100
        3'b001 : BitMask = 8'b00000010;
101
        3'b010 : BitMask = 8'b00000100;
102
        3'b011 : BitMask = 8'b00001000;
103
        3'b100 : BitMask = 8'b00010000;
104
        3'b101 : BitMask = 8'b00100000;
105
        3'b110 : BitMask = 8'b01000000;
106
        default: BitMask = 8'b10000000;
107
      endcase // case(IR[5:3])
108
 
109
      UseCarry = ~ ALU_Op[2] && ALU_Op[0];
110
      { HalfCarry_v, Q_v[3:0] } = AddSub4(BusA[3:0], BusB[3:0], ALU_Op[1], ALU_Op[1] ^ (UseCarry && F_In[Flag_C]) );
111
      { Carry7_v, Q_v[6:4]  } = AddSub3(BusA[6:4], BusB[6:4], ALU_Op[1], HalfCarry_v);
112
      { Carry_v, Q_v[7] } = AddSub1(BusA[7], BusB[7], ALU_Op[1], Carry7_v);
113
      OverFlow_v = Carry_v ^ Carry7_v;
114
    end // always @ *
115
 
116
  reg [7:0] Q_t;
117
  reg [8:0] DAA_Q;
118
 
119
  always @ (/*AUTOSENSE*/ALU_Op or Arith16 or BitMask or BusA or BusB
120
            or Carry_v or F_In or HalfCarry_v or IR or ISet
121
            or OverFlow_v or Q_v or Z16)
122
    begin
123
      Q_t = 8'hxx;
124
      DAA_Q = {9{1'bx}};
125
 
126
      F_Out = F_In;
127
      case (ALU_Op)
128
        4'b0000, 4'b0001,  4'b0010, 4'b0011, 4'b0100, 4'b0101, 4'b0110, 4'b0111 :
129
          begin
130
            F_Out[Flag_N] = 1'b0;
131
            F_Out[Flag_C] = 1'b0;
132
 
133
            case (ALU_Op[2:0])
134
 
135
              3'b000, 3'b001 : // ADD, ADC
136
                begin
137
                  Q_t = Q_v;
138
                  F_Out[Flag_C] = Carry_v;
139
                  F_Out[Flag_H] = HalfCarry_v;
140
                  F_Out[Flag_P] = OverFlow_v;
141
                end
142
 
143
              3'b010, 3'b011, 3'b111 : // SUB, SBC, CP
144
                begin
145
                  Q_t = Q_v;
146
                  F_Out[Flag_N] = 1'b1;
147
                  F_Out[Flag_C] = ~ Carry_v;
148
                  F_Out[Flag_H] = ~ HalfCarry_v;
149
                  F_Out[Flag_P] = OverFlow_v;
150
                end
151
 
152
              3'b100 : // AND
153
                begin
154
                  Q_t[7:0] = BusA & BusB;
155
                  F_Out[Flag_H] = 1'b1;
156
                end
157
 
158
              3'b101 : // XOR
159
                begin
160
                  Q_t[7:0] = BusA ^ BusB;
161
                  F_Out[Flag_H] = 1'b0;
162
                end
163
 
164
              default : // OR 3'b110
165
                begin
166
                  Q_t[7:0] = BusA | BusB;
167
                  F_Out[Flag_H] = 1'b0;
168
                end
169
 
170
            endcase // case(ALU_OP[2:0])
171
 
172
            if (ALU_Op[2:0] == 3'b111 )
173
              begin // CP
174
                F_Out[Flag_X] = BusB[3];
175
                F_Out[Flag_Y] = BusB[5];
176
              end
177
            else
178
              begin
179
                F_Out[Flag_X] = Q_t[3];
180
                F_Out[Flag_Y] = Q_t[5];
181
              end
182
 
183
            if (Q_t[7:0] == 8'b00000000 )
184
              begin
185
                F_Out[Flag_Z] = 1'b1;
186
                if (Z16 == 1'b1 )
187
                  begin
188
                    F_Out[Flag_Z] = F_In[Flag_Z];       // 16 bit ADC,SBC
189
                  end
190
              end
191
            else
192
              begin
193
                F_Out[Flag_Z] = 1'b0;
194
              end // else: !if(Q_t[7:0] == 8'b00000000 )
195
 
196
            F_Out[Flag_S] = Q_t[7];
197
            case (ALU_Op[2:0])
198
              3'b000, 3'b001, 3'b010, 3'b011, 3'b111 : // ADD, ADC, SUB, SBC, CP
199
                ;
200
 
201
              default :
202
                F_Out[Flag_P] = ~(^Q_t);
203
            endcase // case(ALU_Op[2:0])
204
 
205
            if (Arith16 == 1'b1 )
206
              begin
207
                F_Out[Flag_S] = F_In[Flag_S];
208
                F_Out[Flag_Z] = F_In[Flag_Z];
209
                F_Out[Flag_P] = F_In[Flag_P];
210
              end
211
          end // case: 4'b0000, 4'b0001,  4'b0010, 4'b0011, 4'b0100, 4'b0101, 4'b0110, 4'b0111
212
 
213
        4'b1100 :
214
          begin
215
            // DAA
216
            F_Out[Flag_H] = F_In[Flag_H];
217
            F_Out[Flag_C] = F_In[Flag_C];
218
            DAA_Q[7:0] = BusA;
219
            DAA_Q[8] = 1'b0;
220
            if (F_In[Flag_N] == 1'b0 )
221
              begin
222
                // After addition
223
                // Alow > 9 || H == 1
224
                if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 )
225
                  begin
226
                    if ((DAA_Q[3:0] > 9) )
227
                      begin
228
                        F_Out[Flag_H] = 1'b1;
229
                      end
230
                    else
231
                      begin
232
                        F_Out[Flag_H] = 1'b0;
233
                      end
234
                    DAA_Q = DAA_Q + 6;
235
                  end // if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 )
236
 
237
                // new Ahigh > 9 || C == 1
238
                if (DAA_Q[8:4] > 9 || F_In[Flag_C] == 1'b1 )
239
                  begin
240
                    DAA_Q = DAA_Q + 96; // 0x60
241
                  end
242
              end
243
            else
244
              begin
245
                // After subtraction
246
                if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 )
247
                  begin
248
                    if (DAA_Q[3:0] > 5 )
249
                      begin
250
                        F_Out[Flag_H] = 1'b0;
251
                      end
252
                    DAA_Q[7:0] = DAA_Q[7:0] - 6;
253
                  end
254
                if (BusA > 153 || F_In[Flag_C] == 1'b1 )
255
                  begin
256
                    DAA_Q = DAA_Q - 352; // 0x160
257
                  end
258
              end // else: !if(F_In[Flag_N] == 1'b0 )
259
 
260
            F_Out[Flag_X] = DAA_Q[3];
261
            F_Out[Flag_Y] = DAA_Q[5];
262
            F_Out[Flag_C] = F_In[Flag_C] || DAA_Q[8];
263
            Q_t = DAA_Q[7:0];
264
 
265
            if (DAA_Q[7:0] == 8'b00000000 )
266
              begin
267
                F_Out[Flag_Z] = 1'b1;
268
              end
269
            else
270
              begin
271
                F_Out[Flag_Z] = 1'b0;
272
              end
273
 
274
            F_Out[Flag_S] = DAA_Q[7];
275
            F_Out[Flag_P] = ~ (^DAA_Q);
276
          end // case: 4'b1100
277
 
278
        4'b1101, 4'b1110 :
279
          begin
280
            // RLD, RRD
281
            Q_t[7:4] = BusA[7:4];
282
            if (ALU_Op[0] == 1'b1 )
283
              begin
284
                Q_t[3:0] = BusB[7:4];
285
              end
286
            else
287
              begin
288
                Q_t[3:0] = BusB[3:0];
289
              end
290
            F_Out[Flag_H] = 1'b0;
291
            F_Out[Flag_N] = 1'b0;
292
            F_Out[Flag_X] = Q_t[3];
293
            F_Out[Flag_Y] = Q_t[5];
294
            if (Q_t[7:0] == 8'b00000000 )
295
              begin
296
                F_Out[Flag_Z] = 1'b1;
297
              end
298
            else
299
              begin
300
                F_Out[Flag_Z] = 1'b0;
301
              end
302
            F_Out[Flag_S] = Q_t[7];
303
            F_Out[Flag_P] = ~(^Q_t);
304
          end // case: when 4'b1101, 4'b1110
305
 
306
        4'b1001 :
307
          begin
308
            // BIT
309
            Q_t[7:0] = BusB & BitMask;
310
            F_Out[Flag_S] = Q_t[7];
311
            if (Q_t[7:0] == 8'b00000000 )
312
              begin
313
                F_Out[Flag_Z] = 1'b1;
314
                F_Out[Flag_P] = 1'b1;
315
              end
316
            else
317
              begin
318
                F_Out[Flag_Z] = 1'b0;
319
                F_Out[Flag_P] = 1'b0;
320
              end
321
            F_Out[Flag_H] = 1'b1;
322
            F_Out[Flag_N] = 1'b0;
323
            F_Out[Flag_X] = 1'b0;
324
            F_Out[Flag_Y] = 1'b0;
325
            if (IR[2:0] != 3'b110 )
326
              begin
327
                F_Out[Flag_X] = BusB[3];
328
                F_Out[Flag_Y] = BusB[5];
329
              end
330
          end // case: when 4'b1001
331
 
332
        4'b1010 :
333
          // SET
334
          Q_t[7:0] = BusB | BitMask;
335
 
336
        4'b1011 :
337
          // RES
338
          Q_t[7:0] = BusB & ~ BitMask;
339
 
340
        4'b1000 :
341
          begin
342
            // ROT
343
            case (IR[5:3])
344
              3'b000 : // RLC
345
                begin
346
                  Q_t[7:1] = BusA[6:0];
347
                  Q_t[0] = BusA[7];
348
                  F_Out[Flag_C] = BusA[7];
349
                end
350
 
351
              3'b010 : // RL
352
                begin
353
                  Q_t[7:1] = BusA[6:0];
354
                  Q_t[0] = F_In[Flag_C];
355
                  F_Out[Flag_C] = BusA[7];
356
                end
357
 
358
              3'b001 : // RRC
359
                begin
360
                  Q_t[6:0] = BusA[7:1];
361
                  Q_t[7] = BusA[0];
362
                  F_Out[Flag_C] = BusA[0];
363
                end
364
 
365
              3'b011 : // RR
366
                begin
367
                  Q_t[6:0] = BusA[7:1];
368
                  Q_t[7] = F_In[Flag_C];
369
                  F_Out[Flag_C] = BusA[0];
370
                end
371
 
372
              3'b100 : // SLA
373
                begin
374
                  Q_t[7:1] = BusA[6:0];
375
                  Q_t[0] = 1'b0;
376
                  F_Out[Flag_C] = BusA[7];
377
                end
378
 
379
              3'b110 : // SLL (Undocumented) / SWAP
380
                begin
381
                  if (Mode == 3 )
382
                    begin
383
                      Q_t[7:4] = BusA[3:0];
384
                      Q_t[3:0] = BusA[7:4];
385
                      F_Out[Flag_C] = 1'b0;
386
                    end
387
                  else
388
                    begin
389
                      Q_t[7:1] = BusA[6:0];
390
                      Q_t[0] = 1'b1;
391
                      F_Out[Flag_C] = BusA[7];
392
                    end // else: !if(Mode == 3 )
393
                end // case: 3'b110
394
 
395
              3'b101 : // SRA
396
                begin
397
                  Q_t[6:0] = BusA[7:1];
398
                  Q_t[7] = BusA[7];
399
                  F_Out[Flag_C] = BusA[0];
400
                end
401
 
402
              default : // SRL
403
                begin
404
                  Q_t[6:0] = BusA[7:1];
405
                  Q_t[7] = 1'b0;
406
                  F_Out[Flag_C] = BusA[0];
407
                end
408
            endcase // case(IR[5:3])
409
 
410
            F_Out[Flag_H] = 1'b0;
411
            F_Out[Flag_N] = 1'b0;
412
            F_Out[Flag_X] = Q_t[3];
413
            F_Out[Flag_Y] = Q_t[5];
414
            F_Out[Flag_S] = Q_t[7];
415
            if (Q_t[7:0] == 8'b00000000 )
416
              begin
417
                F_Out[Flag_Z] = 1'b1;
418
              end
419
            else
420
              begin
421
                F_Out[Flag_Z] = 1'b0;
422
              end
423
            F_Out[Flag_P] = ~(^Q_t);
424
 
425
            if (ISet == 2'b00 )
426
              begin
427
                F_Out[Flag_P] = F_In[Flag_P];
428
                F_Out[Flag_S] = F_In[Flag_S];
429
                F_Out[Flag_Z] = F_In[Flag_Z];
430
              end
431
          end // case: 4'b1000
432
 
433
 
434
        default :
435
          ;
436
 
437
      endcase // case(ALU_Op)
438
 
439
      Q = Q_t;
440
    end // always @ (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16)
441
 
442
endmodule // T80_ALU

powered by: WebSVN 2.1.0

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