cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
nikoiv
Visitor
Visitor
7,259 Views
Registered: ‎09-04-2009

divide clock by 13.5 circuit

In the documentation accompanying the 6 release of microprocessor Picoblaze, Ken Chapman gives an example, which illustrates the operation of the UART module (UART6_User_Guide_and_Reference_Designs_29March13.pdf).

Particularly attractive to me was the idea that suggests how to build a frequency divider for 115200 baud UART module mode operation, from system frequency 25MHz.
I realize this idea of a low level. This code is used successfully for 2 months in a several projects, implemented in the kit with systemic frequency 25MHz.  I think it will be pleasant for the users of the forum.  Here it is:
----------------------------------------------------------------------------------

--

-- Engineer: Nikolay Ivanov

-- Create Date:    04/17/2013

-- Module Name:   Baud_rate_Timer - Low level definition

-- Project Name:          Baud_rate 115200     

-- Target Devices:  XC6

-- Tool versions: Xilinx WebPack ISE 14.4

-- Description: Generates a Baud rate pulses in order to perform 115200 baud communication

--              from system frequency of 25  MHz.

-- Dependencies:

--

-- Revision: 0.01 - File Created

--

----------------------------------------------------------------------------------

--

-- Library declarations

--

-- Standard IEEE libraries

--

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

library UNISIM;

use UNISIM.VComponents.all;

------------------------------------------------------------------------------------

--

entity Baud_rate_Timer is

    Port (  En_16_x_baud : out std_logic;

                     clk : in std_logic);

    end Baud_rate_Timer;

--

------------------------------------------------------------------------------------

-- Start of test architecture

--

architecture Low_level of Baud_rate_Timer is

--

signal a1,a2, a3 : STD_LOGIC := '0';

--

------------------------------------------------------------------------------------------------

--

-- Start of circuit description

--

begin

--

SRL16E_inst1 : SRL16E

generic map (INIT => X"0001")

--

port map (Q => a1,

                                     A0 => '0',

                                     A1 => '0',

                                     A2 => '1',

                                     A3 => '1',

                                     CE => '1',

                                     CLK => clk,

                                     D => a2 );

--

SRL16E_inst2 : SRL16E

generic map (INIT => X"0000")

--

port map (Q => a2,

               A0 => '1',

               A1 => '0',

               A2 => '1',

               A3 => '1',

               CE => '1',

            CLK => clk,

                 D => a1 );

--

LUT2_inst : LUT2

generic map (INIT => X"E")--or2

--

port map (O => a3,

                I0 => a1,

                I1 => a2 );

--

FDCE_inst : FDCE

generic map (INIT => '0')

--

port map (Q => En_16_x_baud,

     C => clk,

  CE => '1',

           CLR => '0',

                D => a3 );

--

end Low_level;

-----------------------------------------------------------------

-- end of Baud_rate_Timer module

-----------------------------------------------------------------
Success!

0 Kudos
6 Replies
gszakacs
Professor
Professor
7,249 Views
Registered: ‎08-14-2007

This is exactly the reason why I think the idea of using a 16X baud clock for a UART

makes no sense in an FPGA with all its resources.  My own UART incorporates

the baud divider, and samples at the input clock rate, in this case 25 MHz.  Then

the oversampling rate is just clock frequency divided by baud rate, in this case 217.

This gives a very tight baud rate tolerance as well as allowing for sampling very

close to the center of the bit period.  Of course this necessitates a longer baud

divider within the UART but eliminates the (jittery) external clock divider that would

of necessity be in the FPGA also.

-- Gabor
0 Kudos
nikoiv
Visitor
Visitor
7,216 Views
Registered: ‎09-04-2009

Gabor, I do not know your uart module. But I agree with you that the accuracy obtained by dividing 25 MHz to 217 is very high. (0.006%). The objective pursued by the proposed solution is to achieve frequency which after division of 16 allow to the communication module to operate in 115200 baud mode. The accuracy achieved with the proposed solution is near 0.47%, which in practice is more than enough. And because theoretically the divider can be realized within a slice, it becomes a minimax solution I think.

0 Kudos
vremmers
Visitor
Visitor
6,118 Views
Registered: ‎01-19-2014

Nikolay,

 

Thankyou for providing this divide by 14,13,14,13...

It seemed a little more complex than necessary.

 

I made a few changes

 

Changed to use SRL16 instead of SRL16E as the CE was not used

(would not reduce resources used, but simplifies the source)

 

Changed both SRL16 to have INIT of 0001 and removed LUT2

(reduces resources used by no longer needing a 2 input LUT)

 

Changed to use FD instead of FDCE as neither CE or CLR were used

(would not reduce resources used, but simplifies the source)

 

I can not see why the output flip-flop is needed, but in the

White-Paper WP271, Mr. Chapman states:

