FPGARelated.com
Forums

Counter counting on both clock edges.

Started by Andrew Rogers ●August 28, 2004
I'm trying to produce a square wave clock that is a fifth of the 
frequency of a faster clock. This means that I must use both the falling 
edge and rising of the clock. XST complains "Signal cnt cannot be 
synthesized, bad synchronous description.", I have since learned that I 
can only have one event per process.

How do I produce a counter that counts on both clock edges?

Regards
Andrew



entity div5 is
   port (
     clk : in  std_logic;
     q   : out std_logic);
end div5;

architecture div5_arch of div5 is
   signal cnt : std_logic_vector (2 downto 0) := "000";

begin
   process (clk)
   begin
     if(clk'event and clk = '0')then
       if(cnt = "110") then
         cnt <= "000";
       else
         cnt <= cnt + 1;
       end if;
     end if;
     if(clk'event and clk = '1')then
       if(cnt = "010") then
         cnt <= "100";
       else
         cnt <= cnt;
       end if;
     end if;
   end process;
   q         <= cnt(2);
end div5_arch;

-- 
Spartan3 configuration JTAG download tool for GNU/Linux available from
http://www.rogerstech.co.uk/xc3sprog/

Andrew Rogers wrote:
> > I'm trying to produce a square wave clock that is a fifth of the > frequency of a faster clock. This means that I must use both the falling > edge and rising of the clock. XST complains "Signal cnt cannot be > synthesized, bad synchronous description.", I have since learned that I > can only have one event per process. > > How do I produce a counter that counts on both clock edges? > > Regards > Andrew > > entity div5 is > port ( > clk : in std_logic; > q : out std_logic); > end div5; > > architecture div5_arch of div5 is > signal cnt : std_logic_vector (2 downto 0) := "000"; > > begin > process (clk) > begin > if(clk'event and clk = '0')then > if(cnt = "110") then > cnt <= "000"; > else > cnt <= cnt + 1; > end if; > end if; > if(clk'event and clk = '1')then > if(cnt = "010") then > cnt <= "100"; > else > cnt <= cnt; > end if; > end if; > end process; > q <= cnt(2); > end div5_arch;
This program is trying to describe something that can not be built using standard elements found inside an FPGA. Instead of trying to think in VHDL, try thinking in terms of the logic. Forget the code for a moment and figure out what logic would be generated to do what you want. I can think of three ways to do what you want. One is to use a clock that is twice the frequency (generated in a PLL/DLL in the FPGA). Your design is a bit unusual in that you do different things on the rising and falling edges of the original clock. You will need to reference this clock to distinguish the two actions. A second way is to use both a rising edge triggered register and a falling edge register, each a function of the other. Your logic will need to change from what you have above. The third is to use two registers, but one logic path with a MUX in the front to switch registers as required by your function definition. Since this is a very odd function to be implementing as part of a job, I assume it is a homework assignment. So I won't give any more details... But the main idea is to use VHDL to describe your logic... *AFTER* you have figured out what it must be. Don't try to code your problem without having a solution in mind. -- Rick "rickman" Collins rick.collins@XYarius.com Ignore the reply address. To email me use the above address with the XY removed. Arius - A Signal Processing Solutions Company Specializing in DSP and FPGA design URL http://www.arius.com 4 King Ave 301-682-7772 Voice Frederick, MD 21701-3110 301-682-7666 FAX
Hi Andrew
In real hardware the trick is to use a 5-stage shift register with an
inverter between the output of the last stage and the input of the first
stage. This should be easy to implement in VHDL.
Mogens Pelle

"Andrew Rogers" <andrew@_NO_SPAM_rogerstech.co.uk> skrev i en meddelelse
news:4130963b$1_1@127.0.0.1...
> I'm trying to produce a square wave clock that is a fifth of the > frequency of a faster clock. This means that I must use both the falling > edge and rising of the clock. XST complains "Signal cnt cannot be > synthesized, bad synchronous description.", I have since learned that I > can only have one event per process. > > How do I produce a counter that counts on both clock edges? > > Regards > Andrew > > > > entity div5 is > port ( > clk : in std_logic; > q : out std_logic); > end div5; > > architecture div5_arch of div5 is > signal cnt : std_logic_vector (2 downto 0) := "000"; > > begin > process (clk) > begin > if(clk'event and clk = '0')then > if(cnt = "110") then > cnt <= "000"; > else > cnt <= cnt + 1; > end if; > end if; > if(clk'event and clk = '1')then > if(cnt = "010") then > cnt <= "100"; > else > cnt <= cnt; > end if; > end if; > end process; > q <= cnt(2); > end div5_arch; > > -- > Spartan3 configuration JTAG download tool for GNU/Linux available from > http://www.rogerstech.co.uk/xc3sprog/ >
rickman <spamgoeshere4@yahoo.com> wrote in message news:<4130AEF9.BF3AD39D@yahoo.com>...
> Since this is a very odd function to be implementing as part of a job, I > assume it is a homework assignment. So I won't give any more > details...
I see this sort of answer a lot on this forum and, while I agree that we don't need to be doing someone's homework, do we really need to make this sort of statement? It's condescending and really unnecessary. If you don't want to give details, just leave them out. Let's give folks the benefit of the doubt and maybe we won't scare people away. I -have- had to implement this sort of thing as part of a job (more than once, in fact). Another way to do this (depending on what you really need) is to construct a /10 signal, delay it by 2.5 cycles (using a neg-triggered FF) and XOR it with the undelayed version. If the freq. of the input is high enough to allow you to use the on-chip DLL (if you're using an FPGA with one), many DLLs will do a divide-by-5. Jake
"mep" <mpe@metanic.dk> wrote in message
news:4130c30c$0$287$edfadb0f@dread14.news.tele.dk...
> Hi Andrew > In real hardware the trick is to use a 5-stage shift register with an > inverter between the output of the last stage and the input of the first > stage. This should be easy to implement in VHDL. > Mogens Pelle >
Mogens - That gives you a /10, not /5 (assuming you start with all 5 FFs in the same state). But he could use your 5-stage shift register + inverter if he initialized it to "00011". Then delay the shift register output (any stage will work) 1/2 cycle and OR it with the undelayed output to create a 50% duty cycle /5 clock. Without a 2x clock I don't think there's any way to avoid a 1/2 cycle delay someplace plus a gate. Another poster (Jake) suggested a /10 signal delayed 2 1/2 cycles then XORed with the undelayed output. Same idea. RJS
Thanks for all the suggestions, they are valuable ideas that I will use 
for similar problems.

However, I needed a divide by 2.5 in the end. A divide by 5 is simple 
once you have a divide by 2.5. I wrote the following code:

library IEEE;
use IEEE.std_logic_1164.all;            -- defines std_logic types
use IEEE.std_logic_unsigned.all;

--- Divide by 2.5 counter               ---
entity div2p5 is
   port (
     clk : in  std_logic;
     q   : out std_logic);
end div2p5;

architecture div2p5_arch of div2p5 is
   signal cnt0 : std_logic_vector (2 downto 0) := "000";
   signal cnt1 : std_logic_vector (2 downto 0) := "000";
   signal q0   : std_logic;
   signal q1   : std_logic;

begin

   q <= q0 and q1;

   process (clk)
   begin
     if(clk'event and clk = '0')then
       if(cnt1 = "000") then
         q0   <= '1';
       end if;
       if(cnt1 = "100") then
         cnt0 <= "000";
         q0   <= '0';
       else
         cnt0 <= cnt1 + 1;
       end if;
     end if;
   end process;

   process (clk)
   begin
     if(clk'event and clk = '1')then
       cnt1 <= cnt0;
       if(cnt0 = "010")then
         q1 <= '0';
       elsif(cnt0 = "011")then
         q1 <= '1';
       end if;
     end if;
   end process;

end div2p5_arch;
----------------------------

I needed a 20MHz clock on the Xilinx Spartan3 kit which has a 50MHz crystal.

Regards
Andrew
-- 
Spartan3 configuration JTAG download tool for GNU/Linux available from
http://www.rogerstech.co.uk/xc3sprog/

Robert Sefton wrote:

> But he could use your 5-stage shift register + inverter if he initialized it > to "00011". Then delay the shift register output (any stage will work) 1/2 > cycle and OR it with the undelayed output to create a 50% duty cycle /5 > clock.
The shift register gives you a /10 signal, right? I don't see how you generate the 50% duty cycle /5 clock from this by delaying 1/2 cycle and ORing it with undelayed output? Can you elaborate a bit? I think Jake's suggestion makes sense, you generate a /10 clock and delay it 2.5 cycles (in the faster domain) which corresponds to 2.5/10 = 1/4 cycle delay in the slower domain. By XORing two clocks with 1/4 cycle offset you get the double frequency with 50% duty cycle, in this case a /5 clock. -JS-
Jake Janovetz wrote:
> > rickman <spamgoeshere4@yahoo.com> wrote in message news:<4130AEF9.BF3AD39D@yahoo.com>... > > Since this is a very odd function to be implementing as part of a job, I > > assume it is a homework assignment. So I won't give any more > > details... > > I see this sort of answer a lot on this forum and, while I agree that > we don't need to be doing someone's homework, do we really need to > make this sort of statement? It's condescending and really > unnecessary. If you don't want to give details, just leave them out. > Let's give folks the benefit of the doubt and maybe we won't scare > people away.
Condescending it may be, but if I don't explain why I am leaving out details, then he won't be able to correct me if I am wrong. -- Rick "rickman" Collins rick.collins@XYarius.com Ignore the reply address. To email me use the above address with the XY removed. Arius - A Signal Processing Solutions Company Specializing in DSP and FPGA design URL http://www.arius.com 4 King Ave 301-682-7772 Voice Frederick, MD 21701-3110 301-682-7666 FAX
Logically, this will work.  But you don't need two counters, just one
will do.  Like another someone suggested, this algorithm generates two
waveforms, each a divide by five, with a 2.5 clock phase shift.  The
results are ANDed to produce a waveform which is a divide by 2.5. 
Remove cnt0, make everything a function of cnt1 and you will get the
same results.  

Notice that the result will not be square (50%/50% duty cycle).  I
believe this is what was originally requested.  


Andrew Rogers wrote:
> > Thanks for all the suggestions, they are valuable ideas that I will use > for similar problems. > > However, I needed a divide by 2.5 in the end. A divide by 5 is simple > once you have a divide by 2.5. I wrote the following code: > > library IEEE; > use IEEE.std_logic_1164.all; -- defines std_logic types > use IEEE.std_logic_unsigned.all; > > --- Divide by 2.5 counter --- > entity div2p5 is > port ( > clk : in std_logic; > q : out std_logic); > end div2p5; > > architecture div2p5_arch of div2p5 is > signal cnt0 : std_logic_vector (2 downto 0) := "000"; > signal cnt1 : std_logic_vector (2 downto 0) := "000"; > signal q0 : std_logic; > signal q1 : std_logic; > > begin > > q <= q0 and q1; > > process (clk) > begin > if(clk'event and clk = '0')then > if(cnt1 = "000") then > q0 <= '1'; > end if; > if(cnt1 = "100") then > cnt0 <= "000"; > q0 <= '0'; > else > cnt0 <= cnt1 + 1; > end if; > end if; > end process; > > process (clk) > begin > if(clk'event and clk = '1')then > cnt1 <= cnt0; > if(cnt0 = "010")then > q1 <= '0'; > elsif(cnt0 = "011")then > q1 <= '1'; > end if; > end if; > end process; > > end div2p5_arch; > ---------------------------- > > I needed a 20MHz clock on the Xilinx Spartan3 kit which has a 50MHz crystal. > > Regards > Andrew > -- > Spartan3 configuration JTAG download tool for GNU/Linux available from > http://www.rogerstech.co.uk/xc3sprog/
-- Rick "rickman" Collins rick.collins@XYarius.com Ignore the reply address. To email me use the above address with the XY removed. Arius - A Signal Processing Solutions Company Specializing in DSP and FPGA design URL http://www.arius.com 4 King Ave 301-682-7772 Voice Frederick, MD 21701-3110 301-682-7666 FAX
Andrew,

To easiest way generate a 20 Mhz clock signal on the Spartan-3 starter 
kit from the 50 Mhz osc would be to use the DCM.

Is there any reason you have not considered that?

Shalin-

Andrew Rogers wrote:
> Thanks for all the suggestions, they are valuable ideas that I will use > for similar problems. > > However, I needed a divide by 2.5 in the end. A divide by 5 is simple > once you have a divide by 2.5. I wrote the following code: > > library IEEE; > use IEEE.std_logic_1164.all; -- defines std_logic types > use IEEE.std_logic_unsigned.all; > > --- Divide by 2.5 counter --- > entity div2p5 is > port ( > clk : in std_logic; > q : out std_logic); > end div2p5; > > architecture div2p5_arch of div2p5 is > signal cnt0 : std_logic_vector (2 downto 0) := "000"; > signal cnt1 : std_logic_vector (2 downto 0) := "000"; > signal q0 : std_logic; > signal q1 : std_logic; > > begin > > q <= q0 and q1; > > process (clk) > begin > if(clk'event and clk = '0')then > if(cnt1 = "000") then > q0 <= '1'; > end if; > if(cnt1 = "100") then > cnt0 <= "000"; > q0 <= '0'; > else > cnt0 <= cnt1 + 1; > end if; > end if; > end process; > > process (clk) > begin > if(clk'event and clk = '1')then > cnt1 <= cnt0; > if(cnt0 = "010")then > q1 <= '0'; > elsif(cnt0 = "011")then > q1 <= '1'; > end if; > end if; > end process; > > end div2p5_arch; > ---------------------------- > > I needed a 20MHz clock on the Xilinx Spartan3 kit which has a 50MHz > crystal. > > Regards > Andrew