我正在用 Verilog 编写 VGA 控制器。我有一个 100 MHz 时钟,我想在 16670 毫秒的时间内启用信号 VPIXEL 480 次。
显然,我不能每 16670ms/480 ~= 34729.166ms 启用 VPIXEL 或 34729.166...100MHz 时钟的计数。
解决问题的最佳方法是什么,从长远来看,误差最小?
我不想使用新时钟。
这是一个非常老的问题,我知道这个问题的第一个例子是公历的设计。
如果您要求从长远来看减少误差,那可能是因为您尝试使用整数除法阈值的计数器,即每 34729 个时钟一个脉冲,然后您注意到脉冲将开始太早出现。
由于分母是常数,您可以编写一个计数器,您可以跟踪该值,而无需任何除法电路仅更新分数的分子。
// 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
您可以通过简化因子来减少一些位,例如将
N
和 D
除以 160
,另外,你 16670 非常怀疑只是 50000/3
的另一个近似值,在这种情况下,也许你也必须将其作为分数。