"The flip-flop ensures high performance, as such an enable pulse may have a high fan-out.".
Is this implying that a flip-flop can fan-out to a larger number

of inputs, or does the synthesis replicate this output flip-flop
based on the number of inputs it needs to fan out.

 

Vince

 

--------------------------------------------------?--------------------------------
--
-- Engineer: Nikolay Ivanov
-- Create Date:    04/17/2013
-- Module Name:   Baud_rate_Timer - Low level definition
-- Project Name:          Baud_rate 115200    
-- Target Devices:  XC6
-- Tool versions: Xilinx WebPack ISE 14.4
-- Description: Generates a Baud rate pulses in order to perform 115200 baud communication
--              from system frequency of 25  MHz.
-- Dependencies:
--
-- Revision: 0.01 - File Created
--
--------------------------------------------------?--------------------------------
--
-- Library declarations
--
-- Standard IEEE libraries
--
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library UNISIM;
use UNISIM.VComponents.all;
--------------------------------------------------?----------------------------------
--
entity Baud_rate_Timer is
    Port (  En_16_x_baud : out std_logic;
                     clk : in std_logic);
    end Baud_rate_Timer;
--
--------------------------------------------------?----------------------------------
-- Start of test architecture
--
architecture Low_level of Baud_rate_Timer is
--
signal a1,a2 : STD_LOGIC := '0';
--
--------------------------------------------------?----------------------------------------------
--
-- Start of circuit description
--
begin
--
SRL16E_inst1 : SRL16
generic map (INIT => X"0001")
--
port map (Q => a1,
         A0 => '0',
         A1 => '0',
         A2 => '1',
         A3 => '1',
        CLK => clk,
          D => a2 );
--
SRL16E_inst2 : SRL16
generic map (INIT => X"0001")
--
port map (Q => a2,
         A0 => '1',
         A1 => '0',
         A2 => '1',
         A3 => '1',
        CLK => clk,
          D => a1 );
--
FDCE_inst : FD
generic map (INIT => '0')
--
port map (Q => En_16_x_baud,
          C => clk,
          D => a1 );
--
end Low_level;
--------------------------------------------------?---------------
-- end of Baud_rate_Timer module
--------------------------------------------------?---------------

 

0 Kudos
chapman
Xilinx Employee
Xilinx Employee
6,113 Views
Registered: ‎09-05-2007

If, for example, we look in the Kintex-7 data sheet (DS182) we can see that for a -1 speed grade the clock to output time of a dedicated flip-flop (TCKO) is 0.32ns but the clock to output time of an SRL 16 (TREG) is 1.2ns. So when you use a dedicated flip-flop there is 0.88ns more time available for the routing of the signal and that just makes it easier to route a signal a longer distance and/or fan out to more loads. It is not about the drive strength of the CLB output; only the difference in delay.

Ken Chapman
Principal Engineer, Xilinx UK
0 Kudos
vremmers
Visitor
Visitor
6,077 Views
Registered: ‎01-19-2014

Mr. Ken (Constant with a 'K', wink) Chapman,

 

Thankyou for explaining this.  I understand this much better now.  By looking at the timing diagram on the next page (WP271

page 14),  I see that the flip flop is effectively providing an extra shift register bit, outside the circular shift register in the SRL16.

The outgoing pulse is one clock cycle delayed, except the transition edge of the Q output is much closer to the transition

edge of CLK, than it would have been if the output Q of the SRL16 could have been used directly.

 

I am actually currently using a Spartan3AN, "-4" grade, and the difference is even more pronounced than the example

you gave.

 

TCKO Flip-Flop, Time from clock transition to output on Q = 0.68ns

TREG Shift Register, Time from clock transition to output on Q = 4.82nS 

 

Thankout

Vince

0 Kudos
vremmers
Visitor
Visitor
6,074 Views
Registered: ‎01-19-2014

Also note:

If you are using a Spartan6, the shift registers and be configured as 32 bits, and so this could be

done with one shift register and one flip-flop

 

entity Baud_rate_Timer is
    Port (  En_16_x_baud : out std_logic;
                     clk : in std_logic);
    end Baud_rate_Timer;
--
--------------------------------------------------?----------------------------------
-- Start of test architecture
--
architecture Low_level of Baud_rate_Timer is
--
signal a1 : STD_LOGIC := '0';
--
--------------------------------------------------?----------------------------------------------
--
-- Start of circuit description
--
begin
--
SRL32_inst : SRLC32E
generic map (INIT => X"00004001")
--
port map (Q => a1,
        Q31 => open,
          A => "11010",
        CLK => clk,
         CE => '1',
          D => a1 );
--
FD_inst : FD
generic map (INIT => '0')
--
port map (Q => En_16_x_baud,
          C => clk,
          D => a1 );
--
end Low_level;

0 Kudos