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

  • Thread starter Thread starter EugP
  • Start date Start date
  • Tags Tags
    Clock
AI Thread Summary
To divide a 24MHz clock to achieve a 1kHz output in Verilog, a counter-based approach is suggested, where a counter counts to 24,000. The implementation involves creating a frequency divider module that toggles an output signal when the counter reaches 24,000, then resets. Users are encouraged to ensure proper integration of the frequency divider in their top-level module and verify that the clock input is correctly configured. Issues may arise if the counter does not increment as expected, indicating potential problems in the module's instantiation or signal connections. Understanding the counter logic is crucial for successfully dividing any frequency in FPGA designs.
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?
 
Back
Top