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

Subversion Repositories systemc_cordic

[/] [systemc_cordic/] [trunk/] [cordic_ip/] [decoder.cpp] - Rev 3

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

// decoder.cpp: source file
/********************************************************************
// 
// Module:
//   Instruction Decoding Unit
//
// Implementation:
//   This module decodes the instruction and sets up the 12-stage
//   CORDIC pipeline
//
//
// Authors: 	Winnie Cheng <wwcheng@stanford.edu>,
//		Peter Wu <peter5@stanford.edu>
//
 *********************************************************************/
 
#include "decoder.h"
#include "opcode.h"
#include "convert.h"
 
#ifdef MODULE_NAME
#undef MODULE_NAME
#endif
 
#define MODULE_NAME	"decoder"
 
#define DEBUG		1
#if DEBUG
#define dprintf		printf
#else
#define dprintf
#endif
 
#define NUM_STAGES	12
#define IDLE_SLACK	2*NUM_STAGES
 
void decoder::decoder_process()
{
    short flush;
    sc_uint<UNIT_SEL_WIDTH> ir;
    short op1, op2, op3;
 
    short x, y, acc_phase, desired_phase;
    short tmp_x;
 
    // On reset, initialize output
    enable_pipeline.write(false);
    out_x.write(0);
    out_y.write(0);
    out_acc_phase.write(0);
    out_opcode.write(I_NOP);
    out_desired_phase.write(0);
    flush = NUM_STAGES + IDLE_SLACK;
 
    while(1) {  
        wait();
        if(start.read()==true) {
            flush = NUM_STAGES + IDLE_SLACK;	// reset counter
 
	    // Registered input
	    if(instruction_valid.read()==true) {
                // Read registered input
                ir = opcode.read();
		op1 = operand1.read();
		op2 = operand2.read();
		op3 = operand3.read();
 
                // Decode the opcode and adjust input
		if(ir == I_ROTATE) {
 
	            // Rotate Instruction Format
	            //   operand1 : orgX
	            //   operand2 : orgY
	            //   operand3 : angle
	            // returns
	            //   result1 : rotated x-coordinate
	            //   result2 : rotated y-coordinate   
 
		    x = op1;
		    y = op2;
		    acc_phase = op3;
 
		    if(acc_phase < 0) {
	                // If vector lies in fourth-quadrant, position to first-quadrant
		        x = -op1;
		        y = -op2;
			acc_phase += INT180;
	            }   
		    if (acc_phase > INT90) {
	                // If vector lies in third-quadrant, position to first-quadrant
		         tmp_x = x;
			 x = -y;
		         y = tmp_x;
	                 acc_phase -=INT90;
		    }
 
                    dprintf("[%s] ROTATE\n", MODULE_NAME);
 
		} else if (ir == I_MAGPHASE) {
 
	            // Magphase Instruction Format
	            //   operand1 : X
	            //   operand2 : Y
	            // returns
	            //   result1 : magnitude
	            //   result2 : phase
 
                   x = op1;
		   y = op2;
 
                   if(x < 0) {
                       // rotate by an initial +/- 90 degrees
		       tmp_x = x; 
		       if( y > 0) {
		           x = y;
			   y = -tmp_x;
			   acc_phase = -INT90;	// subtract 90 deg
		       } else {
		           x = -y;
			   y = tmp_x;
			   acc_phase = INT90;	// add 90 deg
		       }
                   } else {
		       acc_phase = 0;
		   }    
                    dprintf("[%s] MAG-PHASE\n", MODULE_NAME);
		} else if (ir == I_SINCOS) {
 
	            // SinCos Instruction Format
	            //   operand1 : phase
	            // return
	            //   result1 : sin(phase)
	            //   result2 : cos(phase)
 
                    desired_phase = op1;
 
                    // start with +90, -90, or 0 degrees
	            if(desired_phase > INT90) {
	                x = 0;
	                y = START_SINCOS_Y;	// adjust with mult factor
                        acc_phase = INT90;
	            } else if (desired_phase < -INT90) {
	                x = 0;
	                y = -START_SINCOS_Y;
                        acc_phase = -INT90;
	            } else {
	                x = START_SINCOS_Y;
	                y = 0;
	                acc_phase = 0;
	            }   
                    dprintf("[%s] SIN-COS\n", MODULE_NAME);
		} else if (ir == I_SINHCOSH) {
 
	            // SinhCosh Instruction Format
	            //   operand1 : phase
	            // return
	            //   result1 : sinh(phase)
	            //   result2 : cosh(phase)	 
 
                    desired_phase = op1;
		    x = START_SINHCOSH_X;
		    y = 0;
		    acc_phase = 0;
                    dprintf("[%s] SINH-COSH\n", MODULE_NAME);
		}
 
		// write output
		enable_pipeline.write(true);
		out_x.write(x);
		out_y.write(y);
		out_acc_phase.write(acc_phase);
		out_opcode.write(ir);
		out_desired_phase.write(desired_phase);
 
	    } else {
                // feed with NOP
		enable_pipeline.write(true);
                out_x.write(0);
                out_y.write(0);
                out_acc_phase.write(0);
                out_opcode.write(I_NOP);
                out_desired_phase.write(0);
	    }
	} else {
            if(flush > 0) {
                // keep pipeline enable, flush with NOP
	        enable_pipeline.write(true);
		flush--;
	    } else {
	        enable_pipeline.write(false);
		printf("[%s] Pipeline shutdown for power-save mode\n", MODULE_NAME);
	    }	
            out_x.write(0);
            out_y.write(0);
            out_acc_phase.write(0);
            out_opcode.write(I_NOP);
            out_desired_phase.write(0);
	}
 
    } // forever-loop	
}
 

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.