How to divide a 24MHz clock to get 1kHz (in Verilog)

  • Thread starter Thread starter EugP
  • Start date Start date
  • Tags Tags
    Clock
Click For Summary
SUMMARY

The forum discussion focuses on dividing a 24MHz clock signal to achieve a 1kHz output using Verilog on the Altera Cyclone II FPGA Development Board. Users discuss implementing a counter-based solution, specifically utilizing a 15-bit counter to count to 24000, which corresponds to the desired frequency division. The conversation highlights the need for proper coding practices in Verilog, particularly in the context of the frequency divider module. Participants share code snippets and troubleshooting tips to help resolve issues with signal output and counter functionality.

PREREQUISITES
  • Understanding of Verilog HDL syntax and structure
  • Familiarity with FPGA architecture, specifically Altera Cyclone II
  • Knowledge of clock signal manipulation and frequency division techniques
  • Experience with digital counters and state machines in hardware design
NEXT STEPS
  • Study Verilog HDL through resources like the Wikipedia page on Verilog
  • Learn about FPGA design methodologies and best practices
  • Explore the implementation of programmable chips like the 8254 for frequency division
  • Investigate debugging techniques for Verilog simulations to resolve signal issues
USEFUL FOR

FPGA developers, hardware engineers, and students learning digital design who are interested in frequency division and Verilog programming.

EugP
Messages
104
Reaction score
0
Hey guys,

I'm using the Altera Cyclone II FPGA Development Board, with the goal of controlling a relay. I need to divide 24MHz to get 1kHz, but I don't know how to write the code for it. I know one way to divide it, would be to have a 10bit counter, which will allow me to divide it by 1k, then all that's left is to divide it by 24, which can just be another counter that counts to 23. Again, though, I don't know what the code would look like. I looked online but for some reason I couldn't find any help.

Could anyone point me in the right direction? I don't want any code, just an explanation (if possbile...)

Thanks in advance.
 
Engineering news on Phys.org
Am I missing something here? All you need is a counter to count your 24 MHz pulses and a bit of code to read that counter; when it gets to 12,000 it toggles an output pin (or whatever it is you need done) then resets the counter back to zero for the next half-cycle.
 
There's a wonderful programmable chip called the 8254 which can be instructed to do exactly what you're asking for. You can see its spec sheet at http://jwc.seu.edu.cn/jpkc/declare/08wjjk/louyuwu/jbsc/8254.pdf .

You would want to set a counter up in Mode 3: Square Wave Generator, and feed your 24 MHz signal into the clock input. Program the chip to count to 24000, and the output will be a square wave with frequency of 1 kHz.

I have worked with this chip to provide a timebase for a data acquisition system, so if you have further questions feel free to ask.
 
Last edited by a moderator:
It sounds like he wants to do it in the FPGA, not in a uC or a separate 8254 chip.

EugP -- what learning resources do you have for Verilog? The wikipedia.org page is a reasonable place to start:

http://en.wikipedia.org/wiki/Verilog

.
 
Thanks everyone for the replies.

negitron - it makes sense to me, but I don't know how to implement it

Fenn - I'm trying to use the FPGA on the development board, but thank you anyway, I might use that for some other project.

berkeman - I've looked at a bunch of Verilog tutorials, but I can't seem to find a good explanation. I might be able to find the exact code I need, but I want to understand how it works so then I will be able to divide any frequency. I found the code I used to to divide 50MHz to get 38k, by having a counter count till 1302. That makes sense because 50M/1302 = 38kHz. So by following that logic I tried setting the counter to 24k (24M/24k = 1kHz), but that didn't work for some reason
 
Can you post the code for the 1302 counter/divider? I use HDL mostly, but there are several Verilog guys here that I can ask about this if we can't figure it out quickly.
 
Yup. Here is the code I wrote last summer:

Code:
module freq_divider(
	clk,				//Clock 50 MHz
	reset_n,			//Active low reset
	divided_frequency,	//Divided frequency
	new_freq,
	current_q			//Current value
);

input clk;
input reset_n;

output divided_frequency;
output [11:0] current_q;
output new_freq;

reg divided_frequency;
reg divided_frequency_next;
reg [11:0] current_q;
reg [11:0] next_d;
reg new_freq;

//Flip Flops
always @(posedge clk or negedge reset_n)
begin
	if (!reset_n)
		begin
			divided_frequency <= 1'b0;
			current_q <= 12'b000000000000;
		end

	else
		begin
			divided_frequency <= divided_frequency_next;
			current_q <= next_d;
		end
end

//Parallel Counter Logic
always @(current_q or divided_frequency)
begin
	if (current_q == 1302)
		begin
			next_d <= 12'b0000_0000_0000;
			divided_frequency_next <= 1'b1;
		end

	 else
		begin
			divided_frequency_next <= 1'b0;
			next_d <= current_q + 1;
		end

end

always @(posedge divided_frequency)
begin
	new_freq <= !new_freq;
end

endmodule
 
And how did you modify it to try to get the divide-by-24K?
 
My clock input is now 24MHz, and the current_q == 1302, I have counter == 24000.
 
  • #10
EugP said:
My clock input is now 24MHz, and the current_q == 1302, I have counter == 24000.

And 12 bits can count how high...?
 
  • #11
Oh no no I changed the counter size as well (naturally) to 15 bits.
 
  • #12
Ah, okay. Just checking.

