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

Subversion Repositories systemc_cordic

[/] [systemc_cordic/] [trunk/] [cordic_ip/] [testbench.cpp.nop] - Rev 4

Compare with Previous | Blame | View Log

// testbench.cpp: source file
/********************************************************************
// 
// Module:
//   Testbench feeding instructions into Cordic core
//
// Implementation:
//   This module tests the Rotate, Magnitude-Phase, Sin-Cos and
//   Sinh-Cosh CORDIC engines.
//
//
// Authors:     Winnie Cheng<wwcheng@stanford.edu>,
//              Peter Wu<peter5@stanford.edu>
//
 *********************************************************************/

#include "testbench.h"
#include "opcode.h"
#include "convert.h"
#include <math.h>

#define ROTATE_NUM_TEST         5
#define MAGPHASE_NUM_TEST       5       
#define SINCOS_NUM_TEST         5       
#define SINHCOSH_NUM_TEST       500     

#ifdef MODULE_NAME
#undef MODULE_NAME
#endif

#define MODULE_NAME     "[testbench]"

void testbench::testbench_process()
{
    short i;
    double x, y, a;
    double rad, correct_x, correct_y;
    double computed_v1, computed_v2;
    bool success;

    // Initialize output
    
    done.write(false);
    instructions_valid.write(false);
    wait();

    wait_until(start.delayed()==true);
    printf("%s Testbench for CORDIC engines\n", MODULE_NAME);
    success = true;

    // Test Rotate Engine
    for(i = 0; i < ROTATE_NUM_TEST; i++) {
        wait();
    
        // Generate random input
        a = 1.0*((rand()>>2)%360)-180.0;
        x = 1.0*((rand()>>2)%100);
        y = 1.0*((rand()>>2)%100);     
        cout << MODULE_NAME << "Rotate(" << x << ", " << y << ", " << a << ")" << endl;

        // activate the rotate engine
        engine_select.write(I_ROTATE);  
        operand1.write(toint(x));       // orgX
        operand2.write(toint(y));       // orgY
        operand3.write(toint(a));       // angle
        instructions_valid.write(true);
        wait();

        // pulse instructions valid
        instructions_valid.write(false);
        wait_until(compute_done.delayed()==true);

        // Read Computed Results
        computed_v1 = tofp(result1.read());
        computed_v2 = tofp(result2.read());

        // Check Result
        rad=(3.1415926*a)/180.0;
        correct_x=x*cos(rad)-y*sin(rad); /* Perform "perfect" rotation by  */
        correct_y=y*cos(rad)+x*sin(rad); /* using f.p. and transcendentals */

        if ((fabs(computed_v1-correct_x)>0.15) || 
            (fabs(computed_v2-correct_y)>0.15)) {
            cout << MODULE_NAME << "ERROR computed=" << computed_v1 << ",";
            cout << computed_v2 << " expected=" << correct_x << ",";
            cout << correct_y << endl;
            success = false;
        } else {
            cout << MODULE_NAME << "CORRECT" << endl;
        }

        wait();

    } // end Test Rotate Engine

    // Test MagPhase Engine
    for(i = 0; i < MAGPHASE_NUM_TEST; i++) {
        wait();
        x = 2.0*((rand()>>2)%100) - 100;
        y = 2.0*((rand()>>2)%100) - 100;     
        cout << MODULE_NAME << "Mag and Phase(" << x << ", " << y << ") " << endl;

        // activate the rotate engine
        engine_select.write(I_MAGPHASE);        
        operand1.write(toint(x));       // orgX
        operand2.write(toint(y));       // orgY
        instructions_valid.write(true);
        wait();

        // pulse instructions valid
        instructions_valid.write(false);
        wait_until(compute_done.delayed()==true);

        // Read Computed Results
        computed_v1 = tofp(result1.read());
        computed_v2 = tofp(result2.read());

        // Check Result
        correct_x=sqrt(x*x+y*y); /* Perform "perfect" magnitude */ 
        correct_y=atan(y/x)*180/3.1415926;

        if (x<0 && y>0)
           correct_y = 180 + correct_y;
        if (x<0 && y<=0)
           correct_y = -180 + correct_y;

        if ((fabs(computed_v1-correct_x)>0.15) || 
            (fabs(computed_v2-correct_y)>0.15)) {
            cout << MODULE_NAME << "ERROR computed=" << computed_v1 << ",";
            cout << computed_v2 << " expected=" << correct_x << ",";
            cout << correct_y << endl;
            success = false;
        } else {
            cout << MODULE_NAME << "CORRECT" << endl;
        }

        wait();

    } // end Test Magnitude and Phase Engine

    // Test Sine Cosine Engine
    for(i = 0; i < SINCOS_NUM_TEST; i++) {
        wait();
        a = 1.0*((rand()>>2)%360)-180.0;
        cout << MODULE_NAME << "Sine and Cosine(" << a << ") " << endl;

        // activate the rotate engine
        engine_select.write(I_SINCOS);  
        operand1.write(toint(a));       // orgX
        instructions_valid.write(true);
        wait();

        // pulse instructions valid
        instructions_valid.write(false);
        wait_until(compute_done.delayed()==true);

        // Read Computed Results
        computed_v1 = tofp(result1.read());
        computed_v2 = tofp(result2.read());

        // Check Result
        rad=(3.1415926*a)/180.0;
        correct_x=sin(rad); /* Perform "perfect" Cosine */ 
        correct_y=cos(rad);
        if ((fabs(computed_v1-correct_x)>0.06) || 
            (fabs(computed_v2-correct_y)>0.06)) {
            cout << MODULE_NAME << "ERROR computed=" << computed_v1 << ",";
            cout << computed_v2 << " expected=" << correct_x << ",";
            cout << correct_y << endl;
            success = false;
        } else {
            cout << MODULE_NAME << "CORRECT" << endl;
        }

        wait();

    } // end Test Sine and Cosine Engine

    // Test Sinh Cosh Engine
    for(i = 0; i < SINHCOSH_NUM_TEST; i++) {
        wait();
        a = 1.0*((rand()>>2)%90)-45.0;
        if(a < 0 && a > -3) a = -3;     // adjust for algorithm inaccuracies
        cout << MODULE_NAME << "Sinh and Cosh(" << a << ") " << endl;
        // activate the rotate engine
        engine_select.write(I_SINHCOSH);        
        operand1.write(toint(a));       // orgX
        instructions_valid.write(true);
        wait();

        // pulse instructions valid
        instructions_valid.write(false);
        wait_until(compute_done.delayed()==true);

        // Read Computed Results
        computed_v1 = tofp(result1.read());
        computed_v2 = tofp(result2.read());

        // Check Result
        rad=(3.1415926*a)/180.0;
        correct_x=sinh(rad); /* Perform "perfect" Cosine */ 
        correct_y=cosh(rad);

        if ((fabs(computed_v1-correct_x)>0.06) || 
            (fabs(computed_v2-correct_y)>0.06)) {
            cout << MODULE_NAME << "ERROR computed=" << computed_v1 << ",";
            cout << computed_v2 << " expected=" << correct_x << ",";
            cout << correct_y << endl;
            success = false;
        } else {
            cout << MODULE_NAME << "CORRECT" << endl;
        }

        wait();

    } // end Test Sinh and Cosh Engine
  
    cout << MODULE_NAME << "Testbench completed - ";
    if(success) {
        cout << "SUCCESS" << endl;
    } else {
        cout << "FAILED" << endl;
    }
    done.write(true);
    // end of test vectors
}

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.