Immer wieder taucht das Pseudoargument auf, VHDL sei zu "akademisch" und überaus "aufgeplustert" und "geschwätzig". So auch in einem Thread auf mikrocontroller.net: SPLD (GAL) - welche Software. Dort wird auf die Implementierung einer Stoppuhr in Verilog auf simplefpga.blogspot.de Learn Verilog by Example verwisen und impliziert, eine solch kompakte Lösung sei mit VHDL wohl nicht möglich.
Ich habe mich der Sache mal angenommen und die dort vorgestellte Stoppuhr nach VHDL übertragen. Resultat: 90 Zeilen VHDL vs. 140 Zeilen Verilog...
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity stopwatch is Port ( clock : in STD_LOGIC; reset : in STD_LOGIC; start : in STD_LOGIC; segments : out STD_LOGIC_VECTOR (6 downto 0); -- a, b, c, d, e, f, g dp : out STD_LOGIC; an : out STD_LOGIC_VECTOR (3 downto 0)); end stopwatch; architecture Behavioral of stopwatch is -- minutes, ten seconds, seconds, tenth seconds, the current digit signal m, s10, s1, st, digit : integer range 0 to 9 := 0; -- divides 50MHz to 0.1 sec: 0 to 4999999 are exactly 5000000 clocks signal prescaler : integer range 0 to 4999999 := 0; -- the counter for the multiplexer with automatic overflow signal muxcnt : unsigned (17 downto 0) := (others=>'0'); begin -- the stopwatch process begin wait until rising_edge(clock); if prescaler<4999999 then -- count a tenth second if start = '1' then -- but only if enabled prescaler <= prescaler+1; end if; else prescaler <= 0; if st=9 then st <= 0; if s1=9 then s1 <= 0; if s10=5 then s10 <= 0; if m=9 then m <= 0; else m <= m+1; end if; else s10 <= s10+1; end if; else s1 <= s1+1; end if; else st <= st+1; end if; end if; if reset = '1' then -- last assignment in process "wins" prescaler <= 0; -- -->reset has priority st <= 0; s1 <= 0; s10 <= 0; m <= 0; end if; end process; -- the muxer process begin wait until rising_edge(clock); muxcnt <= muxcnt+1; case muxcnt(17 downto 16) is when "00" => digit <= st; an <= "1110"; dp <= '1'; when "01" => digit <= s1; an <= "1101"; dp <= '0'; when "10" => digit <= s10; an <= "1011"; dp <= '1'; when others => digit <= m; an <= "0111"; dp <= '0'; end case; if reset = '1' then -- when in reset an <= "1111"; -- switch off all segments end if; end process; -- the decoder segments <= "1000000" when digit=0 else "1111001" when digit=1 else "0100100" when digit=2 else "0110000" when digit=3 else "0011001" when digit=4 else "0010010" when digit=5 else "0000010" when digit=6 else "1111000" when digit=7 else "0000000" when digit=8 else "0010000" when digit=9 else "0111111"; -- is a dash, but will hopefully never be used! end Behavioral;
Und dazu dann noch die Portierung des Stimuligenerators (Testbench kann man das eigentlich nicht nennen, es fehlen die Testvektoren und automatisierte Vergleich):
LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY tb_stopwatch IS END tb_stopwatch; ARCHITECTURE behavior OF tb_stopwatch IS signal clock : std_logic := '0'; signal reset : std_logic := '1'; signal start : std_logic := '0'; signal segments : std_logic_vector(6 downto 0); signal dp : std_logic; signal an : std_logic_vector(3 downto 0); BEGIN uut: entity work.stopwatch PORT MAP ( clock => clock, reset => reset, start => start, segments => segments, dp => dp, an => an ); clock <= not clock after 100 ns; stim_proc: process begin wait for 100 ns; reset <= '0'; wait for 100 ns; reset <= '1'; wait for 100 ns; reset <= '0'; wait for 100 ns; start <= '1'; wait; end process; END;
Hier noch ein Beispiel, wie man es mit SystemVerilog machen könnte:
mikrocontroller.net: Beitrag "Frage zur Lernkurve VHDL vs. Verilog"