Electronics > Microcontrollers

Dividing 20MHz FPGA clock down to 2Hz

(1/3) > >>

djsb:
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: ---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;

--- End code ---

I've edited the code for 20Mhz here


--- Code: ---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;


--- End code ---

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.

jahonen:
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

djsb:
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.

codeboy2k:

--- Quote from: djsb on December 28, 2013, 06:19:25 pm ---I'm wondering what XORCY and MUXCY are?

--- End quote ---

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.

--- End quote ---
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.

djsb:
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.

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod