§ Описание входов модуля

  • alumode - режим работы АЛУ
  • opsize - размер входящих данных (16/32)
  • isize - размер данных (8/16)
  • op1 - первый операнд
  • op2 - второй операнд
  • flags - входящие флаги
  • result - результат
  • flags_o - исходящие флаги
  • daa_r - результат десятичных коррекции (daa/das/aaa/aas)
  • flags_d - исходящие флаги для десятичной коррекции

§ Код модуля

1module alu
2(
3    // Входящие данные
4    input   wire        isize,
5    input   wire        opsize,
6    input   wire [ 2:0] alumode,
7    input   wire [31:0] op1,
8    input   wire [31:0] op2,
9    input   wire [11:0] flags,
10
11    // Исходящие данные
12    output  wire [31:0] result,
13    output  reg  [11:0] flags_o,
14    output  reg  [15:0] daa_r,
15    output  reg  [11:0] flags_d
16);
17
18assign result = isize ? (opsize ? res[31:0] : res[15:0]) : res[7:0];
19
20reg [32:0] res;
21
22// Верхний бит 7, 15 или 31
23wire [4:0] signx = isize ? (opsize ? 31 : 15) : 7;
24
25wire parity  = ~^res[7:0];
26wire zerof   = isize ? (opsize ? ~|res : ~|res[15:0]) : ~|res[7:0];
27wire carryf  = res[signx + 1];
28wire signf   = res[signx];
29wire auxf    = op1[4]^op2[4]^res[4];
30
31// Самая хитрая логика из всего тут
32wire add_o   = (op1[signx] == op2[signx]) & (op1[signx] ^ res[signx]);
33wire sub_o   = (op1[signx] != op2[signx]) & (op1[signx] ^ res[signx]);
34
35// Десятичная коррекция
36reg       daa_a;
37reg       daa_c;
38reg       daa_x;
39reg [8:0] daa_i;
40reg [7:0] daa_h;
41
42// Общие АЛУ
43always @* begin
44
45    case (alumode)
46
47        /* ADD */ 0: res = op1 + op2;
48        /* OR  */ 1: res = op1 | op2;
49        /* ADC */ 2: res = op1 + op2 + flags[0];
50        /* SBB */ 3: res = op1 - op2 - flags[0];
51        /* AND */ 4: res = op1 & op2;
52        /* SUB */ 5,
53        /* CMP */ 7: res = op1 - op2;
54        /* XOR */ 6: res = op1 ^ op2;
55
56    endcase
57
58    case (alumode)
59
60        // ADD | ADC
61        0, 2: flags_o = {
62
63            /* O */ add_o,
64            /* D */ flags[10],
65            /* I */ flags[9],
66            /* T */ flags[8],
67            /* S */ signf,
68            /* Z */ zerof,
69            /* 0 */ 1'b0,
70            /* A */ auxf,
71            /* 0 */ 1'b0,
72            /* P */ parity,
73            /* 1 */ 1'b1,
74            /* C */ carryf
75        };
76
77        // SBB | SUB | CMP
78        3, 5, 7: flags_o = {
79
80            /* O */ sub_o,
81            /* D */ flags[10],
82            /* I */ flags[9],
83            /* T */ flags[8],
84            /* S */ signf,
85            /* Z */ zerof,
86            /* 0 */ 1'b0,
87            /* A */ auxf,
88            /* 0 */ 1'b0,
89            /* P */ parity,
90            /* 1 */ 1'b1,
91            /* C */ carryf
92        };
93
94        // OR, AND, XOR одинаковые флаги
95        1, 4, 6: flags_o = {
96
97            /* O */ 1'b0,
98            /* D */ flags[10],
99            /* I */ flags[9],
100            /* T */ flags[8],
101            /* S */ signf,
102            /* Z */ zerof,
103            /* 0 */ 1'b0,
104            /* A */ 1'b0,
105            /* 0 */ 1'b0,
106            /* P */ parity,
107            /* 1 */ 1'b1,
108            /* C */ 1'b0
109        };
110
111    endcase
112
113
114end
115
116// Десятичная коррекция
117always @* begin
118
119    daa_r   = op1[7:0];
120    flags_d = flags;
121
122    case (alumode)
123
124        // DAA, DAS
125        0, 1: begin
126
127            daa_c = flags[0];
128            daa_a = flags[4];
129            daa_i = op1[7:0];
130
131            // Младший ниббл
132            if (op1[3:0] > 9 || flags[4]) begin
133                daa_i = alumode[0] ? op1[7:0]-6 : op1[7:0]+6;
134                daa_c = daa_i[8];
135                daa_a = 1;
136            end
137
138            daa_r = daa_i[7:0];
139            daa_x = daa_c;
140
141            // Старший ниббл
142            if (daa_c || daa_i[7:0] > 8'h9F) begin
143                daa_r = alumode[0] ? daa_i[7:0]-8'h60 : daa_i[7:0]+8'h60;
144                daa_x = 1;
145            end
146
147            flags_d[7] =   daa_r[7];        // S
148            flags_d[6] = ~|daa_r[7:0];      // Z
149            flags_d[4] =   daa_a;           // A
150            flags_d[2] = ~^daa_r[7:0];      // P
151            flags_d[0] =   daa_x;           // C
152
153        end
154
155        // AAA, AAS
156        2, 3: begin
157
158            daa_i = op1[ 7:0];
159            daa_r = op1[15:0];
160
161            if (flags[4] || op1[3:0] > 9) begin
162
163                daa_i = alumode[0] ? op1[ 7:0] - 6 : op1[ 7:0] + 6;
164                daa_h = alumode[0] ? op1[15:8] - 1 : op1[15:8] + 1;
165                daa_r = {daa_h, 4'h0, daa_i[3:0]};
166
167                flags_d[4] = 1; // AF=1
168                flags_d[0] = 1; // CF=1
169
170            end
171            else begin flags_d[4] = 0; flags_d[0] = 0; end
172
173        end
174
175    endcase
176
177end
178
179endmodule