Trying to implement a programmable clock divider in Verilog, with the input divide value able to be set between 1 (clk_out = clk_in) and 2^8 (clk_out = clk_in/256). Here is a working example that performs beautifully in simulation:
module clk_divider (
input clk_in,
input [7:0] divider,
output reg clk_out
);
reg[7:0] counter = 8'd0;
always @(posedge clk_in or negedge clk_in) begin
counter <= counter + 1;
if (counter >= ((divider * 2) - 1)) begin
counter <= 0;
end
if (divider == 1) begin
clk_out <= clk_in;
end else begin
clk_out <= (counter < divider)?1'b1:1'b0;
end
end
endmodule
...however the astute will surely realize that this is not synthesizable in hardware, specifically the always @(posedge clk_in or negedge clk_in)
- attempting to take action on both edges which allows for odd divider values and most importantly my divide by 1 requirement.
Any suggestions for how to implement?
Edit: Final implementation using a mux to pass through clk_in when divider=1. Even-order divides produce 50% duty cycle while odd-order will produce non-50% (off by one half-cycle).
module clk_divider (
input clk_in,
input [7:0] divider,
output wire clk_out
);
reg[7:0] counter = 8'd0;
reg clk_in_div;
wire clk_in_passthru = clk_in;
assign clk_out = (divider == 1)?clk_in_passthru:clk_in_div;
always @(posedge clk_in) begin
counter <= counter + 1;
if (counter >= (divider - 1)) begin
counter <= 0;
end
clk_in_div <= (counter < (divider / 2))?1'b1:1'b0;
end
endmodule
-
\$\begingroup\$ What have you tried? We are not going to just write the code for you. \$\endgroup\$Elliot Alderson– Elliot Alderson2021年09月02日 11:12:01 +00:00Commented Sep 2, 2021 at 11:12
-
\$\begingroup\$ @ElliotAlderson, I tried exactly what I provided above. \$\endgroup\$Antennae– Antennae2021年09月02日 18:06:17 +00:00Commented Sep 2, 2021 at 18:06
1 Answer 1
- The most and simplest way to get rid of "always @(posedge clk_in or negedge clk_in)": MUX the output between the original clock and divided by n clock.
- The simplest way: Regenerate a clock at higher rate using the device internal PLL.
- Simpler way: Phase shift the clock using logic delay, as many as you want. XOR the original clock and the series of phase shifted clock to regenerate higher frequency clock.
- Simple way: Do #3 using external delay-line.
-
\$\begingroup\$ thank you... maybe I am missing something, but seems like your suggestions are for multiplying the clock? I have an external clock coming in that I need to divide down anywhere between freq/1 to freq/256. \$\endgroup\$Antennae– Antennae2021年09月02日 18:35:05 +00:00Commented Sep 2, 2021 at 18:35
-
\$\begingroup\$ @Antennae, Yes, the answer is about either 1)multiplying the clock, or 2)multiplexing the clock in order to get freq/1 along with freq/N. \$\endgroup\$jay– jay2021年09月02日 19:09:35 +00:00Commented Sep 2, 2021 at 19:09
-
\$\begingroup\$ I see. Muxing may be a solution so I can at least get freq/1 output. However without clocking from both edges of the input I can only do even-order divides. May be the best I can do without a whole lot more logic. Thanks for the suggestions. \$\endgroup\$Antennae– Antennae2021年09月02日 19:56:56 +00:00Commented Sep 2, 2021 at 19:56
-
\$\begingroup\$ @Antennae , not necessarily get stuck to 2^n or even division, if you willing to give up 50% duty. Does falling edge give that odd division with 50% duty? \$\endgroup\$jay– jay2021年09月02日 20:09:02 +00:00Commented Sep 2, 2021 at 20:09
-
\$\begingroup\$ 3,4 are highly unrecommended, because OP is targeting FPGAs. \$\endgroup\$Mitu Raj– Mitu Raj2021年09月02日 20:28:29 +00:00Commented Sep 2, 2021 at 20:28