/* Режимы работы АЛУ --------------------------------------------------------------------- 0 LDI 9 EOR 11 LSR 19 MULSU 1 CPC A OR 12 ROR 2 SBC B <SREG> 13 DEC 3 ADD C COM 14 ADIW 5 CP D NEG 15 SBIW 6 SUB E SWAP 16 BLD 7 ADC F INC 17 MUL 8 AND 10 ASR 18 MULS --------------------------------------------------------------------- */ module avralu ( // Входные данные на обработку input [ 4:0] mode, // режим input [ 7:0] dst, // dst input [ 7:0] src, // src input [15:0] src16, // src (16 бит) input [ 7:0] si, // sreg // Результат output reg [ 7:0] so, // Исходящие флаги output reg [ 7:0] resb, // Результат 8 бит output reg [15:0] resw // Результат 16 бит ); // Вычисления wire [7:0] sub = dst - src; // Вычитание wire [7:0] add = dst + src; // Сложение wire [8:0] sbc = dst - src - si[0]; // Вычитание с заемом wire [7:0] adc = dst + src + si[0]; // Сложение с заемом wire [7:0] lsr = { 1'b0, dst[7:1]}; // Логический сдвиг вправо wire [7:0] ror = { si[0], dst[7:1]}; // Сдвиг вправо с заемом wire [7:0] asr = {dst[7], dst[7:1]}; // Арифметический сдвиг вправо wire [7:0] neg = -dst; // Отрицательное значение wire [7:0] inc = dst + 1; // Инкремент wire [7:0] dec = dst - 1; // Декремент wire [7:0] com = dst ^ 8'hFF; // Комплементация wire [7:0] swap = {dst[3:0], dst[7:4]}; // Обмен нибблами reg carry; // 16 битные вычисления wire [15:0] adiw = src16 + src; wire [15:0] sbiw = src16 - src; wire [15:0] mul = dst[7:0] * src[7:0]; wire [15:0] mulsu = {{8{dst[7]}}, dst[7:0]} * src[7:0]; wire [15:0] muls = {{8{dst[7]}}, dst[7:0]} * {{8{src[7]}}, src[7:0]}; // Флаги переполнения после сложения и вычитания wire add_flag_v = (dst[7] & src[7] & !resb[7]) | (!dst[7] & !src[7] & resb[7]); wire sub_flag_v = (dst[7] & !src[7] & !resb[7]) | (!dst[7] & src[7] & resb[7]); wire neg_flag_v = (resb == 8'h80); // Флаги половинного переполнения после сложения и вычитания wire add_flag_h = ( dst[3] & src[3]) | (src[3] & !resb[3]) | (!resb[3] & dst[3]); wire sub_flag_h = (!dst[3] & src[3]) | (src[3] & resb[3]) | ( resb[3] & !dst[3]); wire neg_flag_h = dst[3] | (dst[3] & resb[3]) | resb[3]; // Флаги ADIW, SBIW wire adiw_v = !src16[15] & resw [15]; wire adiw_c = !resw [15] & src16[15]; // Логические флаги wire [7:0] set_logic_flag = { /* i */ si[7], /* t */ si[6], /* h */ si[5], /* s */ resb[7], /* v */ 1'b0, /* n */ resb[7], /* z */ resb[7:0] == 0, /* c */ si[0] }; // Флаги после вычитания с переносом wire [7:0] set_subcarry_flag = { /* i */ si[7], /* t */ si[6], /* h */ sub_flag_h, /* s */ sub_flag_v ^ resb[7], /* v */ sub_flag_v, /* n */ resb[7], /* z */ (resb[7:0] == 0) & si[1], /* c */ sbc[8] }; // Флаги после вычитания wire [7:0] set_subtract_flag = { /* i */ si[7], /* t */ si[6], /* h */ sub_flag_h, /* s */ sub_flag_v ^ resb[7], /* v */ sub_flag_v, /* n */ resb[7], /* z */ (resb[7:0] == 0), /* c */ dst < src }; // Флаги после COM wire [7:0] set_com_flag = { /* i */ si[7], /* t */ si[6], /* h */ si[5], /* s */ resb[7], /* v */ 1'b0, /* n */ resb[7], /* z */ (resb[7:0] == 0), /* c */ 1'b1 }; // Флаги после NEG wire [7:0] set_neg_flag = { /* i */ si[7], /* t */ si[6], /* h */ neg_flag_h, /* s */ neg_flag_v ^ resb[7], /* v */ neg_flag_v, /* n */ resb[7], /* z */ (resb[7:0] == 0), /* c */ dst != 0 }; // Флаги после сложения с переносом wire [7:0] set_add_flag = { /* i */ si[7], /* t */ si[6], /* h */ add_flag_h, /* s */ add_flag_v ^ resb[7], /* v */ add_flag_v, /* n */ resb[7], /* z */ (resb[7:0] == 0), /* c */ dst + src + carry >= 9'h100 }; // Флаги после логической операции сдвига вправо wire [7:0] set_lsr_flag = { /* i */ si[7], /* t */ si[6], /* h */ si[5], /* s */ dst[0], /* v */ resb[7] ^ dst[0], /* n */ resb[7], /* z */ (resb[7:0] == 0), /* c */ dst[0] }; // Флаги после INC wire [7:0] set_inc_flag = { /* i */ si[7], /* t */ si[6], /* h */ si[5], /* s */ (resb == 8'h80) ^ resb[7], /* v */ (resb == 8'h80), /* n */ resb[7], /* z */ (resb[7:0] == 0), /* c */ si[0] }; // Флаги после DEC wire [7:0] set_dec_flag = { /* i */ si[7], /* t */ si[6], /* h */ si[5], /* s */ (resb == 8'h7F) ^ resb[7], /* v */ (resb == 8'h7F), /* n */ resb[7], /* z */ (resb[7:0] == 0), /* c */ si[0] }; // Флаги после ADIW wire [7:0] set_adiw_flag = { /* i */ si[7], /* t */ si[6], /* h */ si[5], /* s */ adiw_v ^ resw[15], /* v */ adiw_v, /* n */ resw[15], /* z */ (resw[15:0] == 0), /* c */ adiw_c }; // Флаги после SBIW wire [7:0] set_sbiw_flag = { /* i */ si[7], /* t */ si[6], /* h */ si[5], /* s */ adiw_v ^ resw[15], /* v */ adiw_v, /* n */ resw[15], /* z */ (resw[15:0] == 0), /* c */ adiw_v }; // Флаги после MUL wire [7:0] set_mul_flag = { /* i */ si[7], /* t */ si[6], /* h */ si[5], /* s */ si[7], /* v */ si[7], /* n */ si[7], /* z */ (mul[15:0] == 0), /* c */ mul[15] }; always @(*) begin so = si; carry = 0; case (mode) /* LDI */ 0: begin resb = src; end /* CPC */ 1: begin resb = sbc[7:0]; so = set_subcarry_flag; end /* SBC */ 2: begin resb = sbc[7:0]; so = set_subcarry_flag; end /* ADD */ 3: begin resb = add; so = set_add_flag; carry = 0; end /* CP */ 5: begin resb = sub; so = set_subtract_flag; end /* SUB */ 6: begin resb = sub; so = set_subtract_flag; end /* ADC */ 7: begin resb = adc; so = set_add_flag; carry = si[0]; end /* AND */ 8: begin resb = dst & src; so = set_logic_flag; end /* EOR */ 9: begin resb = dst ^ src; so = set_logic_flag; end /* OR */ 10: begin resb = dst | src; so = set_logic_flag; end /* SREG */ 11: begin so = src; end /* COM */ 12: begin resb = com; so = set_com_flag; end /* NEG */ 13: begin resb = neg; so = set_neg_flag; end /* SWAP */ 14: begin resb = swap; end /* INC */ 15: begin resb = inc; so = set_inc_flag; end /* ASR */ 16: begin resb = asr; so = set_lsr_flag; end /* LSR */ 17: begin resb = lsr; so = set_lsr_flag; end /* ROR */ 18: begin resb = ror; so = set_lsr_flag; end /* DEC */ 19: begin resb = dec; so = set_dec_flag; end /* ADIW */ 20: begin resw = adiw; so = set_adiw_flag; end /* SBIW */ 21: begin resw = sbiw; so = set_sbiw_flag; end /* BLD */ 22: case (src[2:0]) 0: resb = {dst[7:1], si[6]}; 1: resb = {dst[7:2], si[6], dst[ 0]}; 2: resb = {dst[7:3], si[6], dst[1:0]}; 3: resb = {dst[7:4], si[6], dst[2:0]}; 4: resb = {dst[7:5], si[6], dst[3:0]}; 5: resb = {dst[7:6], si[6], dst[4:0]}; 6: resb = {dst[ 7], si[6], dst[5:0]}; 7: resb = { si[6], dst[6:0]}; endcase /* MUL */ 23: begin resw = mul; so = set_mul_flag; end /* MULS */ 24: begin resw = muls; so = set_mul_flag; end /* MULSU */ 25: begin resw = mulsu; so = set_mul_flag; end default: resb = 8'hFF; endcase end endmodule
9 сен, 2021
© 2007-2023 Мыш плющит на работе