Author Topic: Dividing 20MHz FPGA clock down to 2Hz  (Read 7412 times)

0 Members and 1 Guest are viewing this topic.

Offline djsbTopic starter

  • Frequent Contributor
  • **
  • Posts: 892
  • Country: gb
Dividing 20MHz FPGA clock down to 2Hz
« on: December 28, 2013, 12:36:00 pm »
I'm playing around with my Nanoboard 3000 and I want to provide a 2Hz clock so I can flash some leds using AND,OR gates etc.
Seems I can do this using the 20Mhz on board clock and using some VHDL code. This is (very briefly) described here

http://electronics.stackexchange.com/questions/61422/how-to-divide-50mhz-down-to-2hz-in-vhdl-on-xilinx-fpga

The VHDL code is as follows

Code: [Select]
library IEEE;
use IEEE.STD_LOGIC_1164.all;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.all;

entity scale_clock is
  port (
    clk_50Mhz : in  std_logic;
    rst       : in  std_logic;
    clk_2Hz   : out std_logic);
end scale_clock;

architecture Behavioral of scale_clock is

  signal prescaler : unsigned(23 downto 0);
  signal clk_2Hz_i : std_logic;
begin

  gen_clk : process (clk_50Mhz, rst)
  begin  -- process gen_clk
    if rst = '1' then
      clk_2Hz_i   <= '0';
      prescaler   <= (others => '0');
    elsif rising_edge(clk_50Mhz) then   -- rising clock edge
      if prescaler = X"BEBC20" then     -- 12 500 000 in hex
        prescaler   <= (others => '0');
        clk_2Hz_i   <= not clk_2Hz_i;
      else
        prescaler <= prescaler + "1";
      end if;
    end if;
  end process gen_clk;

clk_2Hz <= clk_2Hz_i;

end Behavioral;

I've edited the code for 20Mhz here

Code: [Select]
library IEEE;
use IEEE.STD_LOGIC_1164.all;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.all;

entity scale_clock is
  port (
    clk_20Mhz : in  std_logic;
    rst       : in  std_logic;
    clk_2Hz   : out std_logic);
end scale_clock;

architecture Behavioral of scale_clock is

  signal prescaler : unsigned(23 downto 0);
  signal clk_2Hz_i : std_logic;
begin

  gen_clk : process (clk_20Mhz, rst)
  begin  -- process gen_clk
    if rst = '1' then
      clk_2Hz_i   <= '0';
      prescaler   <= (others => '0');
    elsif rising_edge(clk_20Mhz) then   -- rising clock edge
      if prescaler = X"4C4B40" then     -- 5 000 000 in hex
        prescaler   <= (others => '0');
        clk_2Hz_i   <= not clk_2Hz_i;
      else
        prescaler <= prescaler + "1";
      end if;
    end if;
  end process gen_clk;

clk_2Hz <= clk_2Hz_i;

end Behavioral;


However I don't really understand how this code works and in particular this line

signal prescaler : unsigned(23 downto 0);

I'm not sure if 23 is the correct number for a start even if I did understand how it works in context with the rest of the code.

I'd like someone here to help me understnd how this works if possible.
Thanks.

David.
David
Hertfordshire,UK
University Electronics Technician, London PIC,CCS C,Arduino,Kicad, Altium Designer,LPKF S103,S62 Operator, Electronics instructor. Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime. Credited Kicad French to English translator.
 

Online jahonen

  • Super Contributor
  • ***
  • Posts: 1054
  • Country: fi
Re: Dividing 20MHz FPGA clock down to 2Hz
« Reply #1 on: December 28, 2013, 12:54:14 pm »
That should work just fine.

Basically, prescaler signal counts to half-cycle of 2 Hz (0.25 seconds of main clock cycles) and then output is inverted, prescale counter reset and process repeats. The signal declaration you ask just defines a 24-bit counter. It works as long it is large enough to hold the range you require, which is the case here.

Regards,
Janne
 

Offline djsbTopic starter

  • Frequent Contributor
  • **
  • Posts: 892
  • Country: gb
Re: Dividing 20MHz FPGA clock down to 2Hz
« Reply #2 on: December 28, 2013, 06:19:25 pm »
Thanks Janne,
Finally got it to work after figuring out how the sheet symbols work with VHDL code in Altium.
It was quite easy really. Now I have an incentive to learn some more VHDL and see it working.

