2017-06-08 4 views
2

Ich versuche, einen Zähler zu bilden, der bis 3 zählt und dann auf 0 usw. zählt. Beispiel: 0 1 2 3 2 1 0 1 2 3 2 1 0 ...VHDL Aufwärts-/Abwärtszähler Fehlerzählung

Was ich tat:

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
use IEEE.STD_LOGIC_ARITH.ALL; 
use IEEE.STD_LOGIC_UNSIGNED.ALL; 

entity Counter is 
    port(
    Clock: in std_logic; 
    Reset: in std_logic; 
    Output: out std_logic_vector(0 to 1)); 
end Counter; 

architecture Behavioral of Counter is 
    signal temp: std_logic_vector(0 to 1); 
    signal down: std_logic := '0'; 
begin process(Clock,Reset) 
    begin 
     if Reset='0' then 
     temp <= "00"; 
     down<= '0'; 
     elsif(rising_edge(Clock)) then 
      if temp="11" then 
       down<= '1'; 
      elsif temp="00" then 
       down<='0'; 
      end if; 

      if down='0' then 
       temp <= temp +1; 
      else 
       temp <= temp-1; 
      end if; 

     end if; 
    end process; 
    Output <= temp; 
end Behavioral; 

Irgendwie ist der Ausgang 3-0 gehen wird, ohne dass die mittleren Zahlen zu zeigen .. Was ist falsch?

+1

vielleicht ist es überläuft eher als herunterzählen. Haben Sie "down" als Variable und nicht als Signal betrachtet und verwenden Sie daher ': =' (unmittelbare Zuweisung) statt '<=' (Zustand bei nächster Zeit)? – diginoise

+2

Seltsam, dass Sie std_logic_vector etwas hinzufügen können. Welches Werkzeug benutzen Sie? Und es ist genau so, wie @Diginoise sagte. Wenn 'temp =" 11 "' Sie 'down <= '1'zuweisen, geschieht dies nach dem Ende des Prozesses. Es ist also immer noch "0", wenn es eingecheckt ist, wenn down = "0" dann ". Deshalb überläuft es. Gleiches in der entgegengesetzten Richtung. – Staszek

+1

@Staszek Sie verwenden das Legacy-Paket std_logic_unsigned. –

Antwort

4

Sie suchen nicht alle Signale: siehe down, um zu sehen, was passiert. Weil Sie getakteten/synchrone Logik verwenden, wird down im Taktzyklus geändert, wo temp 3 erkannt wird, so wird es Wirkung einen Taktzyklus später haben. I.e. wenn temp 3, wird down noch 0 sein, wodurch (3 + 1) mod 4 = 0.

Eine mögliche Lösung ist, einen Schritt voraus davon zu sein: Ändern downein Taktzyklus früher ... wenn temp = 2.

Ein weiteres Problem besteht darin, dass Sie die nicht standardisierten Pakete STD_LOGIC_ARITH und STD_LOGIC_UNSIGNED mit Logikfeldern in umgekehrter Richtung kombinieren. Das kann zu unvorhersehbaren Ergebnissen führen. Bitte verwenden Sie standardisierte Pakete. Beispiel:

library ieee; 
use ieee.STD_LOGIC_1164.ALL; 

entity counter is 
    port(
     clk : in std_logic; 
     rst_n : in std_logic; 
     output : out std_logic_vector(1 downto 0) 
    ); 
end entity; 

architecture behavioral of counter is 
    use ieee.numeric_std.ALL; 
    signal temp : unsigned(output'range) := (others => '0'); 
    signal down : std_logic := '0'; 
begin 
    process(clk, rst_n) 
    begin 
     if rst_n = '0' then -- why asynchronous reset?? 
      temp <= (others => '0'); 
      down <= '0'; 
     elsif(rising_edge(clk)) then 
      if temp = 2 then 
       down <= '1'; 
      elsif temp = 1 then 
       down <= '0'; 
      end if; 
      if down = '0' then 
       temp <= temp + 1; 
      else 
       temp <= temp - 1; 
      end if; 
     end if; 
    end process; 
    output <= std_logic_vector(temp); 
end architecture; 

-

entity counter_tb is end entity; 

library ieee; 
use IEEE.STD_LOGIC_1164.ALL; 

architecture behavioral of counter_tb is 
    signal clk : std_logic; 
    signal rst_n : std_logic; 
    signal output : std_logic_vector(1 downto 0); 
begin 
    DUT: entity work.Counter 
     port map(
      clk => clk, 
      rst_n => rst_n, 
      output => output 
     ); 

    rst_n <= '1'; 
    process 
    begin 
     clk <= '0', '1' after 1 ns; 
     wait for 2 ns; 
    end process; 
end architecture; 

Der nächste Mal fügen Sie bitte Ihren Prüfstand einen kompletten Satz zu bilden ... und bitte nicht 3-Raum-Einzug verwenden :(4 verwenden, wie alle tut)

+0

Das hat funktioniert! es war überfüllt –