I'm writing a VGA controller in Verilog. I have a 100 MHz clock and I want to enable a signal, VPIXEL, 480 times in a span of 16670 ms.
Obviously, I can't enable VPIXEL every 16670ms/480 ~= 34729.166ms or 34729.166... counts of the 100MHz clock.
What is the best way to approach the problem, so that the error is minimal in the long run?
I don't want to use a new clock.
This is a very old problem, the first instance of this problem that I a m aware of is the design of the Gregorian calendar.
If you are asking to reduce the error in the long run, that is probably because you tried a counter using the integer division threshold, i.e. one pulse every 34729 clocks, and then you notice that the pulse will start to come too early.
Since the denominator is constant you can write a counter you can keep track of the value without any division circuit updating only the numerator of the fraction.
// Code just typed here to illustrate the idea, not tested
// may have even syntax errors
module fractional_counter #(
parameter N=16670*1000*100,
parameter D=480
) (
input logic clk,
input logic rst,
output logic pls
);
localparam NB=$clog2(N+D);
logic [NB-1:0] current_num;
always @(posedge clk) begin
if(rst) begin
current_num = 0;
end
else begin
if(current_num >= N - D) begin
// (current_num+D)/D >= N/D
// a cycle is complete
current_num <= (current_num + D - N);
pls <= 1;
end
else begin
// Increase the counter
// current_num / D + 1 = (current_num + D) / D
current_num <= current_num + D;
pls <= 0;
end
end
end
endmodule
You can reduce a few bits there, by simplifying the factor, e.g. dividing both N
and D
by 160
, also, you 16670 is very suspicious of being just another approximation of 50000/3
in that case maybe you have to put that as a fraction as well.