David.

PS Here are the design stats

###############################################################################
### Design Statistics
###############################################################################
 
Flipflops:                                                 : 25
    Flipflops with RESET                    (Asynchronous) : 24
    Flipflops with RESET and ENABLE         (Synchronous)  : 1
                                                           
MacroCells:                                               
    AND2S                                                  : 1
    INV                                                    : 2
    XORCY                                                  : 23
    MUXCY                                                  : 22
                                                           
Area Estimates:                                           
    Area Estimate (2 Input Gate Count)                     : 42
    Area Estimate (LUT Count)                              : 37
 
I'm wondering what XORCY and MUXCY are? How all this is connected up inside the FPGA I suppose I'll leave for some future research.
« Last Edit: December 28, 2013, 06:39:51 pm by djsb »
David
Hertfordshire,UK
University Electronics Technician, London PIC,CCS C,Arduino,Kicad, Altium Designer,LPKF S103,S62 Operator, Electronics instructor. Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime. Credited Kicad French to English translator.
 

Offline codeboy2k

  • Super Contributor
  • ***
  • Posts: 1836
  • Country: ca
Re: Dividing 20MHz FPGA clock down to 2Hz
« Reply #3 on: December 28, 2013, 09:37:05 pm »
I'm wondering what XORCY and MUXCY are?

XORCY and MUXCY are Xilinx resources in a logic cell (called a SLICE in Xilinx speak). Depending on the family used, each slice will have some limited number of those resources, along with some limited number of either a 4 input  or 6-input LUT .

XORCY is used for addition (binary addition is simply XOR),and in combination with MUXCY it provides a fast carry propogate logic to the next XORCY (basically a 2-bit full adder).  A typical 2-bit full adder uses 3 XOR gates and 2 AND gates... but the carry logic can be done with a MUX, so they call it MUXCY, because the MUX can also be used for other things in a slice when it's not being used for carry logic propagation.

Quote
How all this is connected up inside the FPGA I suppose I'll leave for some future research.
You can view it on your tools. Look for the gate level viewer.  Although I can't know exactly how your design was synthesized, your design is simple enough that I can make a reasonable guess here: it seems your design used 25 flip-flops total, and it seems like 23 are the registers for your counter (which turned out to be a 23-bit counter, actually, not a 24-bit counter as you asked for; the synthesis step was smart enough to know you didn't need 24 bits).  The 2 remaining FFs are used for other things that are not part of the 23-bit counter (likely the 2Hz registered output).  The outputs of each of the 23 FFs are going to be routed back to one input of an XORCY (2-input XOR); the second input of each XORCY will be hardwired to logic 0, except the first one, which is hardwired to logic 1.  Thus you have 23 XOR gates, with the A inputs tied to the Q outputs of the FFs and the B inputs tied to X'000001', ; the output of each XORCY gate is sent back to the FF D-input. Thus, it takes the current value of the 23-bit counter, adds 1 to it, and registers it again in the FF, on each clock cycle.  The MUXCY is designed to propagate any carry bits up the chain.

Finally, the AND and INV will be glue logic that was needed somewhere.

Most likely, it also programs the interconnect to wire the Q outputs of each FF back to the address inputs of the LUTS, and uses the LUTS as a comparator to hex 4C4B40 (5,000,000 10) to output logic to drive the reset of the counter. I think it did that because it is most efficient in terms of LUT resources used (slices), and the design output didn't show any additional gates used.

If it used more logic gates as comparators then it would need to use more slices and longer interconnects, and it would waste the LUTS of the counter slices as well as the slices needed for the additional logic gates, and thus use more area. So I think it chose not to use more gates (or muxes) but to use the (what would otherwise be unused) LUTS that are on the same slices as the FFs. Even though it seems like a waste to use LUTS as a simple comparator, in this case it's not really, because those are otherwise unused.
 

Offline djsbTopic starter

  • Frequent Contributor
  • **
  • Posts: 892
  • Country: gb
