function integer log2(input integer v);
begin
log2=0;
while(v>>log2) log2=log2+1;
end
endfunction
localparam AccWidth = log2(ClkFrequency/Baud)+8; // +/- 2% max timing error over a byte
reg [AccWidth:0] Acc = 0;
localparam ShiftLimiter = log2(Baud*Oversampling >> (31-AccWidth)); // this makes sure Inc calculation doesn't overflow
localparam Inc = ((Baud*Oversampling << (AccWidth-ShiftLimiter))+(ClkFrequency>>(ShiftLimiter+1)))/(ClkFrequency>>ShiftLimiter);
always @(posedge clk)
begin
if(enable) Acc <= Acc[AccWidth-1:0] + Inc[AccWidth:0];
else Acc <= Inc[AccWidth:0];
end
assign tick = Acc[AccWidth];
endmodule
///////////////////////////////////////////////////////////////////////////////
有如下疑问:
1.ACC的宽度处有一个+8,不明白为什么是8
2.+/- 2% max timing error over a byte 是如何计算的?
其实这个程序源于以下波特率发生器的介绍,但同样有疑问:
But what do you do if all your have is, say, a 2MHz clock? To generate 115200Hz from a 2MHz clock, you divide the clock by "17.361111111..." Not exactly a round number. The solution is to divide sometimes by 17, sometimes by 18, making sure the ratio stays "17.361111111". That's actually easy to do.
Look at the following "C" code:
while(1) // repeat forever
{
acc += 115200;
if(acc>=2000000) printf("*"); else printf(" ");
acc %= 2000000;
}
That prints the "*" in the exact ratio, once every "17.361111111..." loops on average.
To obtain the same thing efficiently in an FPGA, we rely on the fact that the serial interface can tolerate a few % of error in the baud frequency generator.
It is desirable that the 2000000 be a power of two. Obviously 2000000 is not. So we change the ratio... Instead of "2000000/115200", let's use "1024/59" = 17.356. That's very close to our ideal ratio, and makes an efficient FPGA implementation.
// 10 bits for the accumulator ([9:0]), and one extra bit for the accumulator carry-out ([10])
reg [10:0] acc; // 11 bits total!
always @(posedge clk)
acc <= acc[9:0] + 59; // use only 10 bits from the previous result, but save the full 11 bits
wire BaudTick = acc[10]; // so that the 11th bit is the carry-out
Using our 2MHz clock, "BaudTick" is asserted 115234 times a second, a 0.03% error from the ideal 115200.
Parameterized FPGA baud generator
The previous design was using a 10 bits accumulator, but as the clock frequency increases, more bits are required.
Here's a design with a 25MHz clock and a 16 bits accumulator. The design is parameterized, so easy to customize.
parameter ClkFrequency = 25000000; // 25MHz
parameter Baud = 115200;
parameter BaudGeneratorAccWidth = 16;
parameter BaudGeneratorInc = (Baud<