Search code examples
vhdltimingadc

Strange behaviour in VHDL


I'm trying to integrate (sum) a 14-bit signal of ADC at 50 Mhz. The integration starts with rising edge of signal "trigger". If the integral reaches a defined threshold (6000000), a digital signal ("dout") should be set to 0 (which became 1 with "trigger" becoming 1). So far a quite easy task. Though on the hardware itself (Cyclone V) I realized a strange behaviour. Although I kept the voltage level at the ADC constant, the pulse width of the output signal "dout" is sometimes fluctuating (although it should stay nearly constant for a constant 14-bit value at the ADC, which has a low noise). The pulse width is decreasing with rising voltage level, so the integration itself works fine. But it keeps fluctuating.

Here is my code:

library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;

entity integrator is
port(
  trigger:  in std_logic;
  adc:  in std_logic_vector(13 downto 0);
  clk:  in std_logic;
  dout: out std_logic);
end integrator ;

architecture rtl of integrator is
  signal sum : integer;
begin
  process(clk) is
  begin     
        if rising_edge(clk) then                
            if (trigger='1') and (sum<6000000) then
                sum<=sum+to_integer(unsigned(adc));
                dout<='1';
            else
                dout<='0';
                if (trigger='0') then
                    sum<=0;
                end if;
            end if;
        end if;
  end process;
end rtl;

I checked the signals using SignalTab II of Quartus Prime. I realized that the value of "sum" was rising, but not perfectly correct (compared the sum I calculated manually of the values of "adc".

I used a PLL to phase shift the 50 Mhz clock ("clk") about 90 degrees. The resulting clock served as input for the ADC clock. I left out the PLL and the value of "sum" matched. Nonetheless I see fluctuations in the "dout" signal (oscilloscope).

Even more strange: I changed the type of "sum" to unsigned and finally the fluctuations disappeared. But only without using the PLL! But while making adaptations to the code below the fluctuations came back. Maybe the sum of integer and unsigned leaded to another timing?!?

The questions are now: - Why the value of "sum" is incorrect when using PLL (I though the value of "adc" should stay constant for half a clock cycle when phase shifting of 90 degrees)? - Why I see the fluctuations in "dout"? Is there something wrong with the code?

EDIT1: Add testbench

Here is my testbench:

library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;

entity testbench is
end testbench; 

architecture tb of testbench is


component integrator is
port(
  trigger:  in std_logic;
  adc:  in std_logic_vector(13 downto 0);
  clk:  in std_logic;
  dout: out std_logic);
end component;


signal trigger_in, clk_in, dout_out: std_logic;
signal adc_in:  std_logic_vector(13 downto 0);
begin

  DUT: integrator port map(trigger_in, adc_in, clk_in, dout_out);

  process
  begin
    for I in 1 to 4500 loop
      clk_in <= '0';
      wait for 10 ns;
      clk_in <= '1';
      wait for 10 ns;
    end loop; 
    wait;
  end process;

  process
  begin
      trigger_in <= '0';
      wait for 10 us;
      trigger_in <= '1';
      wait for 30 us;
      trigger_in <= '0';
      wait for 10 us;
      trigger_in <= '1';
      wait for 30 us;
      trigger_in <= '0';
      wait for 10 us;
      wait;
  end process;

  process
  begin
      adc_in <= (others => '0');
      wait for 10 us;
      adc_in <= std_logic_vector(to_unsigned(6000, 14));
      wait for 30 us;
      adc_in <= (others => '0');
      wait for 10 us;
      adc_in <= std_logic_vector(to_unsigned(6000, 14));
      wait for 30 us;
      adc_in <= (others => '0');
      wait for 10 us;
      wait;
  end process;


end tb;

And the resulting output: Simultation output


Solution

  • Sorry guys. The problem was a misconfigured Quartus project with wrong