NCO timing issue, VERILOG fpga

Status
Not open for further replies.

JHEnt

Newbie level 4
Joined
May 23, 2014
Messages
7
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
80
I am trying to implement a numerically controlled oscillator on a Cyclone 4 fpga. The basic version I found as an example online. I have a 50MHz main clock. Using the equasion freq = controlword * 2^numberbits / clockfreq as the basis. Then reading bits 29-26 as the phasekey of the 30 bit accumulator.
The phasekey then has 16 possible values per cycle, or so it should. It doesn't seem to be outputting correctly.
Can someone help me to understand what is or is not happening?

I am sending the control word as " 30'd21861383 ". By the calculation this should produce 1018MHz output.
Code:
module NCO_chipRate(sysclk, reset, cntl_word, chip_enable, nextChip, nco_val, get_nco_val);

	input sysclk, reset;
	input [31:0] cntl_word;
	input get_nco_val;
	
	output reg [2:0]chip_enable; //[2]late, [1]prompt,[0]early
	output reg [31:0]nco_val;
	output reg nextChip;
	
	reg   [29:0] accum_reg;
   reg   [20:0] cycle_count_reg;
   wire  [3:0] phase_key;
   wire  [31:0] accum_sum;
   wire	accum_carry;
   wire  [31:0] combined_carr_value;
	
	// 30 bit phase accumulator
   always @ (posedge sysclk)
	begin
		if (reset) accum_reg <= 0;
		else accum_reg <= accum_sum[29:0];
	end

	// cycle counter and value latching
   always @ (posedge sysclk)
   begin
		if (reset) cycle_count_reg = 0;
		else if (get_nco_val)
		begin
			nco_val = combined_carr_value; // latch in carrier value, then...
			cycle_count_reg = 0; // reset counter
		end
		else if (accum_carry) 
		begin
			cycle_count_reg = cycle_count_reg + 1'b1;
		end
	end
	
	assign accum_sum = accum_reg + cntl_word;
	assign accum_carry = accum_sum[30];
	assign phase_key = accum_sum[29:26];
	assign combined_carr_value[9:0] = accum_reg[29:20];
	assign combined_carr_value[31:10] = cycle_count_reg;
   
	always @ (posedge sysclk)
	begin
		if(phase_key == 4'd8)
		begin
			chip_enable[0] <= 0;
			chip_enable[1] <= 1;
			chip_enable[2] <= 0;
		end
		else if(phase_key == 4'd4)
		begin
			chip_enable[0] <= 1;
			chip_enable[1] <= 0;
			chip_enable[2] <= 0;
		end
		else if(phase_key == 4'd12)
		begin
			chip_enable[0] <= 0;
			chip_enable[1] <= 0;
			chip_enable[2] <= 1;
		end
		else
		begin
			chip_enable[0] <= 0;
			chip_enable[1] <= 0;
			chip_enable[2] <= 0;
		end
		
		if(phase_key == 4'd0) nextChip <= 1; //signal to advance chip coder
		else nextChip <= 0;
	end

endmodule
 

In the first cycle_count_reg always block you are using blocking assignments in a sequential always block. That's incorrectly coded.

I would also move the nco_val out of that if as it doesn't get assigned in the reset or accum_carry branch. use something like nco_val <= get_nco_val ? combined_carr_value : nco_val; outside the if (reset)....else if...end stuff.

I'm also not sure how your "calculation" is supposed to end up as 1018 MHz (over 1GHz). The your equation gives: freq = 21861383*2^30 /50000000 = 469.5 MHz, which makes your equation suspect as NCOs produce frequencies less than the clock driving them.

Maybe you should review the wiki article on NCOs. https://en.wikipedia.org/wiki/Numerically_controlled_oscillator

Regards

- - - Updated - - -

Okay if you use the correct equation:

freq = 21861383/(2^30)*50000000 = 1.018 MHz, which does make more sense.

You still need to fix the blocking assignments and you should move that nco_val out of the if statement.

Graph the 4-bit values they should produce some sort of saw tooth waveform. If they don't then you've got some other issue in your code, which I haven't spotted yet.

Regards
 

Sorry missed the decimal point. Should be 1.018MHz from a 50MHz clock.
I also misstyped the formula, it should be freq = control * clock / 2^N. What I put partially in the post was the notes I used to figure the control word, control = freq * 2^N / clock.
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…