Re: Dividing 20MHz FPGA clock down to 2Hz
« Reply #4 on: December 28, 2013, 10:06:26 pm »
Thanks codeboy2k,
All the gate level logic is behind the scenes in Altium. All I did was put a 2 input AND gate with an invertor on each input (for the push button switch polarity). Then I put a port for the main clock and a sheet symbol on the schematic. The VHDL code was saved as a file associated with the sheet. Altium goes through all the steps needed (synthesis, mapping,timing analysis etc) but it's all hidden behind the scenes (with green for GO and red for ERROR etc). I can still look for the gate level design using the native xilinx tools that Altium drives. Not sure which xilinx tool I would use for this and which files I would open though.
I want to learn about this stuff so I look forward to exploring some more.

David.
« Last Edit: December 28, 2013, 10:10:19 pm by djsb »
David
Hertfordshire,UK
University Electronics Technician, London PIC,CCS C,Arduino,Kicad, Altium Designer,LPKF S103,S62 Operator, Electronics instructor. Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime. Credited Kicad French to English translator.
 

Offline djsbTopic starter

  • Frequent Contributor
  • **
  • Posts: 892
  • Country: gb
Re: Dividing 20MHz FPGA clock down to 2Hz
« Reply #5 on: December 29, 2013, 01:36:51 pm »
Ok, now I'm going to have a try using the Aldec simulator built into Altium Designer.

Here is the automatically created testbench

Code: [Select]
------------------------------------------------------------
-- VHDL Testbench for TWO_INPUT_AND
-- 2013 12 29 13 19 9
-- Created by "EditVHDL"
-- "Copyright (c) 2002 Altium Limited"
------------------------------------------------------------

Library IEEE;
Use     IEEE.std_logic_1164.all;
Use     IEEE.std_logic_textio.all;
Use     STD.textio.all;
------------------------------------------------------------

------------------------------------------------------------
entity TestTWO_INPUT_AND is
end TestTWO_INPUT_AND;
------------------------------------------------------------

------------------------------------------------------------
architecture stimulus of TestTWO_INPUT_AND is
    file RESULTS: TEXT open WRITE_MODE is "results.txt";
    procedure WRITE_RESULTS(
        CLK_BRD: std_logic;
        LED_R0: std_logic;
        SW_USER0: std_logic;
        SW_USER1: std_logic
    ) is
        variable l_out : line;
    begin
        write(l_out, now, right, 15);
        write(l_out, CLK_BRD, right, 2);
        write(l_out, LED_R0, right, 2);
        write(l_out, SW_USER0, right, 2);
        write(l_out, SW_USER1, right, 2);
        writeline(RESULTS, l_out);
    end procedure;

    component TWO_INPUT_AND
        port (
            CLK_BRD: in std_logic;
            LED_R0: out std_logic;
            SW_USER0: in std_logic;
            SW_USER1: in std_logic
        );
    end component;

    signal CLK_BRD: std_logic;
    signal LED_R0: std_logic;
    signal SW_USER0: std_logic;
    signal SW_USER1: std_logic;

begin
    DUT:TWO_INPUT_AND port map (
        CLK_BRD => CLK_BRD,
        LED_R0 => LED_R0,
        SW_USER0 => SW_USER0,
        SW_USER1 => SW_USER1
    );

    STIMULUS0:process
    begin
        -- insert stimulus here (what do I put in here?)
        wait;
    end process;

    WRITE_RESULTS(
        CLK_BRD,
        LED_R0,
        SW_USER0,
        SW_USER1
    );

end architecture;
------------------------------------------------------------

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

Now I'm wondering if I need to make any changes to this code? Is it correct for the circuit I'm using and how do I simulate pressing SW_USER0 and SW_USER1 for say 5 seconds. I need to press both of these buttons on the NB3K for the LED to flash. Any pointers?

TIA.

David.
David
Hertfordshire,UK
University Electronics Technician, London PIC,CCS C,Arduino,Kicad, Altium Designer,LPKF S103,S62 Operator, Electronics instructor. Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime. Credited Kicad French to English translator.
 

Online jahonen

  • Super Contributor
  • ***
  • Posts: 1054
  • Country: fi
Re: Dividing 20MHz FPGA clock down to 2Hz
« Reply #6 on: December 29, 2013, 02:15:29 pm »
Try it like this:

Code: [Select]
    STIMULUS0:process
    begin
        SW_USER0 => '0';
        SW_USER1 => '0';
        wait for 5 sec;
        SW_USER0 => '1';
        SW_USER1 => '1';
        wait;
    end process;

Or swap 0 and 1 if polarity is not correct.

Regards,
Janne
 

