FPGA 串口 波特率 发生器 代码 求教

2019-03-25 07:55发布

代码如下:25M晶振下产生115200的波特率 没有过采样
//////////////////////////////////////////////////////////////////////////////////
module BaudTickGen(
        input clk, enable,
        output tick  // generate a tick at the specified baud rate * oversampling
);


        parameter ClkFrequency = 25000000;
        parameter Baud = 115200;
        parameter Oversampling = 1;


        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<<BaudGeneratorAccWidth)/ClkFrequency;


reg [BaudGeneratorAccWidth:0] BaudGeneratorAcc;
always @(posedge clk)
  BaudGeneratorAcc <= BaudGeneratorAcc[BaudGeneratorAccWidth-1:0] + BaudGeneratorInc;


wire BaudTick = BaudGeneratorAcc[BaudGeneratorAccWidth];

疑问如下:
Instead of "2000000/115200", let's use "1024/59" = 17.356.
近似的时候为什么选择了1024 ?
然后累加器就用了十位的,
25M的时候 又近似的多少呢? 65535? 然后用了16位的?
我是想知道这个近似是怎么确定的?
还是只要精度够 就没必要纠结是多少?
这点并没有介绍?

望大家有这方面经验的朋友不吝点拨~~
此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
3条回答
aibing
1楼-- · 2019-03-25 14:54
 精彩回答 2  元偷偷看……
aibing
2楼-- · 2019-03-25 16:23
代码倒是很好使 吼吼
aibing
3楼-- · 2019-03-25 20:10
本帖最后由 aibing 于 2014-11-30 21:21 编辑

自说自话吧...这是modelsim里的仿真图大致计算了下25M晶振下,1s计115207次,误差在0.006%,满足串口波特率误差容忍范围

一周热门 更多>