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

Subversion Repositories theia_gpu

[/] [theia_gpu/] [branches/] [icarus_version/] [rtl/] [Module_ExecutionFSM.v] - Rev 214

Go to most recent revision | Compare with Previous | Blame | View Log

`timescale 1ns / 1ps
`include "aDefinitions.v"
`ifdef VERILATAOR
`endif
/**********************************************************************************
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.
 
***********************************************************************************/
`define EXEU_AFTER_RESET             0
`define EXEU_INITIAL_STATE           1
`define EXEU_WAIT_FOR_DECODE         2
`define EXEU_FETCH_DECODED_INST      3
`define EXEU_WAIT_FOR_ALU_EXECUTION  4
`define EXEU_WRITE_BACK_TO_RAM       5
`define EXEU_HANDLE_JUMP             7
 
 
 
module ExecutionFSM
(
input wire                              Clock,
input wire                              Reset,
 
input wire                              iDecodeDone,
input wire[`INSTRUCTION_OP_LENGTH-1:0]  iOperation,
input wire[`DATA_ROW_WIDTH-1:0]         iSource0,iSource1,
input wire[`DATA_ADDRESS_WIDTH-1:0]     iDestination,
inout wire[`DATA_ROW_WIDTH-1:0]         RAMBus,
output wire                             oJumpFlag    ,
output  wire [`ROM_ADDRESS_WIDTH-1:0]   oJumpIp     ,
output  wire                            oRAMWriteEnable  ,
output  wire [`DATA_ADDRESS_WIDTH-1:0]  oRAMWriteAddress  ,
output  wire                            oExeLatchedValues,
output  reg                             oBusy ,
 
//ALU ports and control signals
output  wire [`INSTRUCTION_OP_LENGTH-1:0]    oALUOperation,  
output  wire [`WIDTH-1:0]                    oALUChannelX1,
output  wire [`WIDTH-1:0]                    oALUChannelY1,
output  wire [`WIDTH-1:0]                    oALUChannelZ1,
output  wire [`WIDTH-1:0]                    oALUChannelX2,
output  wire [`WIDTH-1:0]                    oALUChannelY2,
output  wire [`WIDTH-1:0]                    oALUChannelZ2,
output  wire                                 oTriggerALU,
 
input  wire   [`WIDTH-1:0]                   iALUResultX,
input  wire   [`WIDTH-1:0]                   iALUResultY,
input wire   [`WIDTH-1:0]                    iALUResultZ,
input wire                                   iALUOutputReady,
input wire                                   iBranchTaken,
input wire                                   iBranchNotTaken,
 
 
`ifdef DEBUG 
 input wire[`ROM_ADDRESS_WIDTH-1:0]  iDebug_CurrentIP,
 input wire [`MAX_CORES-1:0]         iDebug_CoreID,
`endif
//Data forward Signals
output wire [`DATA_ADDRESS_WIDTH-1:0] oLastDestination
 
 
);
 
wire wLatchNow;
reg rInputLatchesEnabled;
 
//If ALU says jump, just pass along
assign oJumpFlag = iBranchTaken; 
//JumpIP is the instruction destination (= oRAMWriteAddress)
assign oJumpIp = oRAMWriteAddress;
 
assign wLatchNow = iDecodeDone & rInputLatchesEnabled;
assign oExeLatchedValues = wLatchNow;
assign oTriggerALU = wLatchNow;
 
wire wOperationIsJump;
assign wOperationIsJump = iBranchTaken || iBranchNotTaken;
 
//Don't allow me to write back back if the operation is a NOP
`ifdef DEBUG
 assign oRAMWriteEnable = iALUOutputReady && (!wOperationIsJump || oALUOperation == `RET ) && 
  (oALUOperation != `NOP) && oALUOperation != `DEBUG_PRINT;
`else
 assign oRAMWriteEnable = iALUOutputReady && (!wOperationIsJump || oALUOperation == `RET) && oALUOperation != `NOP;
`endif 
 
 
assign RAMBus = ( oRAMWriteEnable ) ? {iALUResultX,iALUResultY,iALUResultZ} : `DATA_ROW_WIDTH'bz;
 
assign oALUChannelX1 = iSource1[95:64];
assign oALUChannelY1 = iSource1[63:32];
assign oALUChannelZ1 = iSource1[31:0];
 
assign oALUChannelX2 = iSource0[95:64];
assign oALUChannelY2 = iSource0[63:32];
assign oALUChannelZ2 = iSource0[31:0];
 
assign oALUOperation = iOperation;
 
FFD_POSEDGE_SYNCRONOUS_RESET # ( `DATA_ADDRESS_WIDTH ) PSRegDestination
(
 .Clock( Clock ),//wLatchNow ),
 .Reset( Reset),
 .Enable( wLatchNow ),//1'b1 ),
 .D( iDestination ),
 .Q(oRAMWriteAddress)
);
 
