Skip to content

Instantly share code, notes, and snippets.

@inkwisit
Last active June 20, 2017 15:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save inkwisit/0a367f524a0ede2107aa7ff6a0b83cfe to your computer and use it in GitHub Desktop.
Save inkwisit/0a367f524a0ede2107aa7ff6a0b83cfe to your computer and use it in GitHub Desktop.
Cordic Algorithm for Quadrature Carrier Synthesis (Non-pipelined)
`timescale 1ns / 1ps
module clockDivider #(parameter DIV_LENGTH = 8)(
input mainClock,
output clock
);
initial
begin
counter <= 8'b0;
end
assign clock = counter[DIV_LENGTH-1];
reg [DIV_LENGTH-1:0]counter;
always@(posedge mainClock)
begin
counter <= counter + 1'b1;
end
endmodule
NET "mainClock" LOC = V10 | IOSTANDARD = LVCMOS33 | PERIOD = 100MHz ;
NET "cosine[9]" LOC = T3 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ;
NET "cosine[8]" LOC = R3 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ;
NET "cosine[7]" LOC = V5 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ;
NET "cosine[6]" LOC = U5 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ;
NET "cosine[5]" LOC = V4 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ;
NET "cosine[4]" LOC = T4 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ;
NET "cosine[3]" LOC = V7 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ;
NET "cosine[2]" LOC = U7 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ;
NET "cosine[1]" LOC = V9 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ;
NET "cosine[0]" LOC = T9 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ;
NET "strobe" LOC = T5 | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ;
`timescale 1ns / 1ps
module cordic3 #(parameter ANGLE_RESOLUTION = 10, OUTPUT_RESOLUTION = 10, LUT_SIZE = 3, DC_OFFSET = 10'd512)(
input angleLatch,
input mainClock,
input [ANGLE_RESOLUTION-1:0]angleInput, //from 2's compliment representation e.g., 230 = (230/360)*1024 = 1010001110 , in other ways it represent angle from -pi to pi in signed 2's compliment form
output reg [OUTPUT_RESOLUTION-1:0]cosine,
output reg [OUTPUT_RESOLUTION-1:0]sine,
output strobe
);
reg [ANGLE_RESOLUTION-1:0]angleAccumulator;
reg [LUT_SIZE-1:0]lookupTableIndex;
reg [OUTPUT_RESOLUTION-1:0]xNew; //10-bit number, MSB representing sign-bit //signed 2's compliment form
reg [OUTPUT_RESOLUTION-1:0]yNew; //10-bit number, MSB representing sign-bit //signed 2's compliment form
reg [ANGLE_RESOLUTION-1:0]angleInputReg;
wire [ANGLE_RESOLUTION-1:0]comparator;
wire [OUTPUT_RESOLUTION-1:0]yShifted; //signed 2's compliment
wire [OUTPUT_RESOLUTION-1:0]xShifted; //signed 2's compliment
wire [ANGLE_RESOLUTION-1:0]lookupTable[0:7]; //minimum angle value is 0.4476 at 8th place //ANGLE-3 for 1'st quadrant only
wire [ANGLE_RESOLUTION-1:0]rotationDirection;
assign yShifted = yNew >>> lookupTableIndex; //arithmetic shift right
assign xShifted = xNew >>> lookupTableIndex; //arithmetic shift right
assign strobe = (lookupTableIndex == 3'b000);
//assign rotationDirection = (angleAccumulator >= angleInputReg);
assign rotationDirection = angleInputReg - angleAccumulator;
always@(posedge mainClock)
begin
if(angleLatch == 1'b0)
begin
case(angleInput[9:8])
2'b00:
begin
angleInputReg <= angleInput;
end
2'b11:
begin
angleInputReg <= -angleInput; // in case angle is 270(deg) = 10'b1100000000 then -angle = 0100000000
end
2'b01:
begin
angleInputReg <= 10'b1000000000 - angleInput; //180 - angleInput
end
2'b10:
begin
angleInputReg <= 10'b1000000000 + angleInput; //180 + angleInput
end
endcase
xNew <= 10'b01_0011_0110; //511 * 0.6073 = 310
yNew <= 10'b00_0000_0000;
lookupTableIndex <= 3'b000;
angleAccumulator <= 10'b00_0000_0000;
end
else
begin
xNew <= rotationDirection[ANGLE_RESOLUTION-1] ? (xNew + yShifted):(xNew - yShifted);
yNew <= rotationDirection[ANGLE_RESOLUTION-1] ? (yNew - xShifted):(yNew + xShifted);
angleAccumulator <= rotationDirection[ANGLE_RESOLUTION-1] ? (angleAccumulator - lookupTable[lookupTableIndex]):(angleAccumulator + lookupTable[lookupTableIndex]);
lookupTableIndex <= lookupTableIndex + 3'b1;
//$write(angleAccumulator);
end
end
always@(posedge mainClock)
begin
if(lookupTableIndex == 3'b111)
begin
case(angleInput[9:8]) //selecting the sign of functions using ASTC rule and adding an offset for +3.3V R2R DAC
2'b00:
begin
cosine <= xNew + DC_OFFSET;
sine <= yNew + DC_OFFSET;
end
2'b11:
begin
cosine <= xNew + DC_OFFSET;
sine <= -yNew + DC_OFFSET;
end
2'b01:
begin
cosine <= -xNew + DC_OFFSET;
sine <= yNew + DC_OFFSET;
end
2'b10:
begin
cosine <= -xNew + DC_OFFSET;
sine <= -yNew + DC_OFFSET;
end
endcase
end
end
//lookupTable for the angle //bin //decimal(deg) //exact(deg)
assign lookupTable[0] = 10'b0010000000; //128 //45.0000 //45.0000
assign lookupTable[1] = 10'b0001001011; //75 //26.3672 //26.5651
assign lookupTable[2] = 10'b0000100111; //39 //13.7109 //14.0362
assign lookupTable[3] = 10'b0000010100; //20 //7.0313 //7.1250
assign lookupTable[4] = 10'b0000001010; //10 //3.5156 //3.5763
assign lookupTable[5] = 10'b0000000101; //5 //1.7578 //1.7899
assign lookupTable[6] = 10'b0000000010; //2 //0.7031 //0.8952
assign lookupTable[7] = 10'b0000000001; //1 //0.3516 //0.4476
endmodule
`timescale 1ns / 1ps
module DDS(
input mainClock,
output [9:0]cosine,
output [9:0]sine,
output reg [2:0]stateMachineCounter,
output reg angleLatch,
output strobe
);
reg [9:0]angleCounter;
cordic3 c0(.mainClock(clock),.angleInput(angleCounter),.angleLatch(angleLatch),.cosine(cosine),.sine(sine),.strobe(strobe));
clockDivider c1(.mainClock(mainClock),.clock(clock));
initial
begin
angleLatch <= 1'b0;
angleCounter <= 10'b0;
stateMachineCounter <= 3'b000;
end
always@(posedge clock) // (mainClock / 256)
begin
stateMachineCounter <= stateMachineCounter + 1'b1;
casez(stateMachineCounter)
3'b000:
begin
angleLatch <= 1'b0; // (clock / 8)
angleCounter <= angleCounter + 2'b11;
end
3'b1??,3'b01?,3'b001:
begin
angleLatch <= 1'b1;
end
endcase
end
endmodule
`timescale 1ns / 1ps
module test_DDS;
// Inputs
reg mainClock;
// Outputs
wire [9:0] cosine;
wire [9:0] sine;
wire strobe;
wire [2:0]stateMachineCounter;
wire angleLatch;
// Instantiate the Unit Under Test (UUT)
DDS uut (
.mainClock(mainClock),
.cosine(cosine),
.sine(sine),
.strobe(strobe),
.stateMachineCounter(stateMachineCounter),
.angleLatch(angleLatch)
);
initial begin
// Initialize Inputs
mainClock = 0;
// Wait 100 ns for global reset to finish
// Add stimulus here
end
always
begin
#5 mainClock = ~mainClock;
end
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment