Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Counter output not synchronized to clk

neanton28

Newbie level 5
Newbie level 5
Joined
Jul 21, 2024
Messages
8
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
114
Greetings! I am trying to figure out why there is instable output of simple counter. I am using Sipeed Tang Primer 20k development board based on GW2A-LV18PG256C8/I7 FPGA. I created simple project, which uses clock divider to get output clock ~5.5 Mhz from input 27 Mhz global clock.

Top level design counter_tester.vhd looks like this:
1721595105615.png


Code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity counter_tester is
  port(
       CLK_IN_27MHZ : in STD_LOGIC;
       PROCESSOR_RST : in STD_LOGIC;
       BT656_OUT : out STD_LOGIC_VECTOR(7 downto 0);
       BT656_LLC_OUT : out STD_LOGIC
  );
end counter_tester;

architecture counter_tester of counter_tester is

---- Component declarations -----

component Gowin_CLKDIV
  port(
       hclkin : in STD_LOGIC;
       resetn : in STD_LOGIC;
       clkout : out STD_LOGIC
  );
end component;
component my_counter
  port(
       CLK : in STD_LOGIC;
       RST : in STD_LOGIC;
       Q : out STD_LOGIC_VECTOR(7 downto 0)
  );
end component;

---- Signal declarations used on the diagram ----

signal NET672 : STD_LOGIC;
signal NET693 : STD_LOGIC;

begin

----  Component instantiations  ----

U1 : my_counter
  port map(
       CLK => NET672,
       RST => NET693,
       Q => BT656_OUT
  );

NET693 <= not(PROCESSOR_RST);

U4 : Gowin_CLKDIV
  port map(
       hclkin => CLK_IN_27MHZ,
       resetn => PROCESSOR_RST,
       clkout => NET672
  );


---- Terminal assignment ----

    -- Output\buffer terminals
    BT656_LLC_OUT <= NET672;


end counter_tester;


Here is code of counter itself:
Code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity my_counter is
     port(
         CLK : in STD_LOGIC;
         RST : in STD_LOGIC;
         Q : out STD_LOGIC_VECTOR(7 downto 0)
         );
end my_counter;


architecture my_counter of my_counter is
    signal s_Q_OUT: UNSIGNED (7 downto 0);
begin
    Q <= STD_LOGIC_VECTOR(s_Q_OUT);
   
    process( CLK )
    begin
        if (rising_edge(CLK)) then
            if (RST = '1') then
                s_Q_OUT <= (others => '0');
            else
                if(s_Q_OUT = x"FF") then
                    s_Q_OUT <= (others => '0');
                else
                    s_Q_OUT <= s_Q_OUT + 1;
                end if;
            end if;
        end if;
    end process;
end my_counter;

I may also include code of Gowin's generated Clock divider module, but it's nothing interesting in it and it just works:
Code:
--Copyright (C)2014-2024 Gowin Semiconductor Corporation.
--All rights reserved.
--File Title: IP file
--Tool Version: V1.9.9.02
--Part Number: GW2A-LV18PG256C8/I7
--Device: GW2A-18
--Created Time: Sun Jul 21 23:14:25 2024

library IEEE;
use IEEE.std_logic_1164.all;

entity Gowin_CLKDIV is
    port (
        clkout: out std_logic;
        hclkin: in std_logic;
        resetn: in std_logic
    );
end Gowin_CLKDIV;

architecture Behavioral of Gowin_CLKDIV is

    signal gw_gnd: std_logic;

    --component declaration
    component CLKDIV
        generic (
            GSREN: STRING := "false";
            DIV_MODE : STRING := "2"
        );
        port (
            CLKOUT: out std_logic;
            HCLKIN: in std_logic;
            RESETN: in std_logic;
            CALIB: in std_logic
        );
    end component;

begin
    gw_gnd <= '0';

    clkdiv_inst: CLKDIV
        generic map (
            GSREN => "false",
            DIV_MODE => "5"
        )
        port map (
            CLKOUT => clkout,
            HCLKIN => hclkin,
            RESETN => resetn,
            CALIB => gw_gnd
        );

end Behavioral; --Gowin_CLKDIV

All outputs except one pin in FPGA are configured to use same IO bank:
1721595620243.png


I connected logic analyzer which samples on 100 Mhz to output pins. First, this is overall image that we get on DSLogic analyzer. As we can see, counter in general works, bits are incremented:
overall_logic_analyzer.JPG


Now let's zoom in

zoomed_logic.JPG


Here we see that clock frequency is only ~5 Mhz. In decoder settings I choose to decode data on rising edge of clock BT656_LLC_OUT.

But counter quite often misses with output values. Some of data lanes change after 20 ns of clock rising edge. I placed two markers, and in right bottom we can see calculated time difference.

I added colors to each data lane and zoomed it to demonstrate more clearly:
zoomed_colored.JPG


