§ Описание входов модуля
- alumode - режим работы АЛУ
- opsize - размер входящих данных (16/32)
- isize - размер данных (8/16)
- op1 - первый операнд
- op2 - второй операнд
- flags - входящие флаги
- result - результат
- flags_o - исходящие флаги
- daa_r - результат десятичных коррекции (daa/das/aaa/aas)
- flags_d - исходящие флаги для десятичной коррекции
§ Код модуля
module alu ( // Входящие данные input wire isize, input wire opsize, input wire [ 2:0] alumode, input wire [31:0] op1, input wire [31:0] op2, input wire [11:0] flags, // Исходящие данные output wire [31:0] result, output reg [11:0] flags_o, output reg [15:0] daa_r, output reg [11:0] flags_d ); assign result = isize ? (opsize ? res[31:0] : res[15:0]) : res[7:0]; reg [32:0] res; // Верхний бит 7, 15 или 31 wire [4:0] signx = isize ? (opsize ? 31 : 15) : 7; wire parity = ~^res[7:0]; wire zerof = isize ? (opsize ? ~|res : ~|res[15:0]) : ~|res[7:0]; wire carryf = res[signx + 1]; wire signf = res[signx]; wire auxf = op1[4]^op2[4]^res[4]; // Самая хитрая логика из всего тут wire add_o = (op1[signx] == op2[signx]) & (op1[signx] ^ res[signx]); wire sub_o = (op1[signx] != op2[signx]) & (op1[signx] ^ res[signx]); // Десятичная коррекция reg daa_a; reg daa_c; reg daa_x; reg [8:0] daa_i; reg [7:0] daa_h; // Общие АЛУ always @* begin case (alumode) /* ADD */ 0: res = op1 + op2; /* OR */ 1: res = op1 | op2; /* ADC */ 2: res = op1 + op2 + flags[0]; /* SBB */ 3: res = op1 - op2 - flags[0]; /* AND */ 4: res = op1 & op2; /* SUB */ 5, /* CMP */ 7: res = op1 - op2; /* XOR */ 6: res = op1 ^ op2; endcase case (alumode) // ADD | ADC 0, 2: flags_o = { /* O */ add_o, /* D */ flags[10], /* I */ flags[9], /* T */ flags[8], /* S */ signf, /* Z */ zerof, /* 0 */ 1'b0, /* A */ auxf, /* 0 */ 1'b0, /* P */ parity, /* 1 */ 1'b1, /* C */ carryf }; // SBB | SUB | CMP 3, 5, 7: flags_o = { /* O */ sub_o, /* D */ flags[10], /* I */ flags[9], /* T */ flags[8], /* S */ signf, /* Z */ zerof, /* 0 */ 1'b0, /* A */ auxf, /* 0 */ 1'b0, /* P */ parity, /* 1 */ 1'b1, /* C */ carryf }; // OR, AND, XOR одинаковые флаги 1, 4, 6: flags_o = { /* O */ 1'b0, /* D */ flags[10], /* I */ flags[9], /* T */ flags[8], /* S */ signf, /* Z */ zerof, /* 0 */ 1'b0, /* A */ 1'b0, /* 0 */ 1'b0, /* P */ parity, /* 1 */ 1'b1, /* C */ 1'b0 }; endcase end // Десятичная коррекция always @* begin daa_r = op1[7:0]; flags_d = flags; case (alumode) // DAA, DAS 0, 1: begin daa_c = flags[0]; daa_a = flags[4]; daa_i = op1[7:0]; // Младший ниббл if (op1[3:0] > 9 || flags[4]) begin daa_i = alumode[0] ? op1[7:0]-6 : op1[7:0]+6; daa_c = daa_i[8]; daa_a = 1; end daa_r = daa_i[7:0]; daa_x = daa_c; // Старший ниббл if (daa_c || daa_i[7:0] > 8'h9F) begin daa_r = alumode[0] ? daa_i[7:0]-8'h60 : daa_i[7:0]+8'h60; daa_x = 1; end flags_d[7] = daa_r[7]; // S flags_d[6] = ~|daa_r[7:0]; // Z flags_d[4] = daa_a; // A flags_d[2] = ~^daa_r[7:0]; // P flags_d[0] = daa_x; // C end // AAA, AAS 2, 3: begin daa_i = op1[ 7:0]; daa_r = op1[15:0]; if (flags[4] || op1[3:0] > 9) begin daa_i = alumode[0] ? op1[ 7:0] - 6 : op1[ 7:0] + 6; daa_h = alumode[0] ? op1[15:8] - 1 : op1[15:8] + 1; daa_r = {daa_h, 4'h0, daa_i[3:0]}; flags_d[4] = 1; // AF=1 flags_d[0] = 1; // CF=1 end else begin flags_d[4] = 0; flags_d[0] = 0; end end endcase end endmodule
7 окт, 2021
© 2007-2023 Тот прав, кто знает то, что такое права