So what doesn't work? Does it not compile? Or you just do not get the output signal you expect?
 
  • #13
Well the module "freq_divider" is an instance in my top level file. Maybe I defined it wrong or something, because in my simulations, the signals don't do anything. Here is the new frequency divider and top level modules (I tried cleaning up the top level as much as possible, because most of the code has nothing to do with this implementation):

Top Level
Code:
module project_top
	(
		////////////////////	Clock Inputs	 	////////////////////	 
		CLOCK_24,						//	24 MHz
		CLOCK_27,						//	27 MHz
		CLOCK_50,						//	50 MHz
		EXT_CLOCK,						//	External Clock

		////////////////////	Push Buttons		////////////////////
		KEY,							//	Pushbutton[3:0]

		////////////////////	GPIO	////////////////////////////
		GPIO_0							//	GPIO Connection 0
		GPIO_1							//	GPIO Connection 1
						
	);

////////////////////////	Clock Input	 	////////////////////////
input	[1:0]	CLOCK_24;				//	24 MHz
input	[1:0]	CLOCK_27;				//	27 MHz
input			CLOCK_50;				//	50 MHz
input			EXT_CLOCK;				//	External Clock


////////////////////////	Push Button		////////////////////////
input	[3:0]	KEY;					//	Pushbutton[3:0]


////////////////////////	GPIO	////////////////////////////////
//input	[35:0]	GPIO_0;					//	GPIO Connection 0
output	[35:0]	GPIO_0;					//	GPIO Connection 0
//inout	[35:0]	GPIO_1;					//	GPIO Connection 1


wire	divided_frequency;
wire	new_freq;
wire	boost;
wire	[7:0]	relay_on, relay_off;
wire	[4:0]	counter;
wire	[2:0]	sm_state;
wire	[14:0]	counter1;

assign GPIO_0[5] = new_freq;
assign GPIO_0[6] = divided_frequency;
assign GPIO_0[7] = boost;
assign GPIO_0[8] = relay_on[0];
assign GPIO_0[9] = relay_on[1];
assign GPIO_0[10] = relay_on[2];
assign GPIO_0[11] = relay_on[3];
assign GPIO_0[12] = relay_on[4];
assign GPIO_0[13] = relay_on[5];
assign GPIO_0[14] = relay_on[6];
assign GPIO_0[15] = relay_on[7];
assign GPIO_0[16] = relay_off[0];
assign GPIO_0[17] = relay_off[1];
assign GPIO_0[18] = relay_off[2];
assign GPIO_0[19] = relay_off[3];
assign GPIO_0[20] = relay_off[4];
assign GPIO_0[21] = relay_off[5];
assign GPIO_0[22] = relay_off[6];
assign GPIO_0[23] = relay_off[7];
assign GPIO_0[24] = counter[0];
assign GPIO_0[25] = counter[1];
assign GPIO_0[26] = counter[2];
assign GPIO_0[27] = counter[3];
assign GPIO_0[28] = counter[4];
assign GPIO_0[29] = sm_state[0];
assign GPIO_0[30] = sm_state[1];
assign GPIO_0[31] = sm_state[2];

freq_divider divider(
						.clk(EXT_CLOCK),
						.rst_n(KEY[0]),
						.new_freq(new_freq),
						.divided_frequency(divided_frequency),
						.counter(counter1)
);


project project(
					.clk(EXT_CLOCK),
					.rst_n(KEY[0]),
					.btn_on_n(KEY[3]),
					.btn_off_n(KEY[2]),
					.boost(boost),
					.relay_on(relay_on),
					.relay_off(relay_off),
					.counter(counter),
					.sm_state(sm_state)
);
endmodule

Frequency Divider
Code:
module freq_divider(
					clk,				//Clock 24 MHz
					rst_n,				//Active low reset
					divided_frequency,	//Divided frequency
					new_freq,
					counter				//Current value
);

input clk;
input rst_n;

output divided_frequency;
output [14:0] counter;
output new_freq;

reg divided_frequency, divided_frequency_next;
reg [14:0] counter, counter_next;
reg new_freq;

//Flip Flops
always @(posedge clk or negedge rst_n)
begin
	if (!rst_n)
		begin
			divided_frequency <= 1'b0;
			counter <= 15'b0000000_0000_0000;
		end

	else
		begin
			divided_frequency <= divided_frequency_next;
			counter <= counter_next;
		end
end

//Parallel Counter Logic
always @(counter or divided_frequency)
begin
	if (counter == 24000)
		begin
			counter_next <= 15'b0000000_0000_0000;
			divided_frequency_next <= 1'b1;
		end

	 else
		begin
			divided_frequency_next <= 1'b0;
			counter_next <= counter + 1;
		end

end

always @(posedge divided_frequency)
begin
	new_freq <= !new_freq;
end

endmodule
 
  • #14
You mean you see the clock going in, but in the new code, the counter is not counting?
 

Similar threads

  • · Replies 9 ·
Replies
9
Views
5K
  • · Replies 6 ·
Replies
6
Views
6K
  • · Replies 39 ·
2
Replies
39
Views
5K
Replies
20
Views
2K
  • · Replies 1 ·
Replies
1
Views
4K
  • · Replies 67 ·
3
Replies
67
Views
7K
  • Sticky
  • · Replies 13 ·
Replies
13
Views
8K
  • · Replies 9 ·
Replies
9
Views
3K
  • · Replies 4 ·
Replies
4
Views
2K