Dividing 20MHz FPGA clock down to 2Hz - Page 1
Forum section: electronics / general

author: djsb
author_rank: Super Contributor
timestamp: December 28, 2013, 12:36:00 pm
content: 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 herehttp://electronics.stackexchange.com/questions/61422/how-to-divide-50mhz-down-to-2hz-in-vhdl-on-xilinx-fpgaThe VHDL code is as followsCode:library IEEE;use IEEE.STD_LOGIC_1164.all;-- Uncomment the following library declaration if using-- arithmetic functions with Signed or Unsigned valuesuse IEEE.NUMERIC_STD.all;entity scale_clock isport (clk_50Mhz : in std_logic;rst : in std_logic;clk_2Hz : out std_logic);end scale_clock;architecture Behavioral of scale_clock issignal prescaler : unsigned(23 downto 0);signal clk_2Hz_i : std_logic;begingen_clk : process (clk_50Mhz, rst)begin -- process gen_clkif rst = '1' thenclk_2Hz_i <= '0';prescaler <= (others => '0');elsif rising_edge(clk_50Mhz) then -- rising clock edgeif prescaler = X"BEBC20" then -- 12 500 000 in hexprescaler <= (others => '0');clk_2Hz_i <= not clk_2Hz_i;elseprescaler <= prescaler + "1";end if;end if;end process gen_clk;clk_2Hz <= clk_2Hz_i;end Behavioral;I've edited the code for 20Mhz hereCode:library IEEE;use IEEE.STD_LOGIC_1164.all;-- Uncomment the following library declaration if using-- arithmetic functions with Signed or Unsigned valuesuse IEEE.NUMERIC_STD.all;entity scale_clock isport (clk_20Mhz : in std_logic;rst : in std_logic;clk_2Hz : out std_logic);end scale_clock;architecture Behavioral of scale_clock issignal prescaler : unsigned(23 downto 0);signal clk_2Hz_i : std_logic;begingen_clk : process (clk_20Mhz, rst)begin -- process gen_clkif rst = '1' thenclk_2Hz_i <= '0';prescaler <= (others => '0');elsif rising_edge(clk_20Mhz) then -- rising clock edgeif prescaler = X"4C4B40" then -- 5 000 000 in hexprescaler <= (others => '0');clk_2Hz_i <= not clk_2Hz_i;elseprescaler <= 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 linesignal 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.

author: jahonen
author_rank: Super Contributor
timestamp: December 28, 2013, 12:54:14 pm
content: 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

author: djsb
author_rank: Super Contributor
timestamp: December 28, 2013, 06:19:25 pm
content: 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: : 25Flipflops with RESET (Asynchronous) : 24Flipflops with RESET and ENABLE (Synchronous) : 1MacroCells:AND2S : 1INV : 2XORCY : 23MUXCY : 22Area Estimates:Area Estimate (2 Input Gate Count) : 42Area Estimate (LUT Count) : 37I'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.

author: codeboy2k
author_rank: Super Contributor
timestamp: December 28, 2013, 09:37:05 pm
content: Quote from: djsb on December 28, 2013, 06:19:25 pmXORCY 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.QuoteYou 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,00010) 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.

author: djsb
author_rank: Super Contributor
timestamp: December 28, 2013, 10:06:26 pm
content: 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.

author: djsb
author_rank: Super Contributor
timestamp: December 29, 2013, 01:36:51 pm
content: Ok, now I'm going to have a try using the Aldec simulator built into Altium Designer.Here is the automatically created testbenchCode:-------------------------------------------------------------- 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 isend TestTWO_INPUT_AND;------------------------------------------------------------------------------------------------------------------------architecture stimulus of TestTWO_INPUT_AND isfile 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) isvariable l_out : line;beginwrite(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_ANDport (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;beginDUT:TWO_INPUT_AND port map (CLK_BRD => CLK_BRD,LED_R0 => LED_R0,SW_USER0 => SW_USER0,SW_USER1 => SW_USER1);STIMULUS0:processbegin-- 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.

author: jahonen
author_rank: Super Contributor
timestamp: December 29, 2013, 02:15:29 pm
content: Try it like this:Code:STIMULUS0:processbeginSW_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

author: zapta
author_rank: Super Contributor
timestamp: December 29, 2013, 03:51:24 pm
content: Quote from: djsb on December 28, 2013, 12:36:00 pmThis 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.

author: daveatol
author_rank: Regular Contributor
timestamp: December 30, 2013, 01:31:36 am
content: 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.

author: codeboy2k
author_rank: Super Contributor
timestamp: December 30, 2013, 03:26:42 am
content: Quote from: daveatol on December 30, 2013, 01:31:36 amYes, good catch, easy fix.. should be changed to count from 0 to 4,999,999->>> if prescaler = X"4C4B3F" then -- 4 999 999 in hexAlso, OP said:Quote from: djsb on December 28, 2013, 12:36:00 pmThe 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)

author: amyk
author_rank: Super Contributor
timestamp: December 30, 2013, 07:12:42 am
content: I like power-of-2 clock frequencies because it makes division much simpler.

author: codeboy2k
author_rank: Super Contributor
timestamp: December 30, 2013, 09:19:42 am
content: Quote from: amyk on December 30, 2013, 07:12:42 amMe 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.

author: mrflibble
author_rank: Super Contributor
timestamp: December 30, 2013, 10:06:15 am
content: Quote from: codeboy2k on December 30, 2013, 09:19:42 amDitto. 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.

author: djsb
author_rank: Super Contributor
timestamp: December 30, 2013, 10:53:27 am
content: 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.