//Data forwarding
assign oLastDestination = oRAMWriteAddress;
 
reg [7:0] CurrentState; 
reg [7:0] NextState; 
 
 
//------------------------------------------------
  always @(posedge Clock or posedge Reset) 
  begin 
 
 
 
    if (Reset)  
  CurrentState <= `EXEU_AFTER_RESET; 
    else        
  CurrentState <= NextState; 
 
  end
//------------------------------------------------
 
 
always @( * ) 
   begin 
        case (CurrentState) 
    //------------------------------------------
    `EXEU_AFTER_RESET:
    begin
    //ReadyForNextInstruction = 1;
    oBusy       = 0;
    rInputLatchesEnabled  = 1;
 
 
    NextState  = `EXEU_WAIT_FOR_DECODE;
    end
    //------------------------------------------
    /**
   At the same time iDecodeDone goes to 1, our Flops
   will store the value, so next clock cycle we can
   tell IDU to go ahead and decode the next instruction
   in the pipeline.
    */
    `EXEU_WAIT_FOR_DECODE:
    begin
 
 
    //ReadyForNextInstruction = 1;
    oBusy       = 0;
    rInputLatchesEnabled  = 1;
 
 
   if ( iDecodeDone ) //This same thing triggers the ALU
    NextState = `EXEU_WAIT_FOR_ALU_EXECUTION;
   else
    NextState = `EXEU_WAIT_FOR_DECODE;
    end
    //------------------------------------------
    /*
    If the instruction is aritmetic then pass the parameters
    the ALU, else if it store iOperation then...
    */
    `EXEU_WAIT_FOR_ALU_EXECUTION:
    begin
 
    //ReadyForNextInstruction = 0;      //*
    oBusy       = 1;
    rInputLatchesEnabled  = 0;  //NO INTERRUPTIONS WHILE WE WAIT!!
 
 
 
    if ( iALUOutputReady ) /////This same thing enables writing th results to RAM
     NextState = `EXEU_WAIT_FOR_DECODE; 
    else 
     NextState = `EXEU_WAIT_FOR_ALU_EXECUTION; 
    end
    //------------------------------------------
    `EXEU_WRITE_BACK_TO_RAM:
    begin
 
    //ReadyForNextInstruction = 0;      
    oBusy       = 1;
    rInputLatchesEnabled  = 1;
 
   if ( iDecodeDone )
    NextState = `EXEU_WAIT_FOR_ALU_EXECUTION;
   else
    NextState = `EXEU_WAIT_FOR_DECODE;
 
    end
 
    //------------------------------------------
    default:
    begin
 
    //ReadyForNextInstruction = 1;
    oBusy       = 0;
    rInputLatchesEnabled  = 1;
 
    NextState = `EXEU_AFTER_RESET;
    end
    //------------------------------------------
 endcase
end
 
//-----------------------------------------------------------------------
`ifdef DUMP_CODE
integer ucode_file;
integer reg_log;
initial
begin
 
 $display("Opening ucode dump file....\n");
 ucode_file = $fopen("Code.log","w");
 $fwrite(ucode_file,"\n\n************ Theia UCODE DUMP *******\n\n\n\n");
 $display("Opening Register lof file...\n");
 reg_log = $fopen("Registers.log","w");
 
end
 
`endif //Ucode dump
 
//-----------------------------------------------------------------------
`ifdef DEBUG
wire [`WIDTH-1:0] wALUChannelX1,wALUChannelY1,wALUChannelZ1;
wire [`WIDTH-1:0] wALUChannelX2,wALUChannelY2,wALUChannelZ2;
 