Line D5 changes 0 -> 1 same time as BT656_LLC_OUT changes 0 -> 1
But all other lines change 0 -> 1 only after 20 ns! I find it nonsense. This counter produces too much wrong values on rising edges of clock. Anyone knows what it could be the reason? I am trying to find solution for days...

Here how my dev board is connected with logic analyzer. Board to which probes are connected, is not connected by FFC to other board (ADV7391 coder)
1721597065393.png


I also have set timing constraints in Gowin EDA:
Code:
create_clock -name CLK_IN_27MHZ -period 37.037 -waveform {0 18.518} [get_ports {CLK_IN_27MHZ}] -add


Would be thankful for any help!
 
Synchronous or ripple-plus-swallower / ripple plus early
reset feedback? How is this counter built?

Ripple styles will deliver staggered edges. But whether that's
the deal, can't tell (I'm no good at behavioral digital parsing).
 
This counter is classic synchronous vhdl counter. In my expectations output should increment correctly, like "A1 A2 A3...FF 00" on rising edges, but on real FPGA result is not stable
 
I've simulated cascaded toggle flip-flops in different combinations (ripple counting). I observed that up-counting requires joint negative-going edges at all bits. The same appears to be brought out by your scope traces...

Although I don't know exactly how that invert-gate affects the timing. Certain changes of state must happen at certain times and those certain times depend on whether some other change of state occurs upward-going or downward-going. The particular moment may depend on whether the invert-gate lets half a cycle pass by until a waveform goes upward or downward.
 
I've observed a simulation (when building the 8-bit counter) which needs the invert-gate...
namely when cascading two 4-bit counters. The MSB fm counter #1, feeds the clock in counter #2.

The outputs go through binary-weighted resistors to create the upward ramp wave. Although there are glitches, the steps up the ramp are stable.

8-bit up-ctr fm two 4-bit ctrs (Falstad device) binary wei resis n ramp.png

--- Updated ---

Link below loads schematic above into Falstad's animated interactive simulator at his website, runs it on your computer:

tinyurl.com/26sozu8z

Select 'Toggle full screen' under File menu.
 
Last edited:
This counter is classic synchronous vhdl counter. In my expectations output should increment correctly, like "A1 A2 A3...FF 00" on rising edges, but on real FPGA result is not stable
It basically is. Your decoded output "Parallel" is assigning bit weights incorrectly.
You are also complaining about output bit delay skew. But that's just normal operation of synchronous logic. The big difference is probably caused by insufficient resolution of your logic analyzer.
 
Yes, my main complain is this output bit delay skew. Since clk is quite slow ~5Mhz, I expected all bits to change simultaneously, as it should be in pure vhdl simulations.

Also after creation this topic, I had an idea about adding 8-bit D-register on output which will work on inverted clock - on falling edge. Like this:
1721649764991.png


Code:
library IEEE;
use IEEE.std_logic_1164.all;

entity wide_trigger is
     port(
         clk : in STD_LOGIC;
         LLC_IN : in STD_LOGIC;
         LLC_OUT : out STD_LOGIC;
         DATA_IN_BUS : in STD_LOGIC_VECTOR(7 downto 0);
         DATA_OUT_BUS : out STD_LOGIC_VECTOR(7 downto 0)
         );
end wide_trigger;

--}} End of automatically maintained section

architecture wide_trigger of wide_trigger is
    signal s_DATA_BUS : STD_LOGIC_VECTOR(7 downto 0);
    signal s_LLC : STD_LOGIC;
begin
    DATA_OUT_BUS <= s_DATA_BUS;
    LLC_OUT <= s_LLC;
    
    
    process( clk )
        
    begin
    if ( rising_edge(clk) ) then
        s_DATA_BUS <= DATA_IN_BUS;
        s_LLC <= LLC_IN;
    end if;       
    
    end process;   

     -- enter your statements here --

end wide_trigger;

So I added it and tested with real FPGA. And it was just WOW! No wrong numbers in output, just perfect counter from some digital electronics university book!

And is it normal practice in FPGA design to add additional output register with inverted clk to outputs?
With logic analyzer it's ok, it's sampling frequency is 100 Mhz per channel, so should be enough
 
Hi,
And is it normal practice in FPGA design to add additional output register with inverted clk to outputs?
If you want the outputs to be in sync you have to use registers.

Thus it´s quite standard.

But you talk about "additional" registers. Usually you dont need extra registers when already using registers. For sure you have to be sure to have stable data input when clock is at the active edge. All outputu registers obviously need to run on the same clock edge... from the same clock source.

Klaus
 
I mean, that there are already D-registers for output inside our counter. For scheme without additional register on falling edge like this:
1721652424043.png


GowinEDA produces such RTL:
1721652461084.png


If double click on U1 - my_counter we'll see his internal RTL:
1721652578670.png


And here we can see output dff registers
 
Yes, synchronous counter outputs are already registered. If you understand VHDL, you only nee to look at the code to see this.

Don't believe that real FPGA output has 20 ns output skew.
 

LaTeX Commands Quick-Menu:

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top