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

Subversion Repositories rtf8088

[/] [rtf8088/] [trunk/] [rtl/] [verilog/] [ALU.v] - Diff between revs 6 and 8

Only display areas with differences | Details | Blame | View Log

Rev 6 Rev 8
// ============================================================================
// ============================================================================
//  ALU
//  ALU
//  - perform datapath operations
//  - perform datapath operations
//
//
//
//
//  (C) 2009-2012  Robert Finch
//  (C) 2009-2013  Robert Finch
//  robfinch[remove]@opencores.org
//  robfinch[remove]@finitron.ca
//
//
//
//
// This source file is free software: you can redistribute it and/or modify 
// This source file is free software: you can redistribute it and/or modify 
// it under the terms of the GNU Lesser General Public License as published 
// it under the terms of the GNU Lesser General Public License as published 
// by the Free Software Foundation, either version 3 of the License, or     
// by the Free Software Foundation, either version 3 of the License, or     
// (at your option) any later version.                                      
// (at your option) any later version.                                      
//                                                                          
//                                                                          
// This source file is distributed in the hope that it will be useful,      
// This source file is distributed in the hope that it will be useful,      
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
// GNU General Public License for more details.                             
// GNU General Public License for more details.                             
//                                                                          
//                                                                          
// You should have received a copy of the GNU General Public License        
// You should have received a copy of the GNU General Public License        
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
//
//
//
//
//  Verilog 
//  Verilog 
//
//
// ============================================================================
// ============================================================================
//
//
function carry;
function carry;
        input op;
        input op;
        input a;
        input a;
        input b;
        input b;
        input s;
        input s;
 
 
        begin
        begin
                carry = op ? (~a&b)|(s&~a)|(s&b) : (a&b)|(a&~s)|(b&~s);
                carry = op ? (~a&b)|(s&~a)|(s&b) : (a&b)|(a&~s)|(b&~s);
        end
        end
 
 
endfunction
endfunction
 
 
function overflow;
function overflow;
        input op;
        input op;
        input a;
        input a;
        input b;
        input b;
        input s;
        input s;
 
 
        begin
        begin
                overflow = (op ^ s ^ b) & (~op ^ a ^ b);
                overflow = (op ^ s ^ b) & (~op ^ a ^ b);
        end
        end
 
 
