Prescalable counter

Hi everyone..

I wonder how to build a prescaled counter! That is a counter that can be prescaled by fx. a factor 1.000.000 or less!

Any nice ideas how to do this?

Thanks Preben

Reply to
Preben Holm
Loading thread data ...

Hi,

When using Xilinx, the SRL16 is a very good candidate for prescaler implementation.

Göran

Preben Holm wrote:

Reply to
Göran Bilski

Prescalers are mostly used to increase the max frequency resolution. What is it you are after? Peter Alfke

Reply to
Peter Alfke

what is this counter for?

Reply to
Vladislav Muravin

It is supposed to be a candidate for doing sampling on signals and therefore addressing memory at a "high" speed!

Thanks

Reply to
Preben Holm

In which way would you use this shift register LUT for prescaler implementation!

Reply to
Preben Holm

Preben, it's a deal: You tell us no details, we give you no advice. That's what you seem to want. Peter Alfke

Reply to
Peter Alfke

I would like to give you guys details... I just don't have the "home-cooked" code on this computer!

And I don't think I can say a lot more (not because I don't will, but because my english stinks and because I can't explain it any better).

I need to address memory at different speeds. Therefore I need to be able to prescale. I need to address the memory at the same intervals to be able to save data. The data comes from an analog-to-digital converter that should sample different data's with regular intervals (namely at the same speed of the counter).

The whole idea is to build the sampling part of an digital oscilloscope. This should include sampling, triggering as in an digital storage oscilloscope.

For any further details please ask again! Maybe I forget that I haven't told you what I'm trying to build in details, but I myself don't even know all the details (as I just started the project)!

Thanks for helping!

Reply to
Preben Holm

Preben, your English is ok, better than my limited Danish. You want to build a sampling scope (so do I). You must start with the A/D vonverter, for that's where most of you money goes. That determines the sampling rate = clock, and you must have low jitter! The rest is not too complicated. You can use on-chip BlockRAM, but you need an interface to external DRAM ( cheap and easily available). I suppose you move all the display and human interface problems onto the PC (that's what I would do). Saves you a lot of work and assures good looks. Now, designig a counter should be the least of your problems... Or, to put it differently: If you have problems with a counter, this project is too big for you. Do something simpler. Good luck. Hilsen Peter Alfke

Reply to
Peter Alfke

For that, you need 1:2:5:10:20:50:100 for the best human friendly timebase (rather than a long binary counter).

You can code as above, with taps, and a single MUX, or you could have a first stage that can select a choice of divide by /1/2/5/10, as a clock enable into following cascaded /10 stages that select

10/100/1000/10000 etc.

If you were being 'register frugal', (eg using a CPLD), then the first stage of /1/2/5/10/20/50 is 6 bits wide, and follow that with a number of /100 cascades [7 bits]

The output of this divider chain would be conditioned to be one clock wide, and feed as ClkEnable into the simple binary-memory scanning/loading counter - the scanner counter needs a trigger state engine to Start on Signal trigger, and stop at MAX (or sooner if set).

-jg

Reply to
Jim Granville

Hi,

SRL16 is a 16 deep shift-register and if you clock in a '1' it will take 16 clock before it appears on the output. If you connect the output to the input and initialize the SRL16 with "0001" you will have a counter which have an output to '1' every 16 clock cycle.

Now if you take that output and connect to another SRL16 clock enable input. The second SRL16 will also have "0001" as the init value. The output of this SRL16 will change every 16 clock cycles and the output will be high for 16 clock cycles and low for 240 clock cycles. If we clean this output to only be high for 1 clock cycle and low for 255 cycles, we can chain these SRL16 together to create any size of prescalers. The cleaning is simple and uses only 2 DFF.

Now this will create a 8-bit prescaler using 2 LUTs and 2 DFFs.

To count other values than 2^n is also possible. Each SRL16 has a 4-bit input value which determines the length of the shift register. The above used all '1' which would delay the input signal 16 clock cycles.

