06-13-2019 03:42 AM
I have created design with MicroBlaze + uart16550, Vivado 2018.3. My requirements are baudrate error less than 0.5%. I have generated frequency, good enough at xin pin of uart16550 using MMCM and PLL in chain to produce the required baudrate and error if I'm using the forumla in PG143, page 27:
divisor = (AXI CLK frequency/(16 × Baud Rate))
But this formula assumes the clock used to feed the baudrate generator is actually the AXI clock, not the external xin. And I can't find formula for external clock on xin. Anyway, when exploring the driver generated for this IP by SDK I found this (xuartns550.c, XUartNs550_SetBaudRate() ):
/* * Determine what the divisor should be to get the specified baud * rater based upon the input clock frequency and a baud clock prescaler * of 16 */ Divisor = ((InstancePtr->InputClockHz +((BaudRate * 16UL)/2)) / (BaudRate * 16UL));
Well, this formula differs from the documented one, so with it my error is above the desired limit.
The question is: how must I calculate the correct divisor value and error when using external clock (xin) for uart16550 IO?
07-02-2019 12:55 AM
Hi @head_up ,
Please follow the below link and check the example 2 for usage of the AXI UART 16550 when external xin clock is used.
07-02-2019 01:22 AM
@abhinayp , thank you for your answer, but I already checked this example. If I use the forumla for axi clock (the first in my my post, from this document) the Divisor Latch should be set to 2,057 i.e. 2 as it is in the example. If used the formula in the driver the value should be 2.557. Please, check the drvier for uart 16550 with external clock and let me know - is the driver formula wrong?
08-14-2019 04:07 PM
I would like to know where this equation comes from as well
xuart550.c /* * Determine what the divisor should be to get the specified baud * rater based upon the input clock frequency and a baud clock prescaler * of 16 */ Divisor = ((InstancePtr->InputClockHz +((BaudRate * 16UL)/2)) / (BaudRate * 16UL));
This is not consistent with the documentation of the PC16550, and this new equation apparently specific to the IP is not doucmented in the product guide, or in the driver code, apart from the comment block shown.
08-14-2019 05:19 PM
The Xilinx driver forumula adds exactly 0.5 to the divisor for some reason..possiby for the following error calculations?
In any case, the 0.5 is dropped when the divisor is assigned to the uart's divisor latch, so assuming your baud passes the error calculations, it is correctly assigned.
I tested the UART using the PC16550 equation for finding the divisor and it works as expected.
In other words, if you assign the divisor manually as per the PC16550 documentation, you will get the BAUD you are expecting. And if you assign the BUAD using the xuartns550 drivers, asuming it passes the error calculations, it will also be assigned correctly despite the somewhat misleading equation.
08-16-2019 01:10 AM
Integer division is defined in C (for positive values) to round the result down to an integer.
e.g x is 111 and y is 16,
x / y gives the value 6.
For the Baud rate, we want to round to nearest (rather than down) because we want to minimise the rate error. In this case, we probably want x / y to give us the value 7, because 7 is closer to the exact result (6.9375) than 6.
The usual way of rouding to nearest is:
(x + y / 2) / y
which does give us the correct value in this case.
The Baud rate error depends on the exact ratio of clock frequencies. The formula that rounds to nearest is the one to use in the general case.