endfunction
endfunction
 
 
reg [15:0] alu_o;
reg [15:0] alu_o;
reg [15:0] a;
reg [15:0] a;
reg [15:0] b;
reg [15:0] b;
wire amsb = w ? a[15] : a[7];
wire amsb = w ? a[15] : a[7];
wire bmsb = w ? b[15] : b[7];
wire bmsb = w ? b[15] : b[7];
wire [15:0] as = {!a[15],a[14:0]};
wire [15:0] as = {!a[15],a[14:0]};
wire [15:0] bs = {!b[15],b[14:0]};
wire [15:0] bs = {!b[15],b[14:0]};
wire signed [15:0] sa = a;
wire signed [15:0] sa = a;
wire signed [15:0] sb = b;
wire signed [15:0] sb = b;
wire signed [7:0] als = a[7:0];
wire signed [7:0] als = a[7:0];
wire signed [7:0] bls = b[7:0];
wire signed [7:0] bls = b[7:0];
wire signed [15:0] p = als * bls;
wire signed [15:0] p = als * bls;
wire signed [31:0] wp = sa * sb;
wire signed [31:0] wp = sa * sb;
wire [15:0] p16 = a[7:0] * b[7:0];
wire [15:0] p16 = a[7:0] * b[7:0];
wire [31:0] p32 = a * b;
wire [31:0] p32 = a * b;
 
 
// Compute AL/10
// Compute AL/10
// - multiply by 1/10 = 26/256
// - multiply by 1/10 = 26/256
wire [15:0] al26 = {al,4'b0} + {al,3'b0} + {al,1'b0};    // * 26
wire [15:0] al26 = {al,4'b0} + {al,3'b0} + {al,1'b0};    // * 26
wire [7:0] aldv10 = al26[15:8];  // 256
wire [7:0] aldv10 = al26[15:8];  // 256
 
 
wire [15:0] cmp_o = a - b;
wire [15:0] cmp_o = a - b;
wire eq  = a == b;
wire eq  = a == b;
wire ltu = a < b;
wire ltu = a < b;
wire lt  = as < bs;
wire lt  = as < bs;
 
 
wire [31:0] shlo = {16'h0000,b} << shftamt;
wire [31:0] shlo = {16'h0000,b} << shftamt;
wire [31:0] shruo = {b,16'h0000} >> shftamt;
wire [31:0] shruo = {b,16'h0000} >> shftamt;
wire [15:0] shro = ~(~b >> shftamt);
wire [15:0] shro = ~(~b >> shftamt);
wire [32:0] shlco = {16'h0000,b,cf} << shftamt;
wire [32:0] shlco = {16'h0000,b,cf} << shftamt;
wire [32:0] shrcuo = {cf,b,16'h0000} >> shftamt;
wire [32:0] shrcuo = {cf,b,16'h0000} >> shftamt;
 
 
wire [15:0] shlo8 = {8'h00,b[7:0]} << shftamt;
wire [15:0] shlo8 = {8'h00,b[7:0]} << shftamt;
wire [15:0] shruo8 = {b[7:0],8'h00} >> shftamt;
wire [15:0] shruo8 = {b[7:0],8'h00} >> shftamt;
wire [ 7:0] shro8 = ~(~b[7:0] >> shftamt);
wire [ 7:0] shro8 = ~(~b[7:0] >> shftamt);
wire [16:0] shlco8 = {8'h00,b,cf} << shftamt;
wire [16:0] shlco8 = {8'h00,b,cf} << shftamt;
wire [16:0] shrcuo8 = {cf,b[7:0],8'h00} >> shftamt;
wire [16:0] shrcuo8 = {cf,b[7:0],8'h00} >> shftamt;
 
 
wire div16_done;
wire div16_done;
wire div32_done;
wire div32_done;
wire [15:0] q16;
wire [15:0] q16;
wire [7:0] r16;
wire [7:0] r16;
wire [31:0] q32;
wire [31:0] q32;
wire [15:0] r32;
wire [15:0] r32;
wire [31:0] negdxax = -{dx,ax};
wire [31:0] negdxax = -{dx,ax};
 
 
divr2 #(16) udiv1
divr2 #(16) udiv1
(
(
        .rst(rst_i),
        .rst(rst_i),
        .clk(clk_i),
        .clk(clk_i),
        .ce(1'b1),
        .ce(1'b1),
        .ld(ld_div16),
        .ld(ld_div16),
        .su(TTT[0]),
        .su(TTT[0]),
        .ri(1'b0),
        .ri(1'b0),
        .a(ax),
        .a(ax),
        .b(b[7:0]),
        .b(b[7:0]),
        .i(8'h00),
        .i(8'h00),
        .q(q16),
        .q(q16),
        .r(r16),
        .r(r16),
        .divByZero(),
        .divByZero(),
        .done(div16_done)
        .done(div16_done)
);
);
 
 
 
 
divr2 #(32) udiv2
divr2 #(32) udiv2
(
(
        .rst(rst_i),
        .rst(rst_i),
        .clk(clk_i),
        .clk(clk_i),
        .ce(1'b1),
        .ce(1'b1),
        .ld(ld_div32),
        .ld(ld_div32),
        .su(TTT[0]),
        .su(TTT[0]),
        .ri(1'b0),
        .ri(1'b0),
        .a({dx,ax}),
        .a({dx,ax}),
        .b(b),
        .b(b),
        .i(16'h0000),
        .i(16'h0000),
        .q(q32),
        .q(q32),
        .r(r32),
        .r(r32),
        .divByZero(),
        .divByZero(),
        .done(div32_done)
        .done(div32_done)
);
);
 
 
 
 
always @(ir or ir2 or a or b or cf or af or al or ah or aldv10 or TTT)
always @*       //(ir or ir2 or a or b or cf or af or al or ah or aldv10 or TTT)
        begin
        begin
                casex(ir)
                casex(ir)
                `MOV_M2AL,`MOV_M2AX,`LDS,`LES:
                `MOV_M2AL,`MOV_M2AX,`LDS,`LES:
                        alu_o <= a;
                        alu_o <= a;
                `MOV_MR,`MOV_R2S,
                `MOV_MR,`MOV_R2S,
                `MOV_RR8,`MOV_RR16,
                `MOV_RR8,`MOV_RR16,
                `MOV_I8M,`MOV_I16M,
                `MOV_I8M,`MOV_I16M,
                `MOV_I2AL,`MOV_I2DL,`MOV_I2CL,`MOV_I2BL,`MOV_I2AH,`MOV_I2DH,`MOV_I2CH,`MOV_I2BH,
                `MOV_I2AL,`MOV_I2DL,`MOV_I2CL,`MOV_I2BL,`MOV_I2AH,`MOV_I2DH,`MOV_I2CH,`MOV_I2BH,
                `MOV_I2AX,`MOV_I2DX,`MOV_I2CX,`MOV_I2BX,`MOV_I2SP,`MOV_I2BP,`MOV_I2SI,`MOV_I2DI:
                `MOV_I2AX,`MOV_I2DX,`MOV_I2CX,`MOV_I2BX,`MOV_I2SP,`MOV_I2BP,`MOV_I2SI,`MOV_I2DI:
                        alu_o <= b;
                        alu_o <= b;
                `XCHG_MEM:
                `XCHG_MEM:
                        alu_o <= b;
                        alu_o <= b;
                `ADD,`ADD_ALI8,`ADD_AXI16: alu_o <= a + b;
                `ADD,`ADD_ALI8,`ADD_AXI16: alu_o <= a + b;
                `SUB,`SUB_ALI8,`SUB_AXI16: alu_o <= a - b;
                `SUB,`SUB_ALI8,`SUB_AXI16: alu_o <= a - b;
                `ADC,`ADC_ALI8,`ADC_AXI16: alu_o <= a + b + cf;
                `ADC,`ADC_ALI8,`ADC_AXI16: alu_o <= a + b + cf;
                `SBB,`SBB_ALI8,`SBB_AXI16: alu_o <= a - b - cf;
                `SBB,`SBB_ALI8,`SBB_AXI16: alu_o <= a - b - cf;
                `AND,`AND_ALI8,`AND_AXI16: alu_o <= a & b;
                `AND,`AND_ALI8,`AND_AXI16: alu_o <= a & b;
                `TEST,`TEST_ALI8,`TEST_AXI16: alu_o <= a & b;
                `TEST,`TEST_ALI8,`TEST_AXI16: alu_o <= a & b;
                `OR, `OR_ALI8, `OR_AXI16:  alu_o <= a | b;
                `OR, `OR_ALI8, `OR_AXI16:  alu_o <= a | b;
                `XOR,`XOR_ALI8,`XOR_AXI16: alu_o <= a ^ b;
                `XOR,`XOR_ALI8,`XOR_AXI16: alu_o <= a ^ b;
                `CMP,`CMP_ALI8,`CMP_AXI16: alu_o <= a - b;
                `CMP,`CMP_ALI8,`CMP_AXI16: alu_o <= a - b;
                `SCASB,`SCASW,`CMPSB,`CMPSW: alu_o <= a - b;
                `SCASB,`SCASW,`CMPSB,`CMPSW: alu_o <= a - b;
                `INC_REG: alu_o <= a + 16'd1;
                `INC_REG: alu_o <= a + 16'd1;
                `DEC_REG: alu_o <= a - 16'd1;
                `DEC_REG: alu_o <= a - 16'd1;
                `IMUL: alu_o <= w ? p : wp[15:0];
//              `IMUL: alu_o <= w ? p : wp[15:0];
                `ALU_I2R8:
                `ALU_I2R8:
                        case(TTT)
                        case(TTT)
                        3'd0:   alu_o <= a + b;                 // ADD
                        3'd0:   alu_o <= a + b;                 // ADD
                        3'd1:   alu_o <= a | b;                 // OR
                        3'd1:   alu_o <= a | b;                 // OR
                        3'd2:   alu_o <= a + b + cf;    // ADC
                        3'd2:   alu_o <= a + b + cf;    // ADC
                        3'd3:   alu_o <= a - b - cf;    // SBB
                        3'd3:   alu_o <= a - b - cf;    // SBB
                        3'd4:   alu_o <= a & b;                 // AND
                        3'd4:   alu_o <= a & b;                 // AND
                        3'd5:   alu_o <= a - b;                 // SUB
                        3'd5:   alu_o <= a - b;                 // SUB
                        3'd6:   alu_o <= a ^ b;                 // XOR
                        3'd6:   alu_o <= a ^ b;                 // XOR
                        default:        alu_o <= 16'h0000;
                        default:        alu_o <= 16'h0000;
                        endcase
                        endcase
                // ToDo: fix sign extension / extra immediate byte ?
                // ToDo: fix sign extension / extra immediate byte ?
                `ALU_I2R16:
                `ALU_I2R16:
                        case(TTT)
                        case(TTT)
                        3'd0:   alu_o <= a + b;                 // ADD
                        3'd0:   alu_o <= a + b;                 // ADD
                        3'd1:   alu_o <= a | b;                 // OR
                        3'd1:   alu_o <= a | b;                 // OR
                        3'd2:   alu_o <= a + b + cf;    // ADC
                        3'd2:   alu_o <= a + b + cf;    // ADC
                        3'd3:   alu_o <= a - b - cf;    // SBB
                        3'd3:   alu_o <= a - b - cf;    // SBB
                        3'd4:   alu_o <= a & b;                 // AND
                        3'd4:   alu_o <= a & b;                 // AND
                        3'd5:   alu_o <= a - b;                 // SUB
                        3'd5:   alu_o <= a - b;                 // SUB
                        3'd6:   alu_o <= a ^ b;                 // XOR
                        3'd6:   alu_o <= a ^ b;                 // XOR
                        default:        alu_o <= 16'h0000;
                        default:        alu_o <= 16'h0000;
                        endcase
                        endcase
                8'hF6,8'hF7:
                8'hF6,8'hF7:
 
                        begin
                        case(TTT)
                        case(TTT)
                        3'd0:   alu_o <= a & b;                 // TEST
                        3'd0:   alu_o <= a & b;                 // TEST
                        3'd2:   alu_o <= ~b;                    // NOT
                        3'd2:   alu_o <= ~b;                    // NOT
                        3'd3:   alu_o <= -b;                    // NEG
                        3'd3:   alu_o <= -b;                    // NEG
                        3'd4:   alu_o <= w ? p32[15:0] : p16;            // MUL
                        3'd4:   alu_o <= w ? p32[15:0] : p16;            // MUL
                        3'd5:   alu_o <= w ? wp[15:0] : p[15:0];  // IMUL
                        3'd5:   alu_o <= w ? wp[15:0] : p[15:0];  // IMUL
                        3'd6:   alu_o <= 16'h0000;              // DIV
                        3'd6:   alu_o <= 16'h0000;              // DIV
                        3'd7:   alu_o <= 16'h0000;              // IDIV
                        3'd7:   alu_o <= 16'h0000;              // IDIV
                        default:        alu_o <= 16'h0000;
                        default:        alu_o <= 16'h0000;
                        endcase
                        endcase
 
                        end
                `AAA:
                `AAA:
                        if (al[3:0]>4'h9 || af) begin
                        if (al[3:0]>4'h9 || af) begin
                                alu_o[3:0] <= al[3:0] + 4'd6;
                                alu_o[3:0] <= al[3:0] + 4'd6;
                                alu_o[7:4] <= 4'h0;
                                alu_o[7:4] <= 4'h0;
                                alu_o[15:8] <= ah + 8'd1;
                                alu_o[15:8] <= ah + 8'd1;
                        end
                        end
                        else
                        else
                                alu_o <= ax;
                                alu_o <= ax;
                `AAS:
                `AAS:
                        if (al[3:0]>4'h9 || af) begin
                        if (al[3:0]>4'h9 || af) begin
                                alu_o[3:0] <= al[3:0] - 4'd6;
                                alu_o[3:0] <= al[3:0] - 4'd6;
                                alu_o[7:4] <= 4'h0;
                                alu_o[7:4] <= 4'h0;
                                alu_o[15:8] <= ah - 8'd1;
                                alu_o[15:8] <= ah - 8'd1;
                        end
                        end
                        else
                        else
                                alu_o <= ax;
                                alu_o <= ax;
// ToDo: fix +1 carry
// ToDo: fix +1 carry
                `DAA:
                `DAA:
                        begin
                        begin
                                alu_o <= 16'h0000;
                                alu_o <= 16'h0000;
                                if (al[3:0]>4'h9 || af) begin
                                if (al[3:0]>4'h9 || af) begin
                                        alu_o[3:0] <= al[3:0] + 4'd6;
                                        alu_o[3:0] <= al[3:0] + 4'd6;
                                end
                                end
                                if (al[7:4]>4'h9 || cf) begin
                                if (al[7:4]>4'h9 || cf) begin
                                        alu_o[7:4] <= al[7:4] + 4'd6;
                                        alu_o[7:4] <= al[7:4] + 4'd6;
                                end
                                end
                        end
                        end
// ToDo: fix +1 carry
// ToDo: fix +1 carry
                `DAS:
                `DAS:
                        begin
                        begin
                                alu_o <= 16'h0000;
                                alu_o <= 16'h0000;
                                if (al[3:0]>4'h9 || af) begin
                                if (al[3:0]>4'h9 || af) begin
                                        alu_o[3:0] <= al[3:0] - 4'd6;
                                        alu_o[3:0] <= al[3:0] - 4'd6;
                                end
                                end
                                if (al[7:4]>4'h9 || cf) begin
                                if (al[7:4]>4'h9 || cf) begin
                                        alu_o[7:4] <= al[7:4] - 4'd6;
                                        alu_o[7:4] <= al[7:4] - 4'd6;
                                end
                                end
                        end
                        end
 
 
                `MORE1:
                `MORE1:
                        casex(ir2)
                        casex(ir2)
                        `AAM:
                        `AAM:
                                begin
                                begin
                                        alu_o[ 7:0] <= al - aldv10;
                                        alu_o[ 7:0] <= al - aldv10;
                                        alu_o[15:8] <= aldv10;
                                        alu_o[15:8] <= aldv10;
                                end
                                end
                        default:
                        default:
                                alu_o <= 16'h0000;
                                alu_o <= 16'h0000;
                        endcase
                        endcase
                `MORE2:
                `MORE2:
                        casex(ir2)
                        casex(ir2)
                        `AAD:
                        `AAD:
                                begin
                                begin
                                        alu_o[ 7:0] <= {ah,3'b0} + {ah,1'b0} + al;
                                        alu_o[ 7:0] <= {ah,3'b0} + {ah,1'b0} + al;
                                        alu_o[15:8] <= 8'h00;
                                        alu_o[15:8] <= 8'h00;
                                end
                                end
                        default:
                        default:
                                alu_o <= 16'h0000;
                                alu_o <= 16'h0000;
                        endcase
                        endcase
                default: alu_o <= 16'h0000;
                default: alu_o <= 16'h0000;
                endcase
                endcase
        end
        end
 
 
assign pres = ~^alu_o[7:0];
assign pres = ~^alu_o[7:0];
assign reszw = alu_o==16'h0000;
assign reszw = alu_o==16'h0000;
assign reszb = alu_o[7:0]==8'h00;
assign reszb = alu_o[7:0]==8'h00;
assign resnb = alu_o[7];
assign resnb = alu_o[7];
assign resnw = alu_o[15];
assign resnw = alu_o[15];
 
 
assign resz = w ? reszw : reszb;
assign resz = w ? reszw : reszb;
assign resn = w ? resnw : resnb;
assign resn = w ? resnw : resnb;
 
 
 
 

powered by: WebSVN 2.1.0

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