ex. To have a prescaler of 1404, we need to find values between 1-16 than this number can be built from. In this case 12*13*9 = 1404 So we need 3 SRL16, with values of 11,12,8

Some values can be broken into smaller pieces like prime numbers. These values can't use SRL16 as a prescaler.

I have used this for creating baudrate generators and I have attached some VHDL code which will automate this process. It also have some extra features.

  1. When doing baudrate generators, the prescaler doesn't have to be exact. UART allows some skews. I have added this as a parameter to the baudrate module. The VHDL code will search for good SRL16 numbers around the requested prescaler numbers within the skew limits.

  1. If the VHDL code, can't find any good SRL16 values, it will automatically fall back to a standard n-bit counter which always works but it's larger.

  2. Since this was used for a UART baudrate, it can also have a dynamic baudrate but then it uses a standard counter since the baudrate needs to change dynamically. It could use SRL16 since UART baudrates normally is a multiply of each other. I can add one extra SRL16 which would create 1-16x multiply of the lowest baudrate. I will probably add this sometimes.

This code is a good example of the strength of VHDL.

If you only need small prescaler values, the saving is not that much but it will save some logic for large values.

Göran

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

-- $Id$

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

-- divide_part.vhd - Entity and architecture

--

-- ***************************************************************************

-- ** Copyright(C) 2005 by Xilinx, Inc. All rights reserved. **

-- ** **

-- ** This text contains proprietary, confidential **

-- ** information of Xilinx, Inc. , is distributed by **

-- ** under license from Xilinx, Inc., and may be used, **

-- ** copied and/or disclosed only pursuant to the terms **

-- ** of a valid license agreement with Xilinx, Inc. **

-- ** **

-- ** Unmodified source code is guaranteed to place and route, **

-- ** function and run at speed according to the datasheet **

-- ** specification. Source code is provided "as-is", with no **

-- ** obligation on the part of Xilinx to provide support. **

-- ** **

-- ** Xilinx Hotline support of source code IP shall only include **

-- ** standard level Xilinx Hotline support, and will only address **

-- ** issues and questions related to the standard released Netlist **

-- ** version of the core (and thus indirectly, the original core source). **

-- ** **

-- ** The Xilinx Support Hotline does not have access to source **

-- ** code and therefore cannot answer specific questions related **

-- ** to source HDL. The Xilinx Support Hotline will only be able **

-- ** to confirm the problem in the Netlist version of the core. **

-- ** **

-- ** This copyright and support notice must be retained as part **

-- ** of this text at all times. **

-- ***************************************************************************

--

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

-- Filename: divide_part.vhd

--

-- Description:

--

-- VHDL-Standard: VHDL'93

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

-- Structure:

-- divide_part.vhd

--

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

-- Author: goran

-- Revision: $Revision$

-- Date: $Date$

--

-- History:

-- goran 2005-02-28 First Version

--

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

-- Naming Conventions:

-- active low signals: "*_n"

-- clock signals: "clk", "clk_div#", "clk_#x"

-- reset signals: "rst", "rst_n"

-- generics: "C_*"

-- user defined types: "*_TYPE"

-- state machine next state: "*_ns"

-- state machine current state: "*_cs"

-- combinatorial signals: "*_com"

-- pipelined or register delay signals: "*_d#"

-- counter signals: "*cnt*"

-- clock enable signals: "*_ce"

-- internal version of output port "*_i"

-- device pins: "*_pin"

-- ports: - Names begin with Uppercase

-- processes: "*_PROCESS"

-- component instantiations: "I_

------------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all;

entity Divide_part is

generic ( Ratio : natural; First : boolean := true );

port ( Clk : in std_logic; Clk_En : in std_logic; Clk_En_Out : out std_logic );

end entity Divide_part;

library unisim; use unisim.all;

library ieee; use ieee.numeric_std.all;

architecture VHDL_RTL of Divide_part is

