Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Licznik - post-route - pomóżcie znaleźć błąd

Lukee 27 Sty 2009 14:27 1398 18
  • #1 27 Sty 2009 14:27
    Lukee
    Poziom 12  

    Witam,

    Próbuje opisać układ realizujący następujące rzeczy:
    - zlicza impulsy clk do pewnej wartości i później od początku (np. od 0 do 100),
    - jeśli zliczy już wartość 100 na wyjściu jedynka przesuwana jest o jedną pozycję w lewo (count<=count(30 downto 0)&count(31);).

    Ciągle ma problem z tym, aby sygnał wyjściowy nie otrzymywał przypadkowych wartości. Z poprzednich postów wiem, że muszę sygnał wyjściowy zsynchronizować z clk.

    Oto mój opis:

    Code:

    architecture Behavioral of counter is

       signal counter            :    integer range 0 to 100 := 0;
       signal count_next         :    STD_LOGIC_VECTOR(31 downto 0)   :=   (0=>'1', others=>'0');
       signal count_reg          :    STD_LOGIC_VECTOR(31 downto 0);

    begin
       process (clk) is
       begin
          if (rising_edge(clk)) then
             if (counter=100) then
                counter<=0;
                count_next<=count_next(30 downto 0)&count_next(31);
             else
                counter<=counter+1;
             end if;
          end if;
       end process;
       
       process (clk) is
       begin
          if (rising_edge(clk)) then
             count_reg<=count_next;
          end if;
       end process;
       
       count<=count_reg;
       
    end Behavioral;


    Gdzie popełniam błąd (nadal na wyjściu count otrzymuje przypadkowe sygnały) ?

    Dziękuje za pomoc.
    Pozdrawiam
    Łukasz

    -1 18
  • #2 27 Sty 2009 15:30
    _greis_
    Poziom 14  

    1.zapis

    Code:
    signal count_next         :    STD_LOGIC_VECTOR(31 downto 0)   :=   (0=>'1', others=>'0'); 
    
       

    jest zjadliwy podczas symulacji, lecz niesyntezowalny do rzeczywistego układu. wartość po reset'cie sprzętowym jest zazwyczaj zerowana. bezpiecznej jest zadać wartość początkowową wprowadzając globalny sygnał resetu.

    2. sygnał count_next nie wymaga już synchronizacji gdyż jest synchronizowany poprzez count_reg. mozesz go spokojnie wyrzucić na zewnątrz jak instrukcję współbieżną.

    3. zapis:
    Code:
    count_next<=count_next(30 downto 0)&count_next(31); 
    jest brzydki. lepiej pobrać dane o aktualnym stanie z sygnału count_reg.

    -1
  • #3 27 Sty 2009 15:44
    Lukee
    Poziom 12  

    Dobrze zrozumiałem ?

    Code:
    architecture Behavioral of counter is
    

       signal counter            :    integer range 0 to 100 := 0;
       signal count_next         :    STD_LOGIC_VECTOR(31 downto 0);
       signal count_reg          :    STD_LOGIC_VECTOR(31 downto 0);

    begin
       process (reset,clk) is
       begin
          if (reset='1') then
             count_next<=(0=>'1',others=>'0');
          elsif (rising_edge(clk)) then
             if (counter=100) then
                counter<=0;
                count_next<=count_reg(30 downto 0)&count_reg(31);
             else
                counter<=counter+1;
             end if;
          end if;
       end process;
       
       count_reg<=count_next;
       
       count<=count_reg;
       
    end Behavioral;


    Jeszcze opisu nie symulowałem, tylko chciałem się zapytać czy dobrze zrozumiałem Twoje uwagi ?

    Pozdrawiam
    Łukasz

    -1
  • #4 27 Sty 2009 15:53
    _greis_
    Poziom 14  

    prawie dobrze, lecz dalej synchronizuje count_next. chodziło mi o coś takiego:

    Code:

    count_next<= (0=> '1', others => '0') when RST='1' else
    count_reg(30 downto 0)&count_reg(31) when shifter='1' else count_reg;

    shifter jest sygnałem który jest ustawiany przy warunku counter=100. w przeciwnym razie jest zerowany
    całe przypisanie jest współbieżne.

    0
  • #5 27 Sty 2009 16:01
    Lukee
    Poziom 12  

    Poprawiony fragment opisu:

    Code:

    architecture Behavioral of counter is

       signal counter            :    integer range 0 to 100 := 0;
       signal shifter              :    STD_LOGIC;
       signal count_next         :    STD_LOGIC_VECTOR(31 downto 0);
       signal count_reg          :    STD_LOGIC_VECTOR(31 downto 0);

    begin
       process (clk) is
       begin
          if (rising_edge(clk)) then
             if (counter=100) then
                counter<=0;
                shifter<='1';
             else
                counter<=counter+1;
                shifter<='0';
             end if;
          end if;
       end process;
       
       count_next<= (0=> '1', others => '0') when reset='1' else
                    count_reg(30 downto 0)&count_reg(31) when shifter='1' else count_reg;
       
       count_reg<=count_next;
       
       count<=count_reg;
       
    end Behavioral;


    Czy teraz jest wszystko wporządku ?

    Pozdrawiam
    Łukasz

    1
  • #6 27 Sty 2009 16:14
    _greis_
    Poziom 14  

    już jest prawie dobrze :)
    jeszcze brakuje początkowej synchronizacji count_reg i powinno śmigać

    Code:
    process (clk) is 
    
       begin
          if (rising_edge(clk)) then
             count_reg<=count_next;
          end if;
       end process;     

    0
  • #7 27 Sty 2009 16:30
    Lukee
    Poziom 12  

    Teraz pojawia się problem po jednym pełnym obiegu licznika. Czyli jeśli licznik osiągnie wartość 100 i przechodzi do 0. Sygnał shifter przybiera wartość '1' (pierwszy raz ten sygnał osiąga tą wartość) i następuje próba współbieżnego przypisania:

    Code:

       count_next<= (0=> '1', others => '0') when reset='1' else
                    count_reg(30 downto 0)&count_reg(31) when shifter='1' else count_reg;


    Wydaje mi się, że tutaj pojawia się problem, gdyż przez czas trwania shifter='1' będzie następowała próba obracania sygnału count_reg w lewo (w nieskończoność).

    Licznik - post-route - pomóżcie znaleźć błąd

    Pozdrawiam
    Łukasz

    Zamiast wklejać do postu takiego giganta,
    proszę używać funkcji "Dodaj obrazek" - poprawiłem.
    [zumek]

    0
  • #8 27 Sty 2009 16:44
    _greis_
    Poziom 14  

    wszystko jest okey, zapomnieliśmy o paru rzeczach :)
    1.po resecie powinny być ustawiane wszystkie sygnały ( w naszym przypadku brakuje inicjalicaji countera, shiftera i najważniejszczego cnt_reg!)
    2.to co obserwujesz na symulacji jest skutkiem braku przypisania wartośći początkowej dla count_reg'a.

    0
  • #9 27 Sty 2009 16:50
    Lukee
    Poziom 12  

    Tylko, że podana sytuacja nie następuje po resecie, jak widać do momentu przepełnienia licznika wszystko pracuje poprawnie.

    Pozdrawiam
    Łukasz

    0
  • #10 27 Sty 2009 16:53
    _greis_
    Poziom 14  

    brakuje początkowego przypisania (dla potrzeby symulacji :))

    Code:

    signal count_reg         :    STD_LOGIC_VECTOR(31 downto 0)   :=   (others=>'0');

    0
  • #11 27 Sty 2009 17:07
    Lukee
    Poziom 12  

    ModelSim na to ;) :

    ** Error: (vsim-3601) Iteration limit reached at time 0 ps

    A wyjaśnienie na stronie Xilinx'a:

    http://www.xilinx.com/support/answers/19068.htm

    Nadal myślę, że to nie problem nadania wartości początkowej, tylko sposobu w jaki następuje przypisanie współbieżne.

    Pozdrawiam
    Łukasz

    0
  • #12 27 Sty 2009 17:21
    _greis_
    Poziom 14  

    nie jestem w stanie teg sprawdzić, lecz jestem przekonany że to powinno pujść. zweryfikuję to dopiero wieczorem...

    Code:
    architecture Behavioral of counter is 
    

       signal counter            :    integer range 0 to 100 := 0;
       signal shifter              :    STD_LOGIC := '0';
       signal count_next         :    STD_LOGIC_VECTOR(31 downto 0) := (others => '0');
       signal count_reg          :    STD_LOGIC_VECTOR(31 downto 0):= (others => '0');
     

    begin
       process (clk) is
       begin
          if (rising_edge(clk)) then
             if (counter=100) then
                counter<=0;
                shifter<='1';
             else
                counter<=counter+1;
                shifter<='0';
             end if;
          end if;
       end process;

    process (clk) is
       begin
          if (rising_edge(clk)) then
             count_reg<=count_next;
          end if;
       end process;

       
       count_next<= (0=> '1', others => '0') when reset='1' else
                    count_reg(30 downto 0)&count_reg(31) when shifter='1' else count_reg;
           
       count<=count_reg;
       
    end Behavioral;

    0
  • #13 27 Sty 2009 17:29
    Lukee
    Poziom 12  

    Tak działa (tak samo jak opis zamieszczony w pierwszym poscie). Niestety nadal jest głównym problem - przypadkowe wartości przy zmianie wartości sygnału count (symulacja post-route). Te przypadkowe wartości są nie do zaakceptowania :(.

    0
  • #14 27 Sty 2009 17:35
    _greis_
    Poziom 14  

    Code:
    Te przypadkowe wartości są nie do zaakceptowania . 

    wahania rzędu pikosekund są nie do zaakceptowania? dlaczego?
    w normalnym układzie takie szpilki przejdą niezauważalnie.
    w poprzednim topiku'u J.A sugerował ( i miał rację) że jest to stan przejściowy którego nie da się obejść, więc nie szukałbym rozwiązań do iluzorycznych wymgań :)

    0
  • #15 27 Sty 2009 19:33
    Lukee
    Poziom 12  

    J.A napisał, że to stan przejściowy, ale nigdzie nie zaznaczył, że nie można temu przeciwdziałać. Dokładnie co napisał poniżej:

    Cytat:

    chodzi o to, ze przy przejsciu licznika od wartosci np. ff do 100
    przez chwile na wejsciu ukladu porownujacego stan licznika
    i color_B(CONV_INTEGER(pwm_in) moze pojawic sie dowolna
    wartosc miedzy 0 a 1ff, zaleznie od opoznien sciezek i sygnalu
    zegarowego;
    jest to normalne i zwykle [ale nie zawsze] nie jest to grozne,
    jesli akurat w Twoim przypadku nie mozesz zaakceptowac takich
    szpilek, to musisz zmienic pwm_out z sygnalu czysto kombinacyjnego
    na rejestr, czyli zamiast:
    process (counter) is
    napisac:
    process (clk) is
    begin
    if (rising_edge(clk))


    Z pewnych względów chce uniknąć tych zmian sygnałów - pytam czy to możliwe, jeśli tak to jak to zrobić ? :)

    0
  • #16 27 Sty 2009 21:26
    J.A
    Poziom 27  

    Lukee napisał:
    /.../

    dzieki wam przypominam sobie, co dawno temu umialem o vhdl ;);

    na poczatek - to ja nie pojmuje te komplikacje
    z count_reg, count_next, to mi przypomina styl
    pisania fsm, uzywanie go do zwyklego rejestru
    szeregowego wydaje mi sie przesada;
    ja to bym taki kod napisal najprosciej jak sie da
    Code:
    architecture Behavioral of counter is
    

     signal counter     : integer range 0 to 100 := 0;
     signal count_next  : STD_LOGIC_VECTOR(31 downto 0) := (0=>'1', others=>'0');
     
    begin
       process (clk) is
       begin
          if (rising_edge(clk)) then
             if (counter = 100) then
                counter <= 0;
                count_next <= count_next(30 downto 0) & count_next(31);
             else
                counter <= counter + 1;
             end if;
          end if;
       end process;

       count <= count_next;

    end Behavioral;  -- i tyle ...

    no jeszcze trzeba by dodac ten reset, co prawda i ise i quartus
    akceptuja zapis:
    signal count_next : STD_LOGIC_VECTOR(31 downto 0) := (0=>'1', others=>'0');
    i po power on counter_next bedzie mial prawidlowa wartosc, ale
    lepiej sie nie zdawac na uprzejma domyslnosc narzedzia z ktorym
    pracujemy, bo moze kiedys bedziemy kompilowac innym;

    co do chwilowych stanow przejsciowych, to cytat ktory
    przytoczyles dotyczyl innej sprawy;
    tutaj masz sytuacje, ze z zegarem jeden przerzutnik 'gasnie',
    drugi sie zapala, przez moment masz na wyjsciu albo '0',
    albo oba sa '1', zaleznie do ktorego pierwszy dotrze sygnal clk,
    i zaleznie od czasu podrozy sygnalu z wyjscia ff do pinu;
    jedyne co mozesz z tym zrobic, to poprosic ise, by rejestry
    ktore steruja wyjscia, umiescil w celach I/O, wtedy stany przejsciowe
    beda najkrotsze z mozliwych, byc moze niewidoczne w symulacji;
    jak to zrobic w ise nie wiem;
    a tak z ciekawosci - czemu Ci to przeszkadza ?

    J.A

    0
  • #17 27 Sty 2009 21:44
    Lukee
    Poziom 12  

    Zawsze opisywałem moduł tak jak J.A, niestety poprzedni post mnie zbił z tropu i przez chwilę myślałem :), że te przypisania count_reg, count_next coś dadzą, że tak jest poprawnie, etc :). O tym dlaczego mi to tak przeszkadza, może później, jak potestuje :)

    Dziękuje za pomoc i wyjaśnienie pewnych spraw :)

    Pozdrawiam
    Łukasz

    0
  • #18 28 Sty 2009 12:07
    _greis_
    Poziom 14  

    oba rozwiązania są jak najbardziej poprawne. w pierwszym poście pokazałeś kod który jest opisem w tzw. next-state logic, więc moje uwagi dotyczyły twojego kodu.
    w żadnen sposób nie przymuszałem do stosowania tej techniki i w żaden sposób nie sugerowałem że te rozwiązanie jest lepsze :D
    dla mnie opis wygląda o wiele bardziej przejrzyście i logiczniej. a to już są moje subiektywne odczucia :)

    0
  • #19 28 Sty 2009 12:45
    J.A
    Poziom 27  

    _greis_ napisał:
    /.../w żaden sposób nie przymuszałem/.../

    mysle, ze Lukee piszac, ze poprzedni post go zbil z tropu
    mial na mysli moj post z watku o symulacji post&route;

    J.A

    0