URL
https://opencores.org/ocsvn/theia_gpu/theia_gpu/trunk
Subversion Repositories theia_gpu
[/] [theia_gpu/] [branches/] [beta_1.2/] [rtl/] [EXE/] [Module_VectorALU.v] - Rev 113
Go to most recent revision | Compare with Previous | Blame | View Log
`timescale 1ns / 1ps `include "aDefinitions.v" /********************************************************************************** Theia, Ray Cast Programable graphic Processing Unit. Copyright (C) 2010 Diego Valverde (diego.valverde.g@gmail.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ***********************************************************************************/ //-------------------------------------------------------------- module VectorALU ( input wire Clock, input wire Reset, input wire[`INSTRUCTION_OP_LENGTH-1:0] iOperation, input wire[`WIDTH-1:0] iChannel_Ax, input wire[`WIDTH-1:0] iChannel_Bx, input wire[`WIDTH-1:0] iChannel_Ay, input wire[`WIDTH-1:0] iChannel_By, input wire[`WIDTH-1:0] iChannel_Az, input wire[`WIDTH-1:0] iChannel_Bz, output wire [`WIDTH-1:0] oResultA, output wire [`WIDTH-1:0] oResultB, output wire [`WIDTH-1:0] oResultC, input wire iInputReady, output reg oBranchTaken, output reg oBranchNotTaken, output reg OutputReady ); wire wMultiplcationUnscaled; assign wMultiplcationUnscaled = (iOperation == `IMUL) ? 1'b1 : 1'b0; //-------------------------------------------------------------- reg [7:0] InputReadyA,InputReadyB,InputReadyC; //------------------------------------------------------ /* This is the block that takes care of all tha arithmetic comparisons. Supported operations are <,>,<=,>=,==,!= */ //------------------------------------------------------ reg [`WIDTH-1:0] wMultiplicationA_Ax; reg [`WIDTH-1:0] wMultiplicationA_Bx; wire [`LONG_WIDTH-1:0] wMultiplicationA_Result; wire wMultiplicationA_InputReady; wire wMultiplicationA_OutputReady; wire wMultiplicationOutputReady, wMultiplicationOutputReadyA, wMultiplicationOutputReadyB,wMultiplicationOutputReadyC,wMultiplicationOutputReadyD; wire wAddSubAOutputReady,wAddSubBOutputReady,wAddSubCOutputReady; //-------------------------------------------------------------------- reg [`WIDTH-1:0] ResultA,ResultB,ResultC; //Output Flip Flops, //This flip flop will control the outputs so that the //values of the outputs change ONLY when when there is //a positive edge of OutputReady FFD32_POSEDGE ResultAFFD ( .Clock( OutputReady ), .D( ResultA ), .Q( oResultA ) ); FFD32_POSEDGE ResultBFFD ( .Clock( OutputReady ), .D( ResultB ), .Q( oResultB ) ); FFD32_POSEDGE ResultCFFD ( .Clock( OutputReady ), .D( ResultC ), .Q( oResultC ) ); //-------------------------------------------------------------------- wire [`WIDTH-1:0] wSwizzleOutputX,wSwizzleOutputY,wSwizzleOutputZ; Swizzle3D Swizzle1 ( .Source0_X( iChannel_Bx ), .Source0_Y( iChannel_By ), .Source0_Z( iChannel_Bz ), .iOperation( iChannel_Ax ), .SwizzleX( wSwizzleOutputX ), .SwizzleY( wSwizzleOutputY ), .SwizzleZ( wSwizzleOutputZ ) ); //--------------------------------------------------------------------- wire [`LONG_WIDTH-1:0] wModulus2N_ResultA,wModulus2N_ResultB,wModulus2N_ResultC; //wire wModulusOutputReadyA,wModulusOutputReadyB,wModulusOutputReadyC; /* Modulus2N MODA ( .Clock( Clock ), .Reset( Reset ), .oQuotient( wModulus2N_ResultA ), .iInputReady( iInputReady ), .oOutputReady( wModulusOutputReadyA ) ); Modulus2N MODB ( .Clock( Clock ), .Reset( Reset ), .oQuotient( wModulus2N_ResultB ), .iInputReady( iInputReady ), .oOutputReady( wModulusOutputReadyB ) ); Modulus2N MODC ( .Clock( Clock ), .Reset( Reset ), .oQuotient( wModulus2N_ResultC ), .iInputReady( iInputReady ), .oOutputReady( wModulusOutputReadyC ) ); */ //---------------------------------------------------------------------( /* This MUX will select the apropiated X,Y or Z depending on wheter it is XYZ iOperation. This gets defined by the bits 3 and 4 of iOperation, and only applies for oBranchTaken and Store operations. */ wire wArithmeticComparison_Result; wire ArithmeticComparison_InputReady; wire ArithmeticComparison_OutputReady; reg[`WIDTH-1:0] ArithmeticComparison_A,ArithmeticComparison_B; always @ ( * ) begin case ( {iOperation[4],iOperation[3]} ) 2'b01: ArithmeticComparison_A = iChannel_Ax; 2'b10: ArithmeticComparison_A = iChannel_Ay; 2'b11: ArithmeticComparison_A = iChannel_Az; default: ArithmeticComparison_A = 0; //Should never happen endcase end //--------------------------------------------------------------------- always @ ( * ) begin case ( {iOperation[4],iOperation[3]} ) 2'b01: ArithmeticComparison_B = iChannel_Bx; 2'b10: ArithmeticComparison_B = iChannel_By; 2'b11: ArithmeticComparison_B = iChannel_Bz; default: ArithmeticComparison_B = 0; //Should never happen endcase end //--------------------------------------------------------------------- /* The onbly instance of Aritmetic comparison in the ALU, ArithmeticComparison operations matches the 3 LSB of Global ALU iOperation for oBranchTaken Instruction family */ assign ArithmeticComparison_InputReady = iInputReady; wire wArithmeticComparisonResult; ArithmeticComparison ArithmeticComparison_1 ( .Clock( Clock ), .X( ArithmeticComparison_A ), .Y( ArithmeticComparison_B ), .iOperation( iOperation[2:0] ), .iInputReady( ArithmeticComparison_InputReady ), .OutputReady( ArithmeticComparison_OutputReady ), .Result( wArithmeticComparisonResult ) ); assign wArithmeticComparison_Result = wArithmeticComparisonResult && OutputReady; //-------------------------------------------------------------------- RADIX_R_MUL_32_FULL_PARALLEL MultiplicationChannel_A ( .Clock( Clock ), .Reset( Reset ), .A( wMultiplicationA_Ax ), .B( wMultiplicationA_Bx ), .R( wMultiplicationA_Result ), .iUnscaled( wMultiplcationUnscaled ), .iInputReady( wMultiplicationA_InputReady ), .OutputReady( wMultiplicationA_OutputReady ) ); //-------------------------------------------------------------------- always @ ( * ) begin case (iOperation) `CROSS: wMultiplicationA_Ax = iChannel_Ay; // Ay * Bz `MAG: wMultiplicationA_Ax = iChannel_Ax; `MULP: wMultiplicationA_Ax = iChannel_Ax; //Az = Ax * Ay default: wMultiplicationA_Ax = iChannel_Ax; // Ax * Bx endcase end //-------------------------------------------------------------------- //assign wMultiplicationA_Ax = iChannel_Ax; assign wMultiplicationA_InputReady = (iOperation == `CROSS || iOperation == `DOT || iOperation == `MUL || iOperation == `IMUL || iOperation == `MAG || iOperation == `MULP ) ? iInputReady : 0; //-------------------------------------------------------------------- always @ ( * ) begin case (iOperation) `MUL,`IMUL: wMultiplicationA_Bx = iChannel_Bx; //Ax*Bx `MAG: wMultiplicationA_Bx = iChannel_Ax; //Ax^2 `DOT: wMultiplicationA_Bx = iChannel_Bx; //Ax*Bx `CROSS: wMultiplicationA_Bx = iChannel_Bz; // Ay * Bz `MULP: wMultiplicationA_Bx = iChannel_Ay; //Az = Ax * Ay default: wMultiplicationA_Bx = 32'b0; endcase end //-------------------------------------------------------------------- //------------------------------------------------------ reg [`WIDTH-1:0] wMultiplicationB_Ay; reg [`WIDTH-1:0] wMultiplicationB_By; wire [`LONG_WIDTH-1:0] wMultiplicationB_Result; wire wMultiplicationB_InputReady; wire wMultiplicationB_OutputReady; RADIX_R_MUL_32_FULL_PARALLEL MultiplicationChannel_B ( .Clock( Clock ), .Reset( Reset ), .A( wMultiplicationB_Ay ), .B( wMultiplicationB_By ), .R( wMultiplicationB_Result ), .iUnscaled( wMultiplcationUnscaled ), .iInputReady( wMultiplicationB_InputReady ), .OutputReady( wMultiplicationB_OutputReady ) ); //---------------------------------------------------- always @ ( * ) begin case (iOperation) `CROSS: wMultiplicationB_Ay = iChannel_Az; // Az * By `MAG: wMultiplicationB_Ay = iChannel_Ay; default: wMultiplicationB_Ay = iChannel_Ay; // Ay * By endcase end //---------------------------------------------------- assign wMultiplicationB_InputReady = (iOperation == `CROSS || iOperation == `DOT || iOperation == `MUL || iOperation == `IMUL || iOperation == `MAG ) ? iInputReady : 0; //---------------------------------------------------- always @ ( * ) begin case (iOperation) `MUL,`IMUL: wMultiplicationB_By = iChannel_By; //Ay*By `MAG: wMultiplicationB_By = iChannel_Ay; //Ay^2 `DOT: wMultiplicationB_By = iChannel_By; //Ay*By `CROSS: wMultiplicationB_By = iChannel_By; // Az * By default: wMultiplicationB_By = 32'b0; endcase end //---------------------------------------------------- //------------------------------------------------------ reg [`WIDTH-1:0] wMultiplicationC_Az; reg [`WIDTH-1:0] wMultiplicationC_Bz; wire [`LONG_WIDTH-1:0] wMultiplicationC_Result; wire wMultiplicationC_InputReady; wire wMultiplicationC_OutputReady; RADIX_R_MUL_32_FULL_PARALLEL MultiplicationChannel_C ( .Clock( Clock ), .Reset( Reset ), .A( wMultiplicationC_Az ), .B( wMultiplicationC_Bz ), .R( wMultiplicationC_Result ), .iUnscaled( wMultiplcationUnscaled ), .iInputReady( wMultiplicationC_InputReady ), .OutputReady( wMultiplicationC_OutputReady ) ); //---------------------------------------------------- always @ ( * ) begin case (iOperation) `CROSS: wMultiplicationC_Az = iChannel_Az; //Az*Bx `MAG: wMultiplicationC_Az = iChannel_Az; default: wMultiplicationC_Az = iChannel_Az; //Az*Bz endcase end //---------------------------------------------------- assign wMultiplicationC_InputReady = ( iOperation == `CROSS || iOperation == `DOT || iOperation == `MUL || iOperation == `IMUL || iOperation == `MAG ) ? iInputReady : 0; //---------------------------------------------------- always @ ( * ) begin case (iOperation) `MUL,`IMUL: wMultiplicationC_Bz = iChannel_Bz; //Az*Bz `MAG: wMultiplicationC_Bz = iChannel_Az; //Ay^2 `DOT: wMultiplicationC_Bz = iChannel_Bz; //Az*Bz `CROSS: wMultiplicationC_Bz = iChannel_Bx; //Az*Bx default: wMultiplicationC_Bz = 32'b0; endcase end //---------------------------------------------------- reg [`WIDTH-1:0] wMultiplicationD_Aw; reg [`WIDTH-1:0] wMultiplicationD_Bw; wire [`LONG_WIDTH-1:0] wMultiplicationD_Result; wire wMultiplicationD_InputReady; wire wMultiplicationD_OutputReady; RADIX_R_MUL_32_FULL_PARALLEL MultiplicationChannel_D ( .Clock( Clock ), .Reset( Reset ), .A( wMultiplicationD_Aw ), .B( wMultiplicationD_Bw ), .R( wMultiplicationD_Result ), .iUnscaled( wMultiplcationUnscaled ), .iInputReady( wMultiplicationD_InputReady ), .OutputReady( wMultiplicationD_OutputReady ) ); assign wMultiplicationD_InputReady = (iOperation == `CROSS ) ? iInputReady : 0; //---------------------------------------------------- always @ ( * ) begin case (iOperation) `CROSS: wMultiplicationD_Aw = iChannel_Ax; //Ax*Bz default: wMultiplicationD_Aw = 32'b0; endcase end //---------------------------------------------------- always @ ( * ) begin case (iOperation) `CROSS: wMultiplicationD_Bw = iChannel_Bz; //Ax*Bz default: wMultiplicationD_Bw = 32'b0; endcase end //---------------------------------------------------- reg [`WIDTH-1:0] wMultiplicationE_Ak; reg [`WIDTH-1:0] wMultiplicationE_Bk; wire [`LONG_WIDTH-1:0] wMultiplicationE_Result; wire wMultiplicationE_InputReady; wire wMultiplicationE_OutputReady; RADIX_R_MUL_32_FULL_PARALLEL MultiplicationChannel_E ( .Clock( Clock ), .Reset( Reset ), .A( wMultiplicationE_Ak ), .B( wMultiplicationE_Bk ), .R( wMultiplicationE_Result ), .iUnscaled( wMultiplcationUnscaled ), .iInputReady( wMultiplicationE_InputReady ), .OutputReady( wMultiplicationE_OutputReady ) ); assign wMultiplicationE_InputReady = (iOperation == `CROSS ) ? iInputReady : 0; //---------------------------------------------------- always @ ( * ) begin case (iOperation) `CROSS: wMultiplicationE_Ak = iChannel_Ax; //Ax*By default: wMultiplicationE_Ak = 32'b0; endcase end //---------------------------------------------------- always @ ( * ) begin case (iOperation) `CROSS: wMultiplicationE_Bk = iChannel_By; //Ax*By default: wMultiplicationE_Bk = 32'b0; endcase end //---------------------------------------------------- reg [`WIDTH-1:0] wMultiplicationF_Al; reg [`WIDTH-1:0] wMultiplicationF_Bl; wire [`LONG_WIDTH-1:0] wMultiplicationF_Result; wire wMultiplicationF_InputReady; wire wMultiplicationF_OutputReady; RADIX_R_MUL_32_FULL_PARALLEL MultiplicationChannel_F ( .Clock( Clock ), .Reset( Reset ), .A( wMultiplicationF_Al ), .B( wMultiplicationF_Bl ), .R( wMultiplicationF_Result ), .iUnscaled( wMultiplcationUnscaled ), .iInputReady( wMultiplicationF_InputReady ), .OutputReady( wMultiplicationF_OutputReady ) ); assign wMultiplicationF_InputReady = (iOperation == `CROSS ) ? iInputReady : 0; //---------------------------------------------------- always @ ( * ) begin case (iOperation) `CROSS: wMultiplicationF_Al = iChannel_Ay; //Ay*Bx default: wMultiplicationF_Al = 32'b0; endcase end //---------------------------------------------------- always @ ( * ) begin case (iOperation) `CROSS: wMultiplicationF_Bl = iChannel_Bx; //Ay*Bx default: wMultiplicationF_Bl = 32'b0; endcase end //------------------------------------------------------ wire [`WIDTH-1:0] wDivisionA_Result; wire wDivisionA_OutputReady; wire wDivisionA_InputReady; assign wDivisionA_InputReady = ( iOperation == `DIV) ? iInputReady : 0; SignedIntegerDivision DivisionChannel_A ( .Clock( Clock ), .Reset( Reset ), .iDividend( iChannel_Ax ), .iDivisor( iChannel_Bx ), .xQuotient( wDivisionA_Result ), .iInputReady( wDivisionA_InputReady ), .OutputReady( wDivisionA_OutputReady ) ); //------------------------------------------------------ wire [`WIDTH-1:0] wDivisionB_Result; wire wDivisionB_OutputReady; wire wDivisionB_InputReady; assign wDivisionB_InputReady = ( iOperation == `DIV) ? iInputReady : 0; SignedIntegerDivision DivisionChannel_B ( .Clock( Clock ), .Reset( Reset ), .iDividend( iChannel_Ay ), .iDivisor( iChannel_By ), .xQuotient( wDivisionB_Result ), .iInputReady( wDivisionB_InputReady ), .OutputReady( wDivisionB_OutputReady ) ); //------------------------------------------------------ wire [`WIDTH-1:0] wDivisionC_Result; wire wDivisionC_OutputReady; wire wDivisionC_InputReady; assign wDivisionC_InputReady = ( iOperation == `DIV) ? iInputReady : 0; SignedIntegerDivision DivisionChannel_C ( .Clock( Clock ), .Reset( Reset ), .iDividend( iChannel_Az ), .iDivisor( iChannel_Bz ), .xQuotient( wDivisionC_Result ), .iInputReady( wDivisionC_InputReady ), .OutputReady( wDivisionC_OutputReady ) ); //-------------------------------------------------------------- /* First addtion block instance goes here. Note that all inputs/outputs to the block are wires. It has two MUXES one for each entry. */ reg [`LONG_WIDTH-1:0] wAddSubA_Ax,wAddSubA_Bx; wire [`LONG_WIDTH-1:0] wAddSubA_Result; wire wAddSubA_Operation; //Either addition or substraction reg wAddSubA_InputReady; wire wAddSubA_OutputReady; assign wAddSubA_Operation = ( iOperation == `SUB || iOperation == `CROSS || iOperation == `DEC || iOperation == `MOD ) ? 1 : 0; FixedAddSub AddSubChannel_A ( .Clock( Clock ), .Reset( Reset ), .A( wAddSubA_Ax ), .B( wAddSubA_Bx ), .R( wAddSubA_Result ), .iOperation( wAddSubA_Operation ), .iInputReady( wAddSubA_InputReady ), .OutputReady( wAddSubA_OutputReady ) ); //Diego //---------------------------- //InpuReady Mux A always @ ( * ) begin case (iOperation) `ADD: wAddSubA_InputReady = iInputReady; `SUB: wAddSubA_InputReady = iInputReady; `INC,`INCX,`INCY,`INCZ: wAddSubA_InputReady = iInputReady; `DEC: wAddSubA_InputReady = iInputReady; `MOD: wAddSubA_InputReady = iInputReady; `MAG: wAddSubA_InputReady = wMultiplicationOutputReadyA && wMultiplicationOutputReadyB; //wMultiplicationA_OutputReady //&& wMultiplicationB_OutputReady; `DOT: wAddSubA_InputReady = wMultiplicationOutputReadyA && wMultiplicationOutputReadyB; //wMultiplicationA_OutputReady //&& wMultiplicationB_OutputReady; `CROSS: wAddSubA_InputReady = wMultiplicationOutputReadyA && wMultiplicationOutputReadyB; // wMultiplicationA_OutputReady //&& wMultiplicationB_OutputReady; default: wAddSubA_InputReady = 1'b0; endcase end //---------------------------- //wAddSubA_Bx 2:1 input Mux always @ ( * ) begin case (iOperation) `ADD: wAddSubA_Ax = ( iChannel_Ax[31] == 1'b1) ? {32'hFFFFFFFF, iChannel_Ax } : { 32'b0, iChannel_Ax }; `SUB: wAddSubA_Ax = ( iChannel_Ax[31] == 1'b1) ? {32'hFFFFFFFF, iChannel_Ax } : { 32'b0, iChannel_Ax }; `INC,`INCX,`INCY,`INCZ: wAddSubA_Ax = ( iChannel_Ax[31] == 1'b1) ? {32'hFFFFFFFF, iChannel_Ax } : { 32'b0, iChannel_Ax }; `DEC: wAddSubA_Ax = ( iChannel_Ax[31] == 1'b1) ? {32'hFFFFFFFF, iChannel_Ax } : { 32'b0, iChannel_Ax }; `MOD: wAddSubA_Ax = ( iChannel_Bx[31] == 1'b1) ? {32'hFFFFFFFF, iChannel_Bx } : { 32'b0, iChannel_Bx }; `MAG: wAddSubA_Ax = wMultiplicationA_Result; `DOT: wAddSubA_Ax = wMultiplicationA_Result; `CROSS: wAddSubA_Ax = wMultiplicationA_Result; default: wAddSubA_Ax = 64'b0; endcase end //---------------------------- //wAddSubA_Bx 2:1 input Mux always @ ( * ) begin case (iOperation) `ADD: wAddSubA_Bx = ( iChannel_Bx[31] == 1'b1) ? {32'hFFFFFFFF, iChannel_Bx } : { 32'b0, iChannel_Bx }; `SUB: wAddSubA_Bx = ( iChannel_Bx[31] == 1'b1) ? {32'hFFFFFFFF, iChannel_Bx } : { 32'b0, iChannel_Bx }; `INC,`INCX: wAddSubA_Bx = (`LONG_WIDTH'd1 << `SCALE); `INCY,`INCZ: wAddSubA_Bx = `LONG_WIDTH'd0; `DEC: wAddSubA_Bx = (`LONG_WIDTH'd1 << `SCALE); `MOD: wAddSubA_Bx = (`LONG_WIDTH'd1 << `SCALE); `MAG: wAddSubA_Bx = wMultiplicationB_Result; `DOT: wAddSubA_Bx = wMultiplicationB_Result; `CROSS: wAddSubA_Bx = wMultiplicationB_Result; default: wAddSubA_Bx = 64'b0; endcase end //-------------------------------------------------------------- /* Second addtion block instance goes here. Note that all inputs/outputs to the block are wires. It has two MUXES one for each entry. */ wire [`LONG_WIDTH-1:0] wAddSubB_Result; wire wAddSubB_Operation; //Either addition or substraction reg wAddSubB_InputReady; wire wAddSubB_OutputReady; reg [`LONG_WIDTH-1:0] wAddSubB_Ay,wAddSubB_By; assign wAddSubB_Operation = ( iOperation == `SUB || iOperation == `CROSS || iOperation == `DEC || iOperation == `MOD ) ? 1 : 0; FixedAddSub AddSubChannel_B ( .Clock( Clock ), .Reset( Reset ), .A( wAddSubB_Ay ), .B( wAddSubB_By ), .R( wAddSubB_Result ), .iOperation( wAddSubB_Operation ), .iInputReady( wAddSubB_InputReady ), .OutputReady( wAddSubB_OutputReady ) ); //---------------------------- wire wMultiplicationOutputReadyC_Dealy1; FFD_POSEDGE_ASYNC_RESET # (1) FFwMultiplicationOutputReadyC_Dealy1 ( .Clock( Clock ), .Clear( Reset ), .D( wMultiplicationOutputReadyC ), .Q( wMultiplicationOutputReadyC_Dealy1 ) ); //InpuReady Mux B always @ ( * ) begin case (iOperation) `ADD: wAddSubB_InputReady = iInputReady; `SUB: wAddSubB_InputReady = iInputReady; `INC,`INCX,`INCY,`INCZ: wAddSubB_InputReady = iInputReady; `DEC: wAddSubB_InputReady = iInputReady; `MOD: wAddSubB_InputReady = iInputReady; `MAG: wAddSubB_InputReady = wAddSubAOutputReady && wMultiplicationOutputReadyC_Dealy1; //&& wMultiplicationC_OutputReady; `DOT: wAddSubB_InputReady = wAddSubAOutputReady && wMultiplicationOutputReadyC_Dealy1; //&& wMultiplicationC_OutputReady; `CROSS: wAddSubB_InputReady = wMultiplicationOutputReadyC && wMultiplicationOutputReadyD; // wMultiplicationC_OutputReady //&& wMultiplicationD_OutputReady; default: wAddSubB_InputReady = 1'b0; endcase end //---------------------------- // wAddSubB_Ay 2:1 input Mux // If the iOperation is ADD or SUB, it will simply take the inputs from // ALU Channels. If it is a VECTOR_MAGNITUDE, it take the input from the // previus ADDER_A, same for dot product. always @ ( * ) begin case (iOperation) `ADD: wAddSubB_Ay = (iChannel_Ay[31] == 1'b1) ? {32'hFFFFFFFF, iChannel_Ay} : {32'b0,iChannel_Ay}; //Ay `SUB: wAddSubB_Ay = (iChannel_Ay[31] == 1'b1) ? {32'hFFFFFFFF, iChannel_Ay} : {32'b0,iChannel_Ay}; //Ay `INC,`INCX,`INCY,`INCZ: wAddSubB_Ay = (iChannel_Ay[31] == 1'b1) ? {32'hFFFFFFFF, iChannel_Ay} : {32'b0,iChannel_Ay}; //Ay `DEC: wAddSubB_Ay = (iChannel_Ay[31] == 1'b1) ? {32'hFFFFFFFF, iChannel_Ay} : {32'b0,iChannel_Ay}; //Ay `MOD: wAddSubB_Ay = (iChannel_By[31] == 1'b1) ? {32'hFFFFFFFF, iChannel_By} : {32'b0,iChannel_By}; //Ay `MAG: wAddSubB_Ay = wAddSubA_Result; //A^2+B^2 `DOT: wAddSubB_Ay = wAddSubA_Result; //Ax*Bx + Ay*By `CROSS: wAddSubB_Ay = wMultiplicationC_Result; default: wAddSubB_Ay = 64'b0; endcase end //---------------------------- //wAddSubB_By 2:1 input Mux always @ ( * ) begin case (iOperation) `ADD: wAddSubB_By = (iChannel_By[31] == 1'b1) ? {32'hFFFFFFFF,iChannel_By } : {32'b0,iChannel_By}; //By `SUB: wAddSubB_By = (iChannel_By[31] == 1'b1) ? {32'hFFFFFFFF,iChannel_By } : {32'b0,iChannel_By}; //{32'b0,iChannel_By}; //By `INC,`INCY: wAddSubB_By = (`LONG_WIDTH'd1 << `SCALE); `INCX,`INCZ: wAddSubB_By = `LONG_WIDTH'd0; `DEC: wAddSubB_By = (`LONG_WIDTH'd1 << `SCALE); `MOD: wAddSubB_By = (`LONG_WIDTH'd1 << `SCALE); `MAG: wAddSubB_By = wMultiplicationC_Result; //C^2 `DOT: wAddSubB_By = wMultiplicationC_Result; //Az * Bz `CROSS: wAddSubB_By = wMultiplicationD_Result; default: wAddSubB_By = 32'b0; endcase end //-------------------------------------------------------------- wire [`LONG_WIDTH-1:0] wAddSubC_Result; reg [`LONG_WIDTH-1:0] wAddSubC_Az,wAddSubC_Bz; wire wAddSubC_Operation; //Either addition or substraction reg wAddSubC_InputReady; wire wAddSubC_OutputReady; reg [`LONG_WIDTH-1:0] AddSubC_Az,AddSubB_Bz; //----------------------------------------- always @ ( * ) begin case (iOperation) `CROSS: wAddSubC_Az = wMultiplicationE_Result; `MOD: wAddSubC_Az = (iChannel_Bz[31] == 1'b1) ? {32'hFFFFFFFF,iChannel_Bz} : {32'b0,iChannel_Bz}; default: wAddSubC_Az = (iChannel_Az[31] == 1'b1) ? {32'hFFFFFFFF,iChannel_Az} : {32'b0,iChannel_Az}; endcase end //----------------------------------------- always @ ( * ) begin case (iOperation) `CROSS: wAddSubC_Bz = wMultiplicationF_Result; `INC,`INCZ: wAddSubC_Bz = (`LONG_WIDTH'd1 << `SCALE); `INCX,`INCY: wAddSubC_Bz = `LONG_WIDTH'd0; `DEC: wAddSubC_Bz = (`LONG_WIDTH'd1 << `SCALE); `MOD: wAddSubC_Bz = (`LONG_WIDTH'd1 << `SCALE); default: wAddSubC_Bz = (iChannel_Bz[31] == 1'b1) ? {32'hFFFFFFFF,iChannel_Bz} : {32'b0,iChannel_Bz}; endcase end //----------------------------------------- assign wAddSubC_Operation = ( iOperation == `SUB || iOperation == `CROSS || iOperation == `DEC || iOperation == `MOD ) ? 1 : 0; FixedAddSub AddSubChannel_C ( .Clock( Clock ), .Reset( Reset ), .A( wAddSubC_Az ), .B( wAddSubC_Bz ), .R( wAddSubC_Result ), .iOperation( wAddSubC_Operation ), .iInputReady( wAddSubC_InputReady ), .OutputReady( wAddSubC_OutputReady ) ); always @ ( * ) begin case (iOperation) `CROSS: wAddSubC_InputReady = wMultiplicationE_OutputReady && wMultiplicationF_OutputReady; default: wAddSubC_InputReady = iInputReady; endcase end //------------------------------------------------------ wire [`WIDTH-1:0] wSquareRoot_Result; wire wSquareRoot_OutputReady; FixedPointSquareRoot SQROOT1 ( .Clock( Clock ), .Reset( Reset ), .Operand( wAddSubB_Result ), .iInputReady( wAddSubBOutputReady && iOperation == `MAG), .OutputReady( wSquareRoot_OutputReady ), .Result( wSquareRoot_Result ) ); //------------------------------------------------------ assign wModulus2N_ResultA = (iChannel_Ax & wAddSubA_Result ); assign wModulus2N_ResultB = (iChannel_Ay & wAddSubB_Result ); assign wModulus2N_ResultC = (iChannel_Az & wAddSubC_Result ); //&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&// //****Mux for ResultA*** // Notice that the Dot Product or the Magnitud Result will // output in ResultA. always @ ( * ) begin case ( iOperation ) `RETURN: ResultA = iChannel_Ax; `ADD: ResultA = (wAddSubA_Result[63] == 1'b1) ? { 1'b1,wAddSubA_Result[30:0]} : {1'b0,wAddSubA_Result[30:0]};// & 32'h7FFFFFFF; `SUB: ResultA = (wAddSubA_Result[63] == 1'b1) ? { 1'b1,wAddSubA_Result[30:0]} : {1'b0,wAddSubA_Result[30:0]};//wAddSubA_Result[31:0]; `CROSS: ResultA = (wAddSubA_Result[63] == 1'b1) ? { 1'b1,wAddSubA_Result[30:0]} : {1'b0,wAddSubA_Result[30:0]};//wAddSubA_Result[31:0]; `DIV: ResultA = wDivisionA_Result; `MUL: ResultA = wMultiplicationA_Result[31:0]; `IMUL: ResultA = wMultiplicationA_Result[31:0]; `DOT: ResultA = (wAddSubB_Result[63] == 1'b1) ? { 1'b1,wAddSubB_Result[30:0]} : {1'b0,wAddSubB_Result[30:0]};//wAddSubB_Result[31:0]; `MAG: ResultA = wSquareRoot_Result; `ZERO: ResultA = 32'b0; `COPY: ResultA = iChannel_Ax; `SWIZZLE3D: ResultA = wSwizzleOutputX; //Set Operations `UNSCALE: ResultA = iChannel_Ax >> `SCALE; `SETX: ResultA = iChannel_Ax; `SETY: ResultA = iChannel_Bx; `SETZ: ResultA = iChannel_Bx; `INC,`INCX,`INCY,`INCZ: ResultA = (wAddSubA_Result[63] == 1'b1) ? { 1'b1,wAddSubA_Result[30:0]} : {1'b0,wAddSubA_Result[30:0]}; `DEC: ResultA = (wAddSubA_Result[63] == 1'b1) ? { 1'b1,wAddSubA_Result[30:0]} : {1'b0,wAddSubA_Result[30:0]}; `MOD: ResultA = wModulus2N_ResultA; `FRAC: ResultA = iChannel_Ax & (`WIDTH'hFFFFFFFF >> (`WIDTH - `SCALE)); `MULP: ResultA = iChannel_Ax; `NEG: ResultA = ~iChannel_Ax + 1'b1; `XCHANGEX: ResultA = iChannel_Bx; default: begin `ifdef DEBUG // $display("%dns ALU: Error Unknown Operation: %d",$time,iOperation); // $stop(); `endif ResultA = 32'b0; end endcase end //------------------------------------------------------ //****Mux for RB*** always @ ( * ) begin case ( iOperation ) `RETURN: ResultB = iChannel_Ax; `ADD: ResultB = (wAddSubB_Result[63] == 1'b1) ? {1'b1,wAddSubB_Result[30:0]} : {1'b0,wAddSubB_Result[30:0]}; // & 32'h7FFFFFFF; `SUB: ResultB = (wAddSubB_Result[63] == 1'b1) ? {1'b1,wAddSubB_Result[30:0]} : {1'b0,wAddSubB_Result[30:0]}; //wAddSubB_Result[31:0]; `CROSS: ResultB = (wAddSubB_Result[63] == 1'b1) ? {1'b1,wAddSubB_Result[30:0]} : {1'b0,wAddSubB_Result[30:0]};//wAddSubB_Result[31:0]; `DIV: ResultB = wDivisionB_Result; `MUL: ResultB = wMultiplicationB_Result[31:0]; `IMUL: ResultB = wMultiplicationB_Result[31:0]; `DOT: ResultB = (wAddSubB_Result[63] == 1'b1) ? {1'b1,wAddSubB_Result[30:0]} : {1'b0,wAddSubB_Result[30:0]};//wAddSubB_Result[31:0]; `MAG: ResultB = wSquareRoot_Result; `ZERO: ResultB = 32'b0; `COPY: ResultB = iChannel_Ay; //Set Operations `UNSCALE: ResultB = iChannel_Ay >> `SCALE; `SETX: ResultB = iChannel_By; // {Source1[95:64],Source0[63:32],Source0[31:0]}; `SETY: ResultB = iChannel_Ax; // {Source0[95:64],Source1[95:64],Source0[31:0]}; `SETZ: ResultB = iChannel_By; // {Source0[95:64],Source0[63:32],Source1[95:64]}; `SWIZZLE3D: ResultB = wSwizzleOutputY; `INC,`INCX,`INCY,`INCZ: ResultB = (wAddSubB_Result[63] == 1'b1) ? {1'b1,wAddSubB_Result[30:0]} : {1'b0,wAddSubB_Result[30:0]}; // & 32'h7FFFFFFF; `DEC: ResultB = (wAddSubB_Result[63] == 1'b1) ? {1'b1,wAddSubB_Result[30:0]} : {1'b0,wAddSubB_Result[30:0]}; // & 32'h7FFFFFFF; `MOD: ResultB = wModulus2N_ResultB; `FRAC: ResultB = iChannel_Ay & (`WIDTH'hFFFFFFFF >> (`WIDTH - `SCALE)); `MULP: ResultB = iChannel_Ay; `NEG: ResultB = ~iChannel_Ay + 1'b1; `XCHANGEX: ResultB = iChannel_Ay; default: begin `ifdef DEBUG //$display("%dns ALU: Error Unknown Operation: %d",$time,iOperation); //$stop(); `endif ResultB = 32'b0; end endcase end //------------------------------------------------------ //****Mux for RC*** always @ ( * ) begin case ( iOperation ) `RETURN: ResultC = iChannel_Ax; `ADD: ResultC = (wAddSubC_Result[63] == 1'b1) ? {1'b1,wAddSubC_Result[30:0]} : {1'b0,wAddSubC_Result[30:0]}; //wAddSubC_Result[31:0];// & 32'h7FFFFFFF; `SUB: ResultC = (wAddSubC_Result[63] == 1'b1) ? {1'b1,wAddSubC_Result[30:0]} : {1'b0,wAddSubC_Result[30:0]}; //wAddSubC_Result[31:0]; `CROSS: ResultC = (wAddSubC_Result[63] == 1'b1) ? {1'b1,wAddSubC_Result[30:0]} : {1'b0,wAddSubC_Result[30:0]};//wAddSubC_Result[31:0]; `DIV: ResultC = wDivisionC_Result; `MUL: ResultC = wMultiplicationC_Result[31:0]; `IMUL: ResultC = wMultiplicationC_Result[31:0]; `DOT: ResultC = (wAddSubB_Result[63] == 1'b1) ? {1'b1,wAddSubB_Result[30:0]} : {1'b0,wAddSubB_Result[30:0]};//wAddSubB_Result[31:0]; `MAG: ResultC = wSquareRoot_Result; `ZERO: ResultC = 32'b0; `COPY: ResultC = iChannel_Az; `SWIZZLE3D: ResultC = wSwizzleOutputZ; //Set Operations `UNSCALE: ResultC = iChannel_Az >> `SCALE; `SETX: ResultC = iChannel_Bz; // {Source1[95:64],Source0[63:32],Source0[31:0]}; `SETY: ResultC = iChannel_Bz; // {Source0[95:64],Source1[95:64],Source0[31:0]}; `SETZ: ResultC = iChannel_Ax; // {Source0[95:64],Source0[63:32],Source1[95:64]}; `INC,`INCX,`INCY,`INCZ: ResultC = (wAddSubC_Result[63] == 1'b1) ? {1'b1,wAddSubC_Result[30:0]} : {1'b0,wAddSubC_Result[30:0]}; //wAddSubC_Result[31:0];// & 32'h7FFFFFFF; `DEC: ResultC = (wAddSubC_Result[63] == 1'b1) ? {1'b1,wAddSubC_Result[30:0]} : {1'b0,wAddSubC_Result[30:0]}; //wAddSubC_Result[31:0];// & 32'h7FFFFFFF; `MOD: ResultC = wModulus2N_ResultC; `FRAC: ResultC = iChannel_Az & (`WIDTH'hFFFFFFFF >> (`WIDTH - `SCALE)); `MULP: ResultC = wMultiplicationA_Result[31:0]; `NEG: ResultC = ~iChannel_Az + 1'b1; `XCHANGEX: ResultC = iChannel_Az; default: begin `ifdef DEBUG //$display("%dns ALU: Error Unknown Operation: %d",$time,iOperation); //$stop(); `endif ResultC = 32'b0; end endcase end //------------------------------------------------------------------------ always @ ( * ) begin case (iOperation) `JMP: oBranchTaken = 1; `JGX: oBranchTaken = wArithmeticComparison_Result; `JGY: oBranchTaken = wArithmeticComparison_Result; `JGZ: oBranchTaken = wArithmeticComparison_Result; `JLX: oBranchTaken = wArithmeticComparison_Result; `JLY: oBranchTaken = wArithmeticComparison_Result; `JLZ: oBranchTaken = wArithmeticComparison_Result; `JEQX: oBranchTaken = wArithmeticComparison_Result; `JEQY: oBranchTaken = wArithmeticComparison_Result; `JEQZ: oBranchTaken = wArithmeticComparison_Result; `JNEX: oBranchTaken = wArithmeticComparison_Result; `JNEY: oBranchTaken = wArithmeticComparison_Result; `JNEZ: oBranchTaken = wArithmeticComparison_Result; `JGEX: oBranchTaken = wArithmeticComparison_Result; `JGEY: oBranchTaken = wArithmeticComparison_Result; `JGEZ: oBranchTaken = wArithmeticComparison_Result; `JLEX: oBranchTaken = wArithmeticComparison_Result; `JLEY: oBranchTaken = wArithmeticComparison_Result; `JLEZ: oBranchTaken = wArithmeticComparison_Result; default: oBranchTaken = 0; endcase end always @ ( * ) begin case (iOperation) `JMP,`JGX,`JGY,`JGZ,`JLX,`JLY,`JLZ,`JEQX,`JEQY,`JEQZ, `JNEX,`JNEY,`JNEZ,`JGEX,`JGEY,`JGEZ: oBranchNotTaken = !oBranchTaken && OutputReady; `JLEX: oBranchNotTaken = !oBranchTaken && OutputReady; `JLEY: oBranchNotTaken = !oBranchTaken && OutputReady; `JLEZ: oBranchNotTaken = !oBranchTaken && OutputReady; default: oBranchNotTaken = 0; endcase end //------------------------------------------------------------------------ //Output ready logic Stuff for Division... //Some FFT will hopefully do the trick wire wDivisionOutputReadyA,wDivisionOutputReadyB,wDivisionOutputReadyC; wire wDivisionOutputReady; assign wAddSubAOutputReady = wAddSubA_OutputReady; assign wAddSubBOutputReady = wAddSubB_OutputReady; assign wAddSubCOutputReady = wAddSubC_OutputReady; FFT1 FFT_DivisionA ( .D(1'b1), .Clock( wDivisionA_OutputReady ), .Reset( iInputReady ), .Q( wDivisionOutputReadyA ) ); FFT1 FFT_DivisionB ( .D(1'b1), .Clock( wDivisionB_OutputReady ), .Reset( iInputReady ), .Q( wDivisionOutputReadyB ) ); FFT1 FFT_DivisionC ( .D(1'b1), .Clock( wDivisionC_OutputReady ), .Reset( iInputReady ), .Q( wDivisionOutputReadyC ) ); assign wDivisionOutputReady = ( wDivisionOutputReadyA && wDivisionOutputReadyB && wDivisionOutputReadyC ); assign wMultiplicationOutputReadyA = wMultiplicationA_OutputReady; assign wMultiplicationOutputReadyB = wMultiplicationB_OutputReady; assign wMultiplicationOutputReadyC = wMultiplicationC_OutputReady; assign wMultiplicationOutputReadyD = wMultiplicationD_OutputReady; assign wMultiplicationOutputReady = ( wMultiplicationOutputReadyA && wMultiplicationOutputReadyB && wMultiplicationOutputReadyC ); wire wSquareRootOutputReady; FFT1 FFT_Sqrt ( .D(1'b1), .Clock( wSquareRoot_OutputReady ), .Reset( iInputReady ), .Q( wSquareRootOutputReady ) ); //------------------------------------------------------------------------ wire wOutputDelay1Cycle; FFD_POSEDGE_ASYNC_RESET # (1) FFOutputReadyDelay2 ( .Clock( Clock ), .Clear( Reset ), .D( iInputReady ), .Q( wOutputDelay1Cycle ) ); wire [`INSTRUCTION_OP_LENGTH-1:0] wOperation; FFD_POSEDGE_SYNCRONOUS_RESET # ( `INSTRUCTION_OP_LENGTH ) SourceZ2 ( .Clock( Clock ), .Reset( Reset ), .Enable( iInputReady ), .D( iOperation ), .Q(wOperation) ); //Mux for output ready signal always @ ( * ) begin case ( wOperation ) `UNSCALE: OutputReady = wOutputDelay1Cycle; `RETURN: OutputReady = wOutputDelay1Cycle; `NOP: OutputReady = wOutputDelay1Cycle; `FRAC: OutputReady = wOutputDelay1Cycle; `NEG: OutputReady = wOutputDelay1Cycle; `ifdef DEBUG //Debug Print behaves as a NOP in terms of ALU... `DEBUG_PRINT: OutputReady = wOutputDelay1Cycle; `endif `ADD,`INC,`INCX,`INCY,`INCZ: OutputReady = wAddSubAOutputReady && wAddSubBOutputReady && wAddSubCOutputReady; `SUB,`DEC: OutputReady = wAddSubAOutputReady && wAddSubBOutputReady && wAddSubCOutputReady; `DIV: OutputReady = wDivisionOutputReady; `MUL,`IMUL: OutputReady = wMultiplicationOutputReady; `MULP: OutputReady = wMultiplicationOutputReadyA; `DOT: OutputReady = wAddSubBOutputReady; `CROSS: OutputReady = wAddSubAOutputReady && wAddSubBOutputReady && wAddSubCOutputReady; `MAG: OutputReady = wSquareRootOutputReady; `ZERO: OutputReady = wOutputDelay1Cycle; `COPY: OutputReady = wOutputDelay1Cycle; `SWIZZLE3D: OutputReady = wOutputDelay1Cycle; `SETX,`SETY,`SETZ,`JMP: OutputReady = wOutputDelay1Cycle; `JGX,`JGY,`JGZ: OutputReady = ArithmeticComparison_OutputReady; `JLX,`JLY,`JLZ: OutputReady = ArithmeticComparison_OutputReady; `JEQX,`JEQY,`JEQZ: OutputReady = ArithmeticComparison_OutputReady; `JNEX,`JNEY,`JNEZ: OutputReady = ArithmeticComparison_OutputReady; `JGEX,`JGEY,`JGEZ: OutputReady = ArithmeticComparison_OutputReady; `JLEX,`JLEY,`JLEZ: OutputReady = ArithmeticComparison_OutputReady; `MOD: OutputReady = wAddSubAOutputReady && //TODO: wait 1 more cycle wAddSubBOutputReady && wAddSubCOutputReady; `XCHANGEX: OutputReady = wOutputDelay1Cycle; default: begin OutputReady = 32'b0; $display("*** ALU ERROR: iOperation = %d ***",iOperation); end endcase end endmodule //------------------------------------------------------------------------
Go to most recent revision | Compare with Previous | Blame | View Log