component SRL16E is -- pragma translate_off generic ( INIT : bit_vector := X"0000"); -- pragma translate_on port ( Q : out std_logic; A0 : in std_logic; A1 : in std_logic; A2 : in std_logic; A3 : in std_logic; CE : in std_logic; Clk : in std_logic; D : in std_logic ); end component SRL16E;

component SRLC16E is -- pragma translate_off generic ( INIT : bit_vector := X"0000"); -- pragma translate_on port ( Q : out std_logic; Q15 : out std_logic; A0 : in std_logic; A1 : in std_logic; A2 : in std_logic; A3 : in std_logic; CE : in std_logic; Clk : in std_logic; D : in std_logic ); end component SRLC16E;

signal loop_Bit : std_logic;

attribute INIT : string;

constant Nr_Of_SRL16 : natural := 1 + ((Ratio-1)/16); constant Last_SRL16_Ratio : natural := ((Ratio-1) mod

16); constant A : std_logic_vector(3 downto 0) := std_logic_vector(to_unsigned(Last_SRL16_Ratio, 4));

signal shifts : std_logic_vector(0 to Nr_Of_SRL16); signal Emptys : std_logic_vector(0 to Nr_Of_SRL16);

begin -- architecture VHDL_RTL

One_SRL16 : if (Nr_Of_SRL16 = 1) generate attribute INIT of SRL16E_I : label is "0001"; begin SRL16E_I : SRL16E -- pragma translate_off generic map ( INIT => X"0001") -- [bit_vector] -- pragma translate_on port map ( CE => Clk_En, -- [in std_logic] D => loop_Bit, -- [in std_logic] Clk => Clk, -- [in std_logic] A0 => A(0), -- [in std_logic] A1 => A(1), -- [in std_logic] A2 => A(2), -- [in std_logic] A3 => A(3), -- [in std_logic] Q => loop_Bit); -- [out std_logic] end generate One_SRL16;

Two_SRL16 : if (Nr_Of_SRL16 = 2) generate attribute INIT of SRLC16E_1 : label is "0001"; attribute INIT of SRL16E_2 : label is "0000"; begin -- The first SRLC16E SRLC16E_1 : SRLC16E -- pragma translate_off generic map ( INIT => X"0001") -- [bit_vector] -- pragma translate_on port map ( CE => Clk_En, -- [in std_logic] D => loop_Bit, -- [in std_logic] Clk => Clk, -- [in std_logic] A0 => '1', -- [in std_logic] A1 => '1', -- [in std_logic] A2 => '1', -- [in std_logic] A3 => '1', -- [in std_logic] Q15 => shifts(1), -- [out std_logic] Q => Emptys(1)); -- [out std_logic]

SRL16E_2 : SRL16E -- pragma translate_off generic map ( INIT => X"0000") -- [bit_vector] -- pragma translate_on port map ( CE => Clk_En, -- [in std_logic] D => shifts(1), -- [in std_logic] Clk => Clk, -- [in std_logic] A0 => A(0), -- [in std_logic] A1 => A(1), -- [in std_logic] A2 => A(2), -- [in std_logic] A3 => A(3), -- [in std_logic] Q => loop_Bit); -- [out std_logic] end generate Two_SRL16;

More_Than_Two : if (Nr_Of_SRL16 > 2) generate attribute INIT of SRLC16E_1 : label is "0001"; attribute INIT of SRL16E_n : label is "0000"; begin

-- The first SRLC16E SRLC16E_1 : SRLC16E -- pragma translate_off generic map ( INIT => X"0001") -- [bit_vector] -- pragma translate_on port map ( CE => Clk_En, -- [in std_logic] D => loop_Bit, -- [in std_logic] Clk => Clk, -- [in std_logic] A0 => '1', -- [in std_logic] A1 => '1', -- [in std_logic] A2 => '1', -- [in std_logic] A3 => '1', -- [in std_logic] Q15 => shifts(1), -- [out std_logic] Q => Emptys(1)); -- [out std_logic]

