URL
https://opencores.org/ocsvn/systemc_cordic/systemc_cordic/trunk
Subversion Repositories systemc_cordic
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 2 to Rev 3
- ↔ Reverse comparison
Rev 2 → Rev 3
/trunk/cordic_ip/cordic.cpp
0,0 → 1,170
// cordic.cpp: source file |
/******************************************************************** |
// |
// Module: |
// Cordic Engine Pipeline Stage |
// |
// Implementation: |
// This module implements one pipeline stage of the cordic engine. |
// |
// |
// Authors: Winnie Cheng <wwcheng@stanford.edu>, |
// Peter Wu <peter5@stanford.edu> |
// |
*********************************************************************/ |
|
#include "cordic.h" |
#include "opcode.h" |
|
#ifdef MODULE_NAME |
#undef MODULE_NAME |
#endif |
|
#define MODULE_NAME "cordic" |
|
#define DEBUG 1 |
#if DEBUG |
#define dprintf printf |
#else |
#define dprintf |
#endif |
|
void cordic::cordic_process() |
{ |
|
bool enable; |
|
short opcode; |
short desired_phase; |
|
short x, y, acc_phase; |
|
short type, tmp_x, table_value, cond; |
|
// stage parameters |
short reg_stage_num, reg_tablep, reg_tableh; |
|
// On Reset, initialize output |
done.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); |
|
// Get stage parameters for this stage |
reg_stage_num = stage_num.read(); |
reg_tablep = tablep.read(); |
reg_tableh = tableh.read(); |
|
while(1) { |
|
wait(); |
|
// Registered Input |
enable = start.read(); |
// input data from previous stage |
x = in_x.read(); |
y = in_y.read(); |
acc_phase = in_acc_phase.read(); |
// input data propagated |
opcode = in_opcode.read(); |
desired_phase = in_desired_phase.read(); |
|
if(enable) { |
|
// do stage operation |
|
// condition varies for different opcode |
if(opcode == I_ROTATE) { |
cond = (acc_phase < 0); |
type = TYPE_NONHYPER; |
table_value = -reg_tablep; |
dprintf("[%s%02d] ROTATE\n", MODULE_NAME, reg_stage_num); |
} else if (opcode == I_MAGPHASE) { |
cond = (y >= 0); |
type = TYPE_NONHYPER; |
table_value = reg_tablep; |
dprintf("[%s%02d] MAG-PHASE\n", MODULE_NAME, reg_stage_num); |
} else if (opcode == I_SINCOS) { |
cond = (desired_phase - acc_phase < 0); |
type = TYPE_NONHYPER; |
table_value = reg_tablep; |
dprintf("[%s%02d] SIN-COS\n", MODULE_NAME, reg_stage_num); |
} else if (opcode == I_SINHCOSH) { |
cond = (desired_phase - acc_phase < 0); |
type = TYPE_HYPER; |
table_value = reg_tableh; |
dprintf("[%s%02d] SINH-COSH\n", MODULE_NAME, reg_stage_num); |
} else { |
// treat as NOP |
type = TYPE_NOP; |
dprintf("[%s%02d] NOP\n", MODULE_NAME, reg_stage_num); |
} |
|
tmp_x = x; |
if(type == TYPE_NONHYPER) { |
// non-hyperbolic functions |
if(cond) { |
x += y >> reg_stage_num; |
y -= tmp_x >> reg_stage_num; |
acc_phase -= table_value; |
} else { |
x -= y >> reg_stage_num; |
y += tmp_x >> reg_stage_num; |
acc_phase += table_value; |
} |
|
// Output results |
done.write(true); |
out_x.write(x); |
out_y.write(y); |
out_acc_phase.write(acc_phase); |
out_opcode.write(opcode); |
out_desired_phase.write(desired_phase); |
|
} else if (type == TYPE_HYPER) { |
// hyperbolic functions |
|
if(cond) { |
x -= y >> (reg_stage_num+1); |
y -= tmp_x >> (reg_stage_num+1); |
acc_phase -= table_value; |
} else { |
x += y >> (reg_stage_num+1); |
y += tmp_x >> (reg_stage_num+1); |
acc_phase += table_value; |
} |
|
// Output results |
done.write(true); |
out_x.write(x); |
out_y.write(y); |
out_acc_phase.write(acc_phase); |
out_opcode.write(opcode); |
out_desired_phase.write(desired_phase); |
|
} else { |
|
// NOP, same output as reset condition except done is true |
done.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 { |
|
// same output as reset condition |
done.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); |
} |
|
} // forever loop |
} |
/trunk/cordic_ip/testrun.log
1,3 → 1,5
Your license(s) for feature `SystemCSim' expire within 5 days. |
WARNING: Default time step is used for VCD tracing. |
[testbench] Testbench for CORDIC engines |
[cordic00] NOP |
[cordic01] NOP |
/trunk/cordic_ip/decoder.cpp
0,0 → 1,201
// 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 |
} |
/trunk/cordic_ip/cordic.h
0,0 → 1,67
// cordic.h: header file |
/******************************************************************** |
// |
// Module: |
// Cordic Engine Pipeline Stage |
// |
// Interface: |
// Registered input, non-registered output |
// |
// |
// Authors: Winnie Cheng <wwcheng@stanford.edu>, |
// Peter Wu <peter5@stanford.edu> |
// |
*********************************************************************/ |
|
#include "systemc.h" |
#include "opcode.h" |
|
SC_MODULE(cordic) { |
|
// Clock Declaration |
sc_in_clk clk; |
|
// Input ports Declaration |
sc_in<bool> start; // enables the stage |
sc_in<bool> reset; |
|
// Input data - previous stage results |
sc_in<short> in_x; |
sc_in<short> in_y; |
sc_in<short> in_acc_phase; |
|
// Input data - propagated instruction info |
sc_in<sc_uint<UNIT_SEL_WIDTH> > in_opcode; |
sc_in<short> in_desired_phase; |
|
// Input data - stage parametrization |
sc_in<short> stage_num; |
sc_in<short> tablep; |
sc_in<short> tableh; |
|
// Output ports Declaration |
sc_out<bool> done; |
|
// Output data - results of this stage |
sc_out<short> out_x; |
sc_out<short> out_y; |
sc_out<short> out_acc_phase; |
|
// Output data - propagated instruction info |
sc_out<sc_uint<UNIT_SEL_WIDTH> > out_opcode; |
sc_out<short> out_desired_phase; |
|
// Declare implementation functions |
void cordic_process(); |
|
// Constructor |
SC_CTOR(cordic) |
{ |
// Register processes and define active clock edge |
SC_CTHREAD(cordic_process, clk.pos()); |
|
// Watching for global reset |
watching(reset.delayed()==true); |
} |
|
}; // end module cordic |
/trunk/cordic_ip/decoder.h
0,0 → 1,61
// decoder.h: header file |
/******************************************************************** |
// |
// Module: |
// Instruction Decoding Unit |
// |
// Interface: |
// This module interfaces to the testbench and the pipeline. |
// Registered input, non-registered output |
// |
// |
// Authors: Winnie Cheng <wwcheng@stanford.edu>, |
// Peter Wu <peter5@stanford.edu> |
// |
*********************************************************************/ |
|
#include "systemc.h" |
#include "opcode.h" |
|
SC_MODULE(decoder) { |
|
// Clock Declaration |
sc_in_clk clk; |
|
// Input ports Declaration |
sc_in<bool> start; |
sc_in<bool> reset; |
|
// Input data - instruction |
sc_in<bool> instruction_valid; |
sc_in<sc_uint<UNIT_SEL_WIDTH> > opcode; |
sc_in<short> operand1; |
sc_in<short> operand2; |
sc_in<short> operand3; |
|
// Output ports declaration |
sc_out<bool> enable_pipeline; |
|
// Output data - feed to first stage of pipeline |
sc_out<short> out_x; |
sc_out<short> out_y; |
sc_out<short> out_acc_phase; |
|
// Output data - propagated instruction info |
sc_out<sc_uint<UNIT_SEL_WIDTH> > out_opcode; |
sc_out<short> out_desired_phase; |
|
// Declare implementation functions |
void decoder_process(); |
|
// Constructor |
SC_CTOR(decoder) |
{ |
// Register processes and define active clock edge |
SC_CTHREAD(decoder_process, clk.pos()); |
|
// Watching for global reset |
watching(reset.delayed()==true); |
} |
|
}; // end module cordic |
/trunk/cordic_ip/cordpipe.h
0,0 → 1,423
// cordpipe.h: header file |
/******************************************************************** |
// |
// Module: |
// Cordic Engine 12-stage Pipeline |
// |
// Interface: |
// This module connects the 12-stages together. |
// Registered input, non-registered output |
// |
// |
// Authors: Winnie Cheng <wwcheng@stanford.edu>, |
// Peter Wu <peter5@stanford.edu> |
// |
*********************************************************************/ |
|
#include "systemc.h" |
#include "cordic.h" |
#include "opcode.h" |
|
SC_MODULE(cordpipe) { |
|
// Clock Declaration |
sc_in_clk clk; |
|
// Input ports Declaration |
sc_in<bool> start; |
sc_in<bool> reset; |
|
// Input data - first stage results |
sc_in<short> in_x; |
sc_in<short> in_y; |
sc_in<short> in_acc_phase; |
|
// Input data - propagated instruction info |
sc_in<sc_uint<UNIT_SEL_WIDTH> > in_opcode; |
sc_in<short> in_desired_phase; |
|
// Output ports Declaration |
sc_out<bool> done; |
|
// Output data - results of this stage |
sc_out<short> out_x; |
sc_out<short> out_y; |
sc_out<short> out_acc_phase; |
|
// Output data - propagated instruction info |
sc_out<sc_uint<UNIT_SEL_WIDTH> > out_opcode; |
sc_out<short> out_desired_phase; |
|
// constants to parametrize pipeline module on system reset |
sc_in<short> stage0; |
sc_in<short> stage1; |
sc_in<short> stage2; |
sc_in<short> stage3; |
sc_in<short> stage4; |
sc_in<short> stage5; |
sc_in<short> stage6; |
sc_in<short> stage7; |
sc_in<short> stage8; |
sc_in<short> stage9; |
sc_in<short> stage10; |
sc_in<short> stage11; |
|
sc_in<short> tablep_0; |
sc_in<short> tablep_1; |
sc_in<short> tablep_2; |
sc_in<short> tablep_3; |
sc_in<short> tablep_4; |
sc_in<short> tablep_5; |
sc_in<short> tablep_6; |
sc_in<short> tablep_7; |
sc_in<short> tablep_8; |
sc_in<short> tablep_9; |
sc_in<short> tablep_10; |
sc_in<short> tablep_11; |
|
sc_in<short> tableh_0; |
sc_in<short> tableh_1; |
sc_in<short> tableh_2; |
sc_in<short> tableh_3; |
sc_in<short> tableh_4; |
sc_in<short> tableh_5; |
sc_in<short> tableh_6; |
sc_in<short> tableh_7; |
sc_in<short> tableh_8; |
sc_in<short> tableh_9; |
sc_in<short> tableh_10; |
sc_in<short> tableh_11; |
|
// Signals |
sc_signal<short> out0_x; |
sc_signal<short> out1_x; |
sc_signal<short> out2_x; |
sc_signal<short> out3_x; |
sc_signal<short> out4_x; |
sc_signal<short> out5_x; |
sc_signal<short> out6_x; |
sc_signal<short> out7_x; |
sc_signal<short> out8_x; |
sc_signal<short> out9_x; |
sc_signal<short> out10_x; |
|
sc_signal<short> out0_y; |
sc_signal<short> out1_y; |
sc_signal<short> out2_y; |
sc_signal<short> out3_y; |
sc_signal<short> out4_y; |
sc_signal<short> out5_y; |
sc_signal<short> out6_y; |
sc_signal<short> out7_y; |
sc_signal<short> out8_y; |
sc_signal<short> out9_y; |
sc_signal<short> out10_y; |
|
sc_signal<short> out0_acc_phase; |
sc_signal<short> out1_acc_phase; |
sc_signal<short> out2_acc_phase; |
sc_signal<short> out3_acc_phase; |
sc_signal<short> out4_acc_phase; |
sc_signal<short> out5_acc_phase; |
sc_signal<short> out6_acc_phase; |
sc_signal<short> out7_acc_phase; |
sc_signal<short> out8_acc_phase; |
sc_signal<short> out9_acc_phase; |
sc_signal<short> out10_acc_phase; |
|
sc_signal<sc_uint<UNIT_SEL_WIDTH> > out0_opcode; |
sc_signal<sc_uint<UNIT_SEL_WIDTH> > out1_opcode; |
sc_signal<sc_uint<UNIT_SEL_WIDTH> > out2_opcode; |
sc_signal<sc_uint<UNIT_SEL_WIDTH> > out3_opcode; |
sc_signal<sc_uint<UNIT_SEL_WIDTH> > out4_opcode; |
sc_signal<sc_uint<UNIT_SEL_WIDTH> > out5_opcode; |
sc_signal<sc_uint<UNIT_SEL_WIDTH> > out6_opcode; |
sc_signal<sc_uint<UNIT_SEL_WIDTH> > out7_opcode; |
sc_signal<sc_uint<UNIT_SEL_WIDTH> > out8_opcode; |
sc_signal<sc_uint<UNIT_SEL_WIDTH> > out9_opcode; |
sc_signal<sc_uint<UNIT_SEL_WIDTH> > out10_opcode; |
|
sc_signal<short> out0_desired_phase; |
sc_signal<short> out1_desired_phase; |
sc_signal<short> out2_desired_phase; |
sc_signal<short> out3_desired_phase; |
sc_signal<short> out4_desired_phase; |
sc_signal<short> out5_desired_phase; |
sc_signal<short> out6_desired_phase; |
sc_signal<short> out7_desired_phase; |
sc_signal<short> out8_desired_phase; |
sc_signal<short> out9_desired_phase; |
sc_signal<short> out10_desired_phase; |
|
sc_signal<bool> stage0_done; |
sc_signal<bool> stage1_done; |
sc_signal<bool> stage2_done; |
sc_signal<bool> stage3_done; |
sc_signal<bool> stage4_done; |
sc_signal<bool> stage5_done; |
sc_signal<bool> stage6_done; |
sc_signal<bool> stage7_done; |
sc_signal<bool> stage8_done; |
sc_signal<bool> stage9_done; |
sc_signal<bool> stage10_done; |
|
// 12 stage instances |
cordic *s0_instance; |
cordic *s1_instance; |
cordic *s2_instance; |
cordic *s3_instance; |
cordic *s4_instance; |
cordic *s5_instance; |
cordic *s6_instance; |
cordic *s7_instance; |
cordic *s8_instance; |
cordic *s9_instance; |
cordic *s10_instance; |
cordic *s11_instance; |
|
// Constructor |
SC_CTOR(cordpipe) |
{ |
// instantiate and connect stage 0 |
s0_instance = new cordic("stage0_in_pipe"); |
s0_instance->clk(clk); |
s0_instance->start(start); |
s0_instance->reset(reset); |
s0_instance->in_x(in_x); |
s0_instance->in_y(in_y); |
s0_instance->in_acc_phase(in_acc_phase); |
s0_instance->in_opcode(in_opcode); |
s0_instance->in_desired_phase(in_desired_phase); |
s0_instance->stage_num(stage0); |
s0_instance->tablep(tablep_0); |
s0_instance->tableh(tableh_0); |
s0_instance->done(stage0_done); |
s0_instance->out_x(out0_x); |
s0_instance->out_y(out0_y); |
s0_instance->out_acc_phase(out0_acc_phase); |
s0_instance->out_opcode(out0_opcode); |
s0_instance->out_desired_phase(out0_desired_phase); |
|
// instantiate and connect stage 1 |
s1_instance = new cordic("stage1_in_pipe"); |
s1_instance->clk(clk); |
s1_instance->start(start); |
s1_instance->reset(reset); |
s1_instance->in_x(out0_x); |
s1_instance->in_y(out0_y); |
s1_instance->in_acc_phase(out0_acc_phase); |
s1_instance->in_opcode(out0_opcode); |
s1_instance->in_desired_phase(out0_desired_phase); |
s1_instance->stage_num(stage1); |
s1_instance->tablep(tablep_1); |
s1_instance->tableh(tableh_1); |
s1_instance->done(stage1_done); |
s1_instance->out_x(out1_x); |
s1_instance->out_y(out1_y); |
s1_instance->out_acc_phase(out1_acc_phase); |
s1_instance->out_opcode(out1_opcode); |
s1_instance->out_desired_phase(out1_desired_phase); |
|
// instantiate and connect stage 2 |
s2_instance = new cordic("stage2_in_pipe"); |
s2_instance->clk(clk); |
s2_instance->start(start); |
s2_instance->reset(reset); |
s2_instance->in_x(out1_x); |
s2_instance->in_y(out1_y); |
s2_instance->in_acc_phase(out1_acc_phase); |
s2_instance->in_opcode(out1_opcode); |
s2_instance->in_desired_phase(out1_desired_phase); |
s2_instance->stage_num(stage2); |
s2_instance->tablep(tablep_2); |
s2_instance->tableh(tableh_2); |
s2_instance->done(stage2_done); |
s2_instance->out_x(out2_x); |
s2_instance->out_y(out2_y); |
s2_instance->out_acc_phase(out2_acc_phase); |
s2_instance->out_opcode(out2_opcode); |
s2_instance->out_desired_phase(out2_desired_phase); |
|
// instantiate and connect stage 3 |
s3_instance = new cordic("stage3_in_pipe"); |
s3_instance->clk(clk); |
s3_instance->start(start); |
s3_instance->reset(reset); |
s3_instance->in_x(out2_x); |
s3_instance->in_y(out2_y); |
s3_instance->in_acc_phase(out2_acc_phase); |
s3_instance->in_opcode(out2_opcode); |
s3_instance->in_desired_phase(out2_desired_phase); |
s3_instance->stage_num(stage3); |
s3_instance->tablep(tablep_3); |
s3_instance->tableh(tableh_3); |
s3_instance->done(stage3_done); |
s3_instance->out_x(out3_x); |
s3_instance->out_y(out3_y); |
s3_instance->out_acc_phase(out3_acc_phase); |
s3_instance->out_opcode(out3_opcode); |
s3_instance->out_desired_phase(out3_desired_phase); |
|
// instantiate and connect stage 4 |
s4_instance = new cordic("stage4_in_pipe"); |
s4_instance->clk(clk); |
s4_instance->start(start); |
s4_instance->reset(reset); |
s4_instance->in_x(out3_x); |
s4_instance->in_y(out3_y); |
s4_instance->in_acc_phase(out3_acc_phase); |
s4_instance->in_opcode(out3_opcode); |
s4_instance->in_desired_phase(out3_desired_phase); |
s4_instance->stage_num(stage4); |
s4_instance->tablep(tablep_4); |
s4_instance->tableh(tableh_4); |
s4_instance->done(stage4_done); |
s4_instance->out_x(out4_x); |
s4_instance->out_y(out4_y); |
s4_instance->out_acc_phase(out4_acc_phase); |
s4_instance->out_opcode(out4_opcode); |
s4_instance->out_desired_phase(out4_desired_phase); |
|
// instantiate and connect stage 5 |
s5_instance = new cordic("stage5_in_pipe"); |
s5_instance->clk(clk); |
s5_instance->start(start); |
s5_instance->reset(reset); |
s5_instance->in_x(out4_x); |
s5_instance->in_y(out4_y); |
s5_instance->in_acc_phase(out4_acc_phase); |
s5_instance->in_opcode(out4_opcode); |
s5_instance->in_desired_phase(out4_desired_phase); |
s5_instance->stage_num(stage5); |
s5_instance->tablep(tablep_5); |
s5_instance->tableh(tableh_5); |
s5_instance->done(stage5_done); |
s5_instance->out_x(out5_x); |
s5_instance->out_y(out5_y); |
s5_instance->out_acc_phase(out5_acc_phase); |
s5_instance->out_opcode(out5_opcode); |
s5_instance->out_desired_phase(out5_desired_phase); |
|
// instantiate and connect stage 6 |
s6_instance = new cordic("stage6_in_pipe"); |
s6_instance->clk(clk); |
s6_instance->start(start); |
s6_instance->reset(reset); |
s6_instance->in_x(out5_x); |
s6_instance->in_y(out5_y); |
s6_instance->in_acc_phase(out5_acc_phase); |
s6_instance->in_opcode(out5_opcode); |
s6_instance->in_desired_phase(out5_desired_phase); |
s6_instance->stage_num(stage6); |
s6_instance->tablep(tablep_6); |
s6_instance->tableh(tableh_6); |
s6_instance->done(stage6_done); |
s6_instance->out_x(out6_x); |
s6_instance->out_y(out6_y); |
s6_instance->out_acc_phase(out6_acc_phase); |
s6_instance->out_opcode(out6_opcode); |
s6_instance->out_desired_phase(out6_desired_phase); |
|
// instantiate and connect stage 7 |
s7_instance = new cordic("stage7_in_pipe"); |
s7_instance->clk(clk); |
s7_instance->start(start); |
s7_instance->reset(reset); |
s7_instance->in_x(out6_x); |
s7_instance->in_y(out6_y); |
s7_instance->in_acc_phase(out6_acc_phase); |
s7_instance->in_opcode(out6_opcode); |
s7_instance->in_desired_phase(out6_desired_phase); |
s7_instance->stage_num(stage7); |
s7_instance->tablep(tablep_7); |
s7_instance->tableh(tableh_7); |
s7_instance->done(stage7_done); |
s7_instance->out_x(out7_x); |
s7_instance->out_y(out7_y); |
s7_instance->out_acc_phase(out7_acc_phase); |
s7_instance->out_opcode(out7_opcode); |
s7_instance->out_desired_phase(out7_desired_phase); |
|
// instantiate and connect stage 8 |
s8_instance = new cordic("stage8_in_pipe"); |
s8_instance->clk(clk); |
s8_instance->start(start); |
s8_instance->reset(reset); |
s8_instance->in_x(out7_x); |
s8_instance->in_y(out7_y); |
s8_instance->in_acc_phase(out7_acc_phase); |
s8_instance->in_opcode(out7_opcode); |
s8_instance->in_desired_phase(out7_desired_phase); |
s8_instance->stage_num(stage8); |
s8_instance->tablep(tablep_8); |
s8_instance->tableh(tableh_8); |
s8_instance->done(stage8_done); |
s8_instance->out_x(out8_x); |
s8_instance->out_y(out8_y); |
s8_instance->out_acc_phase(out8_acc_phase); |
s8_instance->out_opcode(out8_opcode); |
s8_instance->out_desired_phase(out8_desired_phase); |
|
// instantiate and connect stage 9 |
s9_instance = new cordic("stage9_in_pipe"); |
s9_instance->clk(clk); |
s9_instance->start(start); |
s9_instance->reset(reset); |
s9_instance->in_x(out8_x); |
s9_instance->in_y(out8_y); |
s9_instance->in_acc_phase(out8_acc_phase); |
s9_instance->in_opcode(out8_opcode); |
s9_instance->in_desired_phase(out8_desired_phase); |
s9_instance->stage_num(stage9); |
s9_instance->tablep(tablep_9); |
s9_instance->tableh(tableh_9); |
s9_instance->done(stage9_done); |
s9_instance->out_x(out9_x); |
s9_instance->out_y(out9_y); |
s9_instance->out_acc_phase(out9_acc_phase); |
s9_instance->out_opcode(out9_opcode); |
s9_instance->out_desired_phase(out9_desired_phase); |
|
// instantiate and connect stage 10 |
s10_instance = new cordic("stage10_in_pipe"); |
s10_instance->clk(clk); |
s10_instance->start(start); |
s10_instance->reset(reset); |
s10_instance->in_x(out9_x); |
s10_instance->in_y(out9_y); |
s10_instance->in_acc_phase(out9_acc_phase); |
s10_instance->in_opcode(out9_opcode); |
s10_instance->in_desired_phase(out9_desired_phase); |
s10_instance->stage_num(stage10); |
s10_instance->tablep(tablep_10); |
s10_instance->tableh(tableh_10); |
s10_instance->done(stage10_done); |
s10_instance->out_x(out10_x); |
s10_instance->out_y(out10_y); |
s10_instance->out_acc_phase(out10_acc_phase); |
s10_instance->out_opcode(out10_opcode); |
s10_instance->out_desired_phase(out10_desired_phase); |
|
// instantiate and connect stage 11 |
s11_instance = new cordic("stage11_in_pipe"); |
s11_instance->clk(clk); |
s11_instance->start(start); |
s11_instance->reset(reset); |
s11_instance->in_x(out10_x); |
s11_instance->in_y(out10_y); |
s11_instance->in_acc_phase(out10_acc_phase); |
s11_instance->in_opcode(out10_opcode); |
s11_instance->in_desired_phase(out10_desired_phase); |
s11_instance->stage_num(stage11); |
s11_instance->tablep(tablep_11); |
s11_instance->tableh(tableh_11); |
s11_instance->done(done); |
s11_instance->out_x(out_x); |
s11_instance->out_y(out_y); |
s11_instance->out_acc_phase(out_acc_phase); |
s11_instance->out_opcode(out_opcode); |
s11_instance->out_desired_phase(out_desired_phase); |
|
} |
|
}; // end module cordpipe |
/trunk/cordic_ip/opcode.h
0,0 → 1,39
#ifndef _OPCODE_H_ |
#define _OPCODE_H_ |
// opcode.h: header file |
/******************************************************************** |
// |
// Module: |
// A collection of opcode related decodings and settings |
// |
// Authors: Winnie Cheng<wwcheng@stanford.edu>, |
// Peter Wu<peter5@stanford.edu> |
*********************************************************************/ |
|
// specification in user program file |
#define ROT_OPNAME "rot" |
#define MAG_OPNAME "mgp" |
#define SIN_OPNAME "sin" |
#define COS_OPNAME "cos" |
#define SINH_OPNAME "sinh" |
#define COSH_OPNAME "cosh" |
#define NOP_OPNAME "nop" |
|
// decode which function unit |
#define UNIT_SEL_WIDTH 4 |
#define I_NOP (short)0 |
#define I_ROTATE (short)1 |
#define I_MAGPHASE (short)2 |
#define I_SINCOS (short)8 // selects the SIN-COS unit |
#define I_SIN (short)8 |
#define I_COS (short)9 |
#define I_SINHCOSH (short)10 // selects the SINH-COSH unit |
#define I_SINH (short)10 |
#define I_COSH (short)11 |
|
// differentiate operations within a pipeline stage |
#define TYPE_NOP 0 |
#define TYPE_NONHYPER 1 |
#define TYPE_HYPER 2 |
|
#endif // _OPCODE_H_ |
/trunk/cordic_ip/testbench.cpp
0,0 → 1,494
// 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 100 |
#define MAGPHASE_NUM_TEST 100 |
#define SINCOS_NUM_TEST 100 |
#define SINHCOSH_NUM_TEST 100 |
|
#ifdef MODULE_NAME |
#undef MODULE_NAME |
#endif |
|
#define MODULE_NAME "[testbench]" |
|
#define PROGFILE "userprog.dat" |
#define LOGFILE "testpipe.log" |
#define MAX_PROGSIZE 24 |
#define MAX_STR_LEN 128 |
|
void testbench::testbench_process() |
{ |
short i; |
double x, y, a; |
double rad, correct_x, correct_y; |
double computed_v1, computed_v2; |
int fixed1, fixed2; |
bool success, skip; |
int retval; |
char ir[MAX_STR_LEN]; |
char op[3][MAX_STR_LEN]; |
int file_opcode; |
int num_instr; |
FILE *logfile; |
|
// Opens user program file for reading |
FILE *infile = fopen(PROGFILE, "r"); |
|
if(!infile) { |
cout << MODULE_NAME << "File does not exist: " << PROGFILE << endl; |
exit(-1); |
} |
|
// Initialize output |
|
done.write(false); |
instructions_valid.write(false); |
start_monitor.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 |
|
// Testing Pipeline |
wait(); |
cout << MODULE_NAME << "Testing Pipeline Mode" << endl; |
start_monitor.write(true); |
wait(); |
|
// Translates user program |
i = 0; |
|
while(i < MAX_PROGSIZE) { |
wait(); |
|
retval = fscanf(infile, "%s", ir); |
if(retval==EOF) break; |
if(!strcmp(ir, "rot")) { |
// Rotate type functions |
printf("%s Opcode ROTATE[%s]: ", MODULE_NAME, ir); |
// get operands |
if((retval=fscanf(infile, "%s %s %s\n", op[0], op[1], op[2]))!= 3) { |
printf("Parse Error\n"); |
break; |
} else { |
printf("[%s], [%s], [%s]\n", op[0], op[1], op[2]); |
|
engine_select.write(I_ROTATE); |
operand1.write(toint(atof(op[0]))); |
operand2.write(toint(atof(op[1]))); |
operand3.write(toint(atof(op[2]))); |
instructions_valid.write(true); |
} |
} else if(!strcmp(ir, MAG_OPNAME)){ |
// Magnitude-Phase type functions |
printf("%s Opcode MAG-PHASE[%s]: ", MODULE_NAME, ir); |
// get operands |
if((retval=fscanf(infile, "%s %s\n", op[0], op[1]))!= 2) { |
printf("Parse Error\n"); |
break; |
} else { |
printf("%s, %s\n", op[0], op[1]); |
engine_select.write(I_MAGPHASE); |
operand1.write(toint(atof(op[0]))); |
operand2.write(toint(atof(op[1]))); |
instructions_valid.write(true); |
} |
} else if(!strcmp(ir, SIN_OPNAME) || !strcmp(ir, COS_OPNAME)) { |
// Trig type functions |
printf("%s Opcode SIN-COS[%s]: ", MODULE_NAME, ir); |
// get operands |
if((retval=fscanf(infile, "%s\n", op[0]))!= 1) { |
printf("Parse Error\n"); |
break; |
} else { |
printf("%s\n", op[0]); |
engine_select.write(I_SINCOS); |
operand1.write(toint(atof(op[0]))); |
instructions_valid.write(true); |
} |
} else if(!strcmp(ir, SINH_OPNAME) || !strcmp(ir, COSH_OPNAME)) { |
// Trig Hyperbolic type functions |
printf("%s Opcode SINH-COSH[%s]: ", MODULE_NAME, ir); |
// get operands |
if((retval=fscanf(infile, "%s\n", op[0]))!= 1) { |
printf("Parse Error\n"); |
break; |
} else { |
printf("%s\n", op[0]); |
engine_select.write(I_SINHCOSH); |
operand1.write(toint(atof(op[0]))); |
instructions_valid.write(true); |
} |
} else if (!strcmp(ir, NOP_OPNAME)) { |
// NOP function |
printf("%s Opcode NOP[%s]\n", MODULE_NAME, ir); |
engine_select.write(I_NOP); |
instructions_valid.write(true); |
} else { |
printf("Unknown Opcode %s\n", ir); |
engine_select.write(I_NOP); |
instructions_valid.write(false); |
break; |
} |
i++; |
} |
|
if(i == MAX_PROGSIZE) wait(); |
|
instructions_valid.write(false); |
fclose(infile); |
cout << MODULE_NAME << "Interpreted " << i << " instructions\n"; |
num_instr = i; |
|
wait_until(monitor_idle.delayed()==true); |
start_monitor.write(false); |
wait(); |
|
// Check results |
cout << MODULE_NAME << "Checking Pipeline Mode results" << endl; |
infile = fopen(PROGFILE, "r"); |
logfile = fopen(LOGFILE, "r"); |
if(!infile) { |
cout << MODULE_NAME << "Prog file cannot be opened: " << PROGFILE << endl; |
exit(-1); |
} |
if(!logfile) { |
cout << MODULE_NAME << "Log file cannot be opened: " << LOGFILE << endl; |
exit(-1); |
} |
|
i = 0; |
skip = false; |
|
while(i < MAX_PROGSIZE) { |
wait(); |
|
retval = fscanf(infile, "%s", ir); |
if(retval==EOF) break; |
if(skip==false) { |
retval = fscanf(logfile, "%d %x %x\n", &file_opcode, &fixed1, &fixed2); |
if(retval!=3) { |
cout << MODULE_NAME << "ERROR mismatch num_arg in " << LOGFILE << " found " << retval << endl; |
break; |
} |
computed_v1 = tofp((short)fixed1); |
computed_v2 = tofp((short)fixed2); |
} |
skip = false; |
if(!strcmp(ir, "rot")) { |
// Rotate type functions |
printf("%s Opcode ROTATE[%s]: ", MODULE_NAME, ir); |
// get operands |
if((retval=fscanf(infile, "%s %s %s\n", op[0], op[1], op[2]))!= 3) { |
printf("Parse Error\n"); |
break; |
} else { |
printf("[%s], [%s], [%s]\n", op[0], op[1], op[2]); |
// Check |
rad=(3.1415926*atof(op[2]))/180.0; |
correct_x=atof(op[0])*cos(rad)-atof(op[1])*sin(rad); |
correct_y=atof(op[1])*cos(rad)+atof(op[0])*sin(rad); |
|
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; |
} |
} |
} else if(!strcmp(ir, MAG_OPNAME)){ |
// Magnitude-Phase type functions |
printf("%s Opcode MAG-PHASE[%s]: ", MODULE_NAME, ir); |
// get operands |
if((retval=fscanf(infile, "%s %s\n", op[0], op[1]))!= 2) { |
printf("Parse Error\n"); |
break; |
} else { |
printf("%s, %s\n", op[0], op[1]); |
// Check |
x = atof(op[0]); |
y = atof(op[1]); |
correct_x=sqrt(x*x+y*y); |
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; |
} |
} |
} else if(!strcmp(ir, SIN_OPNAME) || !strcmp(ir, COS_OPNAME)) { |
// Trig type functions |
printf("%s Opcode SIN-COS[%s]: ", MODULE_NAME, ir); |
// get operands |
if((retval=fscanf(infile, "%s\n", op[0]))!= 1) { |
printf("Parse Error\n"); |
break; |
} else { |
printf("%s\n", op[0]); |
// Check |
rad=(3.1415926*atof(op[0]))/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; |
} |
} |
} else if(!strcmp(ir, SINH_OPNAME) || !strcmp(ir, COSH_OPNAME)) { |
// Trig Hyperbolic type functions |
printf("%s Opcode SINH-COSH[%s]: ", MODULE_NAME, ir); |
// get operands |
if((retval=fscanf(infile, "%s\n", op[0]))!= 1) { |
printf("Parse Error\n"); |
break; |
} else { |
printf("%s\n", op[0]); |
// Check |
rad=(3.1415926*atof(op[0]))/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; |
} |
} |
} else if (!strcmp(ir, NOP_OPNAME)) { |
// NOP function |
printf("%s Opcode NOP[%s]\n", MODULE_NAME, ir); |
skip = true; |
} else { |
printf("Unknown Opcode %s\n", ir); |
break; |
} |
i++; |
} |
if(i != num_instr) { |
cout << MODULE_NAME << "ERROR num of instruction mismatched " ; |
cout << i << " vs " << num_instr << endl; |
success = false; |
} else { |
cout << MODULE_NAME << "Pipeline processed " << i << " instructions" <<endl; |
} |
fclose(infile); |
fclose(logfile); |
|
cout << MODULE_NAME << "Testbench completed - "; |
if(success) { |
cout << "SUCCESS" << endl; |
} else { |
cout << "FAILED" << endl; |
} |
done.write(true); |
// end of test vectors |
} |
/trunk/cordic_ip/main.cpp
19,7 → 19,6
#include "decoder.h" |
#include "cordpipe.h" |
#include "adjust.h" |
#include "resultfifo.h" |
#include "monitor.h" |
#include "opcode.h" |
#include "table.h" |
63,14 → 62,7
sc_signal<short> pipe_acc_phase; |
sc_signal<short> pipe_desired_phase; |
sc_signal<sc_uint<UNIT_SEL_WIDTH> > pipe_opcode; |
|
// result fifo |
sc_signal<bool> fifo_read_request; |
sc_signal<bool> fifo_out_valid; |
sc_signal<sc_uint<UNIT_SEL_WIDTH> > fifo_out_opcode; |
sc_signal<short> fifo_out_result1; |
sc_signal<short> fifo_out_result2; |
|
|
// constants to parametrize pipeline module on system reset |
sc_signal<short> stage0; |
sc_signal<short> stage1; |
124,10 → 116,6
testbench1.result1(result1); |
testbench1.result2(result2); |
testbench1.monitor_idle(monitor_idle); |
testbench1.fifo_valid(fifo_out_valid); |
testbench1.fifo_opcode(fifo_out_opcode); |
testbench1.fifo_result1(fifo_out_result1); |
testbench1.fifo_result2(fifo_out_result2); |
// outputs |
testbench1.instructions_valid(instruction_valid); |
testbench1.done(powerdown); |
136,8 → 124,7
testbench1.operand1(operand1); |
testbench1.operand2(operand2); |
testbench1.operand3(operand3); |
testbench1.fifo_read_request(fifo_read_request); |
|
|
// instantiate decoder |
decoder decoder1("decoder"); |
decoder1.clk(CLOCK); |
223,27 → 210,11
adjust1.in_acc_phase(pipe_acc_phase); |
adjust1.in_opcode(pipe_opcode); |
// output |
adjust1.result_valid(compute_done); // compute_done |
adjust1.out_opcode(adjust_opcode); // adjust_opcode |
adjust1.out_result1(result1); // result1 |
adjust1.out_result2(result2); // result2 |
adjust1.result_valid(compute_done); |
adjust1.out_opcode(adjust_opcode); |
adjust1.out_result1(result1); |
adjust1.out_result2(result2); |
|
// instantiate result fifo |
resultfifo resultfifo1("resultfifo1"); |
resultfifo1.clk(CLOCK); |
resultfifo1.reset(reset); |
// inputs |
resultfifo1.read_request(fifo_read_request); |
resultfifo1.write_request(compute_done); |
resultfifo1.in_opcode(adjust_opcode); |
resultfifo1.in_result1(result1); |
resultfifo1.in_result2(result2); |
// outputs |
resultfifo1.out_valid(fifo_out_valid); |
resultfifo1.out_opcode(fifo_out_opcode); |
resultfifo1.out_result1(fifo_out_result1); |
resultfifo1.out_result2(fifo_out_result2); |
|
// instantiate monitor unit |
monitor monitor1("monitor1"); |
monitor1.clk(CLOCK); |
250,10 → 221,10
monitor1.reset(reset); |
// inputs |
monitor1.start(start_monitor); |
monitor1.in_valid(compute_done); // compute_done |
monitor1.in_opcode(adjust_opcode); // adjust_opcode |
monitor1.in_result1(result1); // result1 |
monitor1.in_result2(result2); // result2 |
monitor1.in_valid(compute_done); |
monitor1.in_opcode(adjust_opcode); |
monitor1.in_result1(result1); |
monitor1.in_result2(result2); |
monitor1.idle(monitor_idle); |
|
// create trace file |
/trunk/cordic_ip/testbench.h
29,12 → 29,6
sc_in<short> result2; |
sc_in<bool> monitor_idle; |
|
// Input ports from result fifo |
sc_in<bool> fifo_valid; |
sc_in<sc_uint<UNIT_SEL_WIDTH> > fifo_opcode; |
sc_in<short> fifo_result1; |
sc_in<short> fifo_result2; |
|
// Output ports Declaration |
sc_out<bool> instructions_valid; |
sc_out<bool> done; |
46,12 → 40,8
sc_out<short> operand2; |
sc_out<short> operand3; |
|
// Output to result fifo |
sc_out<bool> fifo_read_request; |
|
// Declare implementation functions |
void testbench_process(); |
void readfifo_process(); |
|
// Constructor |
SC_CTOR(testbench) |
58,7 → 48,6
{ |
// Register processes and define active clock edge |
SC_CTHREAD(testbench_process, clk.pos()); |
SC_CTHREAD(readfifo_process, clk.pos()); |
|
// Watching for global reset |
watching(reset.delayed()==true); |
/trunk/cordic_ip/adjust.cpp
0,0 → 1,134
// adjust.cpp: source file |
/******************************************************************** |
// |
// Module: |
// Pipeline Output Adjusting Unit |
// |
// Implementation: |
// This module performs some of the shifts there are needed to |
// obtain final results. |
// |
// |
// Authors: Winnie Cheng <wwcheng@stanford.edu>, |
// Peter Wu <peter5@stanford.edu> |
// |
*********************************************************************/ |
|
#include "adjust.h" |
#include "opcode.h" |
|
#ifdef MODULE_NAME |
#undef MODULE_NAME |
#endif |
|
#define MODULE_NAME "adjust" |
|
#define DEBUG 1 |
#if DEBUG |
#define dprintf printf |
#else |
#define dprintf |
#endif |
|
void adjust::adjust_process() |
{ |
sc_uint<UNIT_SEL_WIDTH> opcode; |
short x, y, acc_phase; |
short result1, result2; |
|
// On Reset, initialize output |
result_valid.write(true); |
out_opcode.write(I_NOP); |
out_result1.write(0); |
out_result2.write(0); |
wait(); |
|
while(1) { |
|
wait(); |
|
// propagate through |
opcode = in_opcode.read(); |
out_opcode.write(opcode); |
|
if(in_valid.read()==true){ |
// Register input |
x = in_x.read(); |
y = in_y.read(); |
acc_phase = in_acc_phase.read(); |
|
// Adjust according to opcode |
if(opcode == I_ROTATE) { |
|
// Rotate Instruction Format |
// operand1 : orgX |
// operand2 : orgY |
// operand3 : angle |
// returns |
// result1 : rotated x-coordinate |
// result2 : rotated y-coordinate |
|
// Reduce vector size by multiplier |
// (1/2+1/8-1/64-1/512) |
|
// adjust |
result1=(x>>1)+(x>>3)-(x>>6)-(x>>9); |
result2=(y>>1)+(y>>3)-(y>>6)-(y>>9); |
|
// output results |
out_result1.write(result1); |
out_result2.write(result2); |
result_valid.write(true); |
|
dprintf("[%s] Adjust ROTATE\n", MODULE_NAME); |
|
} else if (opcode == I_MAGPHASE) { |
|
// Magphase Instruction Format |
// operand1 : X |
// operand2 : Y |
// returns |
// result1 : magnitude |
// result2 : phase |
|
// adjust |
result1 = (x>>1)+(x>>3)-(x>>6)-(x>>9); |
result2 = -acc_phase; |
|
// output results |
out_result1.write(result1); |
out_result2.write(result2); |
result_valid.write(true); |
|
dprintf("[%s] Adjust MAG-PHASE\n", MODULE_NAME); |
|
} else if (opcode == I_SINCOS || opcode == I_SINHCOSH) { |
|
// SinCos/SinhCosh Instruction Format |
// operand1 : phase |
// return |
// result1 : sin/sinh(phase) |
// result2 : cos/cosh(phase) |
|
// no adjustment needed |
|
// output results |
out_result1.write(y); // sin/sinh result |
out_result2.write(x); // cos/cosh result |
result_valid.write(true); |
|
dprintf("[%s] Adjust SINCOS or SINHCOSH\n", MODULE_NAME); |
|
} else { |
// filter out NOP results |
result_valid.write(false); |
|
dprintf("[%s] Adjust ignored NOP\n", MODULE_NAME); |
} |
|
} else { |
result_valid.write(false); |
dprintf("[%s] Nothing to adjust\n", MODULE_NAME); |
} |
} // forever loop |
} |
/trunk/cordic_ip/names.fof
0,0 → 1,6
cordic.cpp |
decoder.cpp |
adjust.cpp |
monitor.cpp |
testbench.cpp |
main.cpp |
/trunk/cordic_ip/table.h
0,0 → 1,42
#ifndef _TABLE_H_ |
#define _TABLE_H_ |
// table.h: header file |
/******************************************************************** |
// |
// Module: |
// A collection of lookup tables used in CORDIC computation |
// |
// |
// Authors: Winnie Cheng<wwcheng@stanford.edu>, |
// Peter Wu<peter5@stanford.edu> |
*********************************************************************/ |
|
// table for non-hyperbolic functions |
#define TABLEP_0 0x1680 |
#define TABLEP_1 0x0d48 |
#define TABLEP_2 0x0705 |
#define TABLEP_3 0x0390 |
#define TABLEP_4 0x01ca |
#define TABLEP_5 0x00e5 |
#define TABLEP_6 0x0073 |
#define TABLEP_7 0x0039 |
#define TABLEP_8 0x001d |
#define TABLEP_9 0x000e |
#define TABLEP_10 0x0007 |
#define TABLEP_11 0x0004 |
|
// table for hyperbolic functions |
#define TABLEH_0 0x0fbd |
#define TABLEH_1 0x0751 |
#define TABLEH_2 0x039a |
#define TABLEH_3 0x01cb |
#define TABLEH_4 0x00e5 |
#define TABLEH_5 0x0073 |
#define TABLEH_6 0x0039 |
#define TABLEH_7 0x001d |
#define TABLEH_8 0x000e |
#define TABLEH_9 0x0007 |
#define TABLEH_10 0x0004 |
#define TABLEH_11 0x0002 |
|
#endif // _TABLE_H_ |