FFD_POSEDGE_SYNCRONOUS_RESET # ( `WIDTH ) SourceX1
(
 .Clock( Clock ),
 .Reset( Reset),
 .Enable( wLatchNow ),
 .D( iSource1[95:64] ),
 .Q(wALUChannelX1)
);
FFD_POSEDGE_SYNCRONOUS_RESET # ( `WIDTH ) SourceY1
(
 .Clock( Clock ),
 .Reset( Reset),
 .Enable( wLatchNow ),
 .D( iSource1[63:32] ),
 .Q(wALUChannelY1)
);
FFD_POSEDGE_SYNCRONOUS_RESET # ( `WIDTH ) SourceZ1
(
 .Clock( Clock ),
 .Reset( Reset),
 .Enable( wLatchNow ),
 .D( iSource1[31:0] ),
 .Q(wALUChannelZ1)
);
 
 
FFD_POSEDGE_SYNCRONOUS_RESET # ( `WIDTH ) SourceX2
(
 .Clock( Clock ),
 .Reset( Reset),
 .Enable( wLatchNow ),
 .D( iSource0[95:64] ),
 .Q(wALUChannelX2)
);
FFD_POSEDGE_SYNCRONOUS_RESET # ( `WIDTH ) SourceY2
(
 .Clock( Clock ),
 .Reset( Reset),
 .Enable( wLatchNow ),
 .D( iSource0[63:32] ),
 .Q(wALUChannelY2)
);
FFD_POSEDGE_SYNCRONOUS_RESET # ( `WIDTH ) SourceZ2
(
 .Clock( Clock ),
 .Reset( Reset),
 .Enable( wLatchNow ),
 .D( iSource0[31:0] ),
 .Q(wALUChannelZ2)
);
 
 
 always @ (posedge iDecodeDone && iDebug_CoreID == `DEBUG_CORE)
 begin
  `LOGME"[CORE %d] IP:%d", iDebug_CoreID,iDebug_CurrentIP);
 end
 
 always @ (negedge  Clock && iDebug_CoreID == `DEBUG_CORE)
 begin
 if ( iALUOutputReady )
 begin
 
 
  if (iBranchTaken)
   `LOGME"<BT>");
 
  if (iBranchNotTaken )
   `LOGME"<BNT>");
 
  if (oRAMWriteEnable)
   `LOGME"<WE>");
 
  `LOGME "(%dns ",$time); 
     case ( oALUOperation )
     `RETURN: `LOGME"RETURN"); 
     `ADD:  `LOGME"ADD");    
     `SUB:  `LOGME"SUB"); 
     `DIV:  `LOGME"DIV");  
     `MUL:  `LOGME"MUL");   
     `MAG:  `LOGME"MAG"); 
     `JGX:  `LOGME"JGX");
     `JLX:  `LOGME"JLX");     
     `JGEX: `LOGME"JGEX");    
     `JGEY: `LOGME"JGEY");   
     `JGEZ: `LOGME"JGEZ");   
     `JLEX: `LOGME"JLEX");   
     `JLEY: `LOGME"JLEY");   
     `JLEZ: `LOGME"JLEZ");   
     `JMP:  `LOGME"JMP");      
     `ZERO: `LOGME"ZERO");   
     `JNEX: `LOGME"JNEX");   
     `JNEY: `LOGME"JNEY");   
     `JNEZ: `LOGME"JNEZ");   
     `JEQX: `LOGME"JEQX");   
     `JEQY: `LOGME"JEQY");   
     `JEQZ: `LOGME"JEQZ");   
     `CROSS: `LOGME"CROSS");   
     `DOT:  `LOGME"DOT");   
     `SETX: `LOGME"SETX");   
     `SETY: `LOGME"SETY");   
     `SETZ: `LOGME"SETZ");
     `NOP:  `LOGME"NOP");
     `COPY: `LOGME"COPY");
     `INC:  `LOGME"INC");
     `DEC:  `LOGME"DEC");
     `MOD:  `LOGME"MOD");
     `FRAC: `LOGME"FRAC");
     `NEG:    `LOGME"NEG");
     `SWIZZLE3D: `LOGME"SWIZZLE3D");
     `MULP:  `LOGME"MULP");
     `XCHANGEX:  `LOGME"XCHANGEX");
	  `XCHANGEY:  `LOGME"XCHANGEY");
	  `XCHANGEZ:  `LOGME"XCHANGEZ");
     `IMUL:      `LOGME"IMUL");
     `UNSCALE:   `LOGME"UNSCALE");
	  `RESCALE:    `LOGME"UNSCALE");
     `INCX: `LOGME"INCX");
     `INCY: `LOGME"INCY");
     `INCZ: `LOGME"INCZ");
     `OMWRITE: `LOGME"OMWRITE");
     `TMREAD: `LOGME"TMREAD");
     `LEA:     `LOGME"LEA");
     `CALL:    `LOGME"CALL");
     `RET:     `LOGME"RET");
     `DEBUG_PRINT:
     begin
      `LOGME"DEBUG_PRINT");
 
     end
     default:
     begin
      `LOGME"**********ERROR UNKNOWN OP*********");
      $display("%dns EXE: Error Unknown Instruction : %d", $time,oALUOperation);
     // $stop();
     end 
     endcase
 
     `LOGME"\t %h [ %h %h %h ][ %h %h %h ] = ",
     oRAMWriteAddress,
     wALUChannelX1,wALUChannelY1,wALUChannelZ1,
     wALUChannelX2,wALUChannelY2,wALUChannelZ2
 
     );
 
     if (oALUOperation == `RETURN)
      `LOGME"\n\n\n");
 
  end   
 end //always
 
 always @ ( negedge Clock && iDebug_CoreID == `DEBUG_CORE )
 begin
 if ( iALUOutputReady )
  `LOGME" [ %h %h %h ])\n",iALUResultX,iALUResultY,iALUResultZ);
 end //always
`endif
 
endmodule
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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