The_Rest : for I in 2 to Nr_Of_SRL16-2 generate attribute INIT of SRLC16E_I : label is "0000"; begin SRLC16E_I : SRLC16E -- pragma translate_off generic map ( INIT => X"0000") -- [bit_vector] -- pragma translate_on port map ( CE => Clk_En, -- [in std_logic] D => shifts(I-1), -- [in std_logic] Clk => Clk, -- [in std_logic] A0 => '1', -- [in std_logic] A1 => '1', -- [in std_logic] A2 => '1', -- [in std_logic] A3 => '1', -- [in std_logic] Q15 => shifts(I), -- [out std_logic] Q => Emptys(I)); -- [out std_logic]

end generate The_Rest;

-- The last SRL16 SRL16E_n : SRL16E -- pragma translate_off generic map ( INIT => X"0000") -- [bit_vector] -- pragma translate_on port map ( CE => Clk_En, -- [in std_logic] D => shifts(Nr_Of_SRL16-2), -- [in std_logic] Clk => Clk, -- [in std_logic] A0 => A(0), -- [in std_logic] A1 => A(1), -- [in std_logic] A2 => A(2), -- [in std_logic] A3 => A(3), -- [in std_logic] Q => loop_Bit); -- [out std_logic]

end generate More_Than_Two;

----------------------------------------------------------------------------- -- If the SRL16 is the first in a serie then the output is a clean single -- clock pulse ----------------------------------------------------------------------------- Is_First : if (First) generate Clk_En_Out New_Cnt(I), -- [in std_logic] LO => Carry(I+1)); -- [out std_logic]

XORCY_I1 : XORCY port map ( LI => New_Cnt(I), -- [in std_logic] CI => Carry(I), -- [in std_logic] O => Cnt(I)); -- [out std_logic] end generate All_Bits;

Counter : process (Clk) is begin -- process Counter if Clk'event and Clk = '1' then -- rising clock edge Count

Reply to
Göran Bilski

I agree with you on that!

I dont't what you mean by that! What are taps? I only know taps from the DCM's (and I can't see that I can use that for this)

How will you use the MUX? Please sketch some VHDL or components for me so I can see the idea?

The idea is to make the smallest "die", so using only the FPGA and maybe some external RAM.

Reply to
Preben Holm

I already got the A/D converter. It's 8 bit conversion and min. sampling rate is 1MHz and maximum of 100MHz. So I use the highest clock that gives me no problems at the Starter Kit (Spartan 3).

Well, the time planning I made for my project is to last until the end of june where I hope to have build the sampling circuitry with triggering (and pre-triggering).

Yes, it's not the counter, but the prescaling that irritates me.

I read your note xl33_30 about the "unusual clock dividers". The problem for me is, that I need to build a configurable clock-divider and not a "fixed" division.

I could use clock-division since this a nice idea, but also I need the min. sampling rate of 1MHz. The idea could also be to use a FIFO-buffer that just samples at the rate of fx. 50MHz (and prescale the FIFO-counting) and read from the FIFO (dual-port) at a faster or slower rate when the fifo is full!

Reply to
Preben Holm

Preben, I would run the A/D continuously at the fastest rate possible with a "jitter-free" clock. Then, in the digital domain, you can always average or throw away samples to fit your time scale. At the frequencies you are mentioning, you just build a synchronous binary counter and either decode a specific value, and reset, or (my favorite) you detect overflow and synchronously preset to a certain value. I wish you success. Peter Alfke

Reply to
Peter Alfke

That's the idea I've had.

Thanks.. I never thought about a preset value and then detecting overflow - that's a fine idea!

Thanks for helping

Preben

Reply to
Preben Holm

Take a look at some Microcontroller data sheets, for how they implement prescaler Counter Taps + MUX selection. A good example is in the Atmel AT90PWM2 SPI Clock prescaler, Page 182... [This has 3 SFR bits selecting one of 8 Binary weighted taps, via an 8 way MUX]

-jg

Reply to
Jim Granville

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.