对于一个大学项目,我必须参加一个小组,设计一个CORDIC正弦波发生器。我的小组将CORDIC分为多个部分,以使我们能够同时工作。现在,我已经将模块集成在一起(以计算单级的纯正弦和余弦值,例如旋转60度),而我的输出值不再是我所期望的。我相信我可能误解了有关CORDIC算法的一些基础知识,因此该程序带来了价值。这是我解决这个问题的最后努力。
我已经将到目前为止所拥有的代码与在ModelSim中用于测试的do文件一起附加了。
用于预先计算幅度计算器的下一个值的方向计算器
/*DirectionCalculator
*Author: -------------------
*Description:
A calculator that finds out if the next angle is added
or subtracted based on if the current angle.
If greater subtract if smaller add.
*Version: V 2.2
*Log:
-Created input output
-Conditionals for next tirection
-Moved the lookup table from controller to direction calculator
to reduce amout of data handled by controller
-Removed signed portion of Angle_Table to increase accuracy and the signed
part will never be used as the angle will alwasy be between 0 and 90
-Shifted start value to 45 degrees as the calcualtor needs to be a step ahead
*Input Description
-
*/
module DirectionCalculator(Start, Reset, TAngle, Done, N_Dir, Zout);
input Start, Reset;
input[15:0] TAngle;
output logic Done, N_Dir;
output logic [15:0] Zout;
//Registers
reg Res_flag = 0;
reg [3:0] n;
reg [15:0] Z, Angle_Table[0:14];
//lookup table
//Bits in table are decimal representative
//Each bit represents a value of pi so that 10... is pie 01... is 1/2 pi in radians
assign Angle_Table[0] = 16'b0100000000000000; //fist angle of 45 = arctan(2^-0)
assign Angle_Table[1] = 16'b0010010111001000; //26.565 = arctan(2^-1)
assign Angle_Table[2] = 16'b0001001111110110; //14.036 = arctan(2^-2)
assign Angle_Table[3] = 16'b0000101000100010;
assign Angle_Table[4] = 16'b0000010100010110;
assign Angle_Table[5] = 16'b0000001010001100;
assign Angle_Table[6] = 16'b0000000101000110;
assign Angle_Table[7] = 16'b0000000010100011;
assign Angle_Table[8] = 16'b0000000001010001;
assign Angle_Table[9] = 16'b0000000000101001;
assign Angle_Table[10] = 16'b0000000000010100;
assign Angle_Table[11] = 16'b0000000000001010;
assign Angle_Table[12] = 16'b0000000000000101;
assign Angle_Table[13] = 16'b0000000000000011;
assign Angle_Table[14] = 16'b0000000000000001;
always @(posedge Start or posedge Reset)
begin
//Reset to Start values
if(Reset && !Res_flag) begin
Z = Angle_Table[0]; //Angle started at is 45 degrees
n = 1;
Res_flag = 0;//flag reset as complete
Done = 0;
end else if (Reset) //
Res_flag = 0;
//Check if the controller is asking to operate
if (Start) begin
if(n == 15) begin
Zout <= Z;
end else if(n < 15) begin
Done = 0;
//Calculate Direction
if(Z < TAngle) begin //Angle less than desired
Z <= Z + Angle_Table[n]; //Accumulate Total Angle
N_Dir <= 1'b1; //Set Direction to Rotate anticlockwise
end else if(Z > TAngle)begin //Angle Grater than desired
Z <= Z - Angle_Table[n]; //Accumulate Total Angle
N_Dir <= 1'b0; //Set direction to rotate Clockwise
end
n++; //Itterate next step
#5 Done = 1; //Tell the controller the task is complete
end
end
end
endmodule
用于计算X和Y值(分别为Cos / Sin)的振幅计算
/*Amplitude_Calculator.sv
*Author: ------------
*Description: Used to calculate the amplitude of the Wave at a certain angle
through the use of shifting.
*
*/
// This part just design the calculation about sin and cos waveform generator.
// the calculation just like:
// Xi+1 = Xi-[Yi*di*2^(-1)]
// Yi+1 = Yi+[Xi*di*2^(-1)]
module AmplitudeCalculator(Dir, Start, Xin, Yin, AngleShift, Xout, Yout, Done);
input Dir, Start;// N_Dir means "di"
input signed [15:0] Xin, Yin;// there are 16 bits input,
// Xin is Xi, Yin is Yi and
input signed [4:0] AngleShift; // the AngleShift is 2^(-1)
output logic Done; // that just means the calculation is finished
output logic signed [15:0] Xout, Yout;// there are 16 bits output,
// Xout is Xi+1
// Yout is Yi+1
always @(posedge Start)// if the Start value is 1, run the calculation.
begin
Done = 1'd0; //set the done value to 0 to prevent premature finish
#5
Xtemp <= Xin >>> AngleShift;// X_temp is the value of Xin right shift,
// and X_temp will change because of AngleShift
Ytemp <= Yin >>> AngleShift;// Y_temp is the value of Xin right shift,
// and X_temp will change because of AngleShift
#5
//Multiplexers Selecting corre
Xout <= Dir ? Xin - Ytemp : Xin + Ytemp; //Multiplexes output for Xout selecting addition or subtraction
Yout <= Dir ? Yin + Xtemp : Yin - Xtemp; //Multiplexex output for Yout selecting addition or subtraction
#5
Done = 1'b1; //inform the controller that the process is finished
end
endmodule
在计算器之间迭代并传递值以防止模块重复的控制器
/*
Controller
Author: -------------
Description: A module that acts as the controller for the other modules.
It iterates values for the next sequence.
Version: 1.0
Inputs:
Yin
Xin
CLK = Clock signal
Yin_S = Yin Starting Value
Xin_S = Xin Starting Value
N_Dir = Next Direction
Done = This is an Input showing when both modules are done
Outputs:
Yout_F = Final Yout Output Value
Xout_F = Final Xout Output Value
AS = Angle Shift; amount of times we have to shift the angle
C_Dir = Current Direction
Yout
Xout
Start
*/
module Controller(Yin, Xin, CLK, Yin_S, Xin_S, Done, Yout_F, Xout_F,
Yout, Xout, AS, C_Dir, N_Dir, Start, Reset);
input Done, CLK, N_Dir;
input signed [15:0] Yin_S, Xin_S, Yin, Xin;
output logic Start, C_Dir, Reset;
output logic signed [4:0] AS;
output logic signed [15:0] Yout, Xout, Yout_F, Xout_F;
reg signed [15:0] Yout_F_reg = 0;
reg signed [15:0] Xout_F_reg = 0;
reg signed [4:0] n = 0;
reg CLK_flag = 0;
enum{S0,S1,S2} cstate, nstate;
//Assign Outputs to X Y registers
assign Xout_F = Xout_F_reg;
assign Yout_F = Yout_F_reg;
//next state Block
always_comb
begin
case (cstate)
S0: nstate = S1; //state 0 always goes to state 1
S1: if(n >= 13) nstate = S2; else nstate = S1; // repeat state 14 times to find final value of ordic rotation
S2: nstate = S2; //end state output is set and program is stalled waiting for reset
endcase
end
//Current state action Block
always @(*) //occures when any input values change eg. cstate
begin
case (cstate)
//Reset values state
S0: begin
#5 Start = 0;
Reset = 1;
n = 0;
#5 Reset = 0;
Xout <= Xin_S;
Yout <= Yin_S;
AS <= n;
C_Dir = 1;
#5 Start = 1;
end
//Core itteration State
S1: begin
#5 Start = 0;
//itterate step
n++;
//pass calculated values over to AC
Xout = Xin;
Yout = Yin;
C_Dir = N_Dir;
AS = n; //set shift angle
#5 Start = 1;
end
//Endstate Outputs X Y values
S2: begin
#5 Start = 0;
//output
Xout_F_reg = Xin;
Yout_F_reg = Yin;
end
endcase
end
//Incremnet Block incremnets to the next state upon completion of calculations
//Set cstate to S0 when clock is input reseting the State machine
always @(posedge Done or posedge CLK)
begin
//reset on positive edge of clock (do not know how to do this any other way)
if (CLK && !CLK_flag) begin //reset state machine
cstate = S0;
CLK_flag = 1; //flag that the resest has occured
end else
if(!CLK) begin
CLK_flag = 0; //set the flag to 0 whe clock is 0
end
if(Done)//continue to next state
cstate = nstate; //change current state to next state when the calculater have finished
end
endmodule
三个模块的组合
/*CORDIC_Core.sv
*Author: -------------
*Description: Combination of all the logic elements of the main cordic part
*
*
*
*/
module CORDIC_Core(Clk, Yin_S, Xin_S, TAngle, Yout_F, Xout_F, Zout);
input Clk;
input [15:0] Yin_S, Xin_S, TAngle;
output [15:0] Yout_F, Xout_F, Zout;
wire [15:0] Y[1:0], X[1:0];
wire [4:0] AS;
wire D0, D1, C_Dir, N_Dir, Start, Reset;
//And for Done values
assign Done = D0 && D1;
//isntaciate Blocks and connect with wires
Controller C0 (Y[0], X[0], Clk, Yin_S, Xin_S, Done, Yout_F, Xout_F,
Y[1], X[1], AS, C_Dir, N_Dir, Start, Reset);
DirectionCalculator DC0 (Start, Reset, TAngle, D1, N_Dir, Zout);
AmplitudeCalculator AC0 (C_Dir, Start, X[1], Y[1], AS, X[0], Y[0], D0);
endmodule
做测试文件
#Test_CORDIC_Core.do
#Setup
force Clk 0 1,0 500 -r 1000
#Xin set to 0.607 to test without amplifier (pre multipling by 0.0607)
force Xin_S 16'b0001001101101101
force Yin_S 16'b0000000000000000
#Test1 for angle shift of 60 degrees
force TAngle 16'b0010101010101011
run 950
#Test2 for angle shift of 20 degrees
force TAngle 16'b0000111000111000
#run 1050
非常感谢您浏览我的作品
这是我运行x和y最终值的代码时得到的测试结果 The results where the binary values are 16 bit with a decimal point at 000.0000000000000 portion os Modelsim Waveform
我知道程序中存在多个错误,但是我想首先解决此价值问题。我正在修复其他错误