Offline zapta

  • Super Contributor
  • ***
  • Posts: 6190
  • Country: us
Re: Dividing 20MHz FPGA clock down to 2Hz
« Reply #7 on: December 29, 2013, 03:51:24 pm »
However I don't really understand how this code works and in particular this line

signal prescaler : unsigned(23 downto 0);

I'm not sure if 23 is the correct number for a start even if I did understand how it works in context with the rest of the code.

This about the naming convention (indexing) of the 24 bits in your signal which happened to be a counter. Has nothing to do with the up/down counting.
 

Offline daveatol

  • Regular Contributor
  • *
  • Posts: 136
  • Country: au
Re: Dividing 20MHz FPGA clock down to 2Hz
« Reply #8 on: December 30, 2013, 01:31:36 am »
Regarding the accuracy of your divider, it's dividing by 10,000,002 rather than 10,000,000. If you use this code pattern again for something that requires an exact division ratio, you may want to keep this in mind.
 

Offline codeboy2k

  • Super Contributor
  • ***
  • Posts: 1836
  • Country: ca
Re: Dividing 20MHz FPGA clock down to 2Hz
« Reply #9 on: December 30, 2013, 03:26:42 am »
Regarding the accuracy of your divider, it's dividing by 10,000,002 rather than 10,000,000. If you use this code pattern again for something that requires an exact division ratio, you may want to keep this in mind.

Yes, good catch, easy fix.. should be changed to count from 0 to 4,999,999

->>>    if prescaler = X"4C4B3F" then     -- 4 999 999 in hex

Also, OP said:

However I don't really understand how this code works and in particular this line

signal prescaler : unsigned(23 downto 0);

I'm not sure if 23 is the correct number for a start even if I did understand how it works in context with the rest of the code.

The number of bits you need to count to N is log(N)/log(2). 

So the original VHDL code needed to count to 12,500,000 so it used log(12500000)/log(2) = 23.575, so 24 bits. (23 downto 0)

In your case, you only need to count to 4,999,999 , log (4999999)/log(2) is 22.25 so you need 23 bits (22 down to 0)


 

Offline amyk

  • Super Contributor
  • ***
  • Posts: 8275
Re: Dividing 20MHz FPGA clock down to 2Hz
« Reply #10 on: December 30, 2013, 07:12:42 am »
I like power-of-2 clock frequencies because it makes division much simpler. :)
 

Offline codeboy2k

  • Super Contributor
  • ***
  • Posts: 1836
  • Country: ca
Re: Dividing 20MHz FPGA clock down to 2Hz
« Reply #11 on: December 30, 2013, 09:19:42 am »
I like power-of-2 clock frequencies because it makes division much simpler. :)

Me too.  It also uses much less resources in an FPGA, for example the synthesizer can just use the single carry out from a counter chain as an enable line to the register that counts at the lower frequency.  It no longer needs to use LUT resources as a comparator, so those are free for other uses.

 

Offline mrflibble

  • Super Contributor
  • ***
  • Posts: 2051
  • Country: nl
Re: Dividing 20MHz FPGA clock down to 2Hz
« Reply #12 on: December 30, 2013, 10:06:15 am »
I like power-of-2 clock frequencies because it makes division much simpler. :)

Me too.  It also uses much less resources in an FPGA, for example the synthesizer can just use the single carry out from a counter chain as an enable line to the register that counts at the lower frequency.  It no longer needs to use LUT resources as a comparator, so those are free for other uses.
Ditto. I also like numbers that have single multiplicities for the prime factors, where the prime factors are small enough that they fit nicely in a shift register (<= 16 or <=32). AND the outputs of those shift registers and voila, we have clock enable. Even cheaper in resources than carry chains. And less effort to get it working at high clock speeds.
 

Offline djsbTopic starter

  • Frequent Contributor
  • **
  • Posts: 892
  • Country: gb
Re: Dividing 20MHz FPGA clock down to 2Hz
« Reply #13 on: December 30, 2013, 10:53:27 am »
Thanks everyone for your help. I'll go back and change my code as suggested. Then I'll try and do some more reading on how all this stuff works.

David.
David
Hertfordshire,UK
University Electronics Technician, London PIC,CCS C,Arduino,Kicad, Altium Designer,LPKF S103,S62 Operator, Electronics instructor. Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime. Credited Kicad French to English translator.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf