1
votes

My VHDL-Code is functionaly correct, in ModelSim every thing works fine. I tested it with many variations and the code is functionaly correct.

But when I put it on the Altera board it displays a "3" on the 7-segment display, but it should show "0". If I put RESET to "1" it breaks completly and displays only a line in the top segment. My Inputs X, CLK, RESET are connected to the switches. LOAD ist connected to a button and DIGIT to the 7-segment display.

It should have a clock signal as I swtich the CLK-switch.

Here my full code:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY seqdec IS
PORT    (   X:          IN      std_logic_vector(15 DOWNTO 0);
            CLK:        IN      std_logic;
            RESET:  IN      std_logic;
            LOAD:       IN      std_logic;
            DIGIT:  OUT std_logic_vector(6 DOWNTO 0) := "1111110";
            Y:          OUT std_logic);
END seqdec;

ARCHITECTURE SEQ OF seqdec IS
TYPE        statetype IS (s0, s1, s2, s3, s4);
SIGNAL  state: statetype:=s0;
SIGNAL  next_state: statetype;
SIGNAL  counter: std_logic_vector(2 DOWNTO 0) :="000" ;
SIGNAL  temp:   std_logic_vector(15 DOWNTO 0):= (OTHERS => '0');
SIGNAL  so:     std_logic := 'U';

-------------------Aktualisierung des Zustandes--------------------------------
    BEGIN
    STATE_AKT: PROCESS (CLK, RESET)
        BEGIN   
            IF RESET = '1' THEN     
                state <= s0;
            ELSIF CLK = '1' AND CLK'event THEN
                state <= next_state ;
            END IF;
        END PROCESS STATE_AKT;

---------------------Counter---------------------------------------------------
    COUNT:  PROCESS (state, RESET)
        BEGIN   
            IF (RESET = '1') THEN   
                counter <= (OTHERS => '0');
            ELSIF (state = s4) THEN
                counter <= counter + '1';
            END IF;
    END PROCESS COUNT;

-------------------PiSo für die Eingabe des zu Prüfenden Vektors---------------
    PISO:       PROCESS (CLK, LOAD, X)
        BEGIN
            IF (LOAD = '1') THEN
                temp(15 DOWNTO 0) <= X(15 DOWNTO 0);
            ELSIF (CLK'event and CLK='1') THEN
                so <= temp(15);
                temp(15 DOWNTO 1) <= temp(14 DOWNTO 0);
                temp(0) <= '0';
            END IF;
        END PROCESS PISO;

-------------------Zustandsabfrage und Berechnung------------------------------
    STATE_CAL: PROCESS (so,state)
        BEGIN

            next_state <= state;
            Y <= '0';

            CASE state IS
                WHEN s0 =>  
                    IF so = '1' THEN 
                        next_state <= s0  ;
                    END IF;

                WHEN s1 =>  
                    IF so = '1' THEN 
                        next_state <= s1;
                    END IF;

                WHEN s2 =>  
                    IF so = '0' THEN 
                        next_state <= s3 ;
                    END IF;

                WHEN s3 =>  
                    IF so = '0' THEN 
                        next_state <= s0 ;
                    ELSE
                        next_state <= s4 ;
                    END IF;

                WHEN s4 =>  
                    Y <= '1';
                    IF so = '0' THEN 
                        next_state <= s0;
                    ELSE
                        next_state <= s2 ;
                    END IF;

                WHEN OTHERS => NULL;
            END CASE;
        END PROCESS STATE_CAL;

-------------------7 Segment---------------------------------------------------
    SEVEN_SEG: PROCESS (counter)
        BEGIN
            CASE counter IS
                WHEN "000" => DIGIT <= "1111110";
                WHEN "001" => DIGIT <= "0110000";
                WHEN "010" => DIGIT <= "1101101";
                WHEN "011" => DIGIT <= "1111001";
                WHEN "100" => DIGIT <= "0110011";
                WHEN "101" => DIGIT <= "1011011";
                WHEN OTHERS => NULL;
            END CASE;
        END PROCESS SEVEN_SEG;


END SEQ;

I am pretty new to VHDL and am pretty sure it hase to do something with the timings, cause the functional part should be fine, as already said.

Hope for some hints, tips or even solutions.

EDIT: new code without LOAD, is this a valid idea? (non the less the whole code is not working on the FPGA....)

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY seqdec IS
PORT    (   X:          IN      std_logic_vector(15 DOWNTO 0);
            CLK:        IN      std_logic;
            RESET:  IN      std_logic;
            LOAD:       IN      std_logic;
            DIGIT:  OUT std_logic_vector(0 TO 6) := "0000001";
            Y:          OUT std_logic);
END seqdec;

ARCHITECTURE SEQ OF seqdec IS
TYPE        statetype IS (s0, s1, s2, s3, s4);
SIGNAL  state: statetype:=s0;
SIGNAL  next_state: statetype;
SIGNAL  counter: std_logic_vector(2 DOWNTO 0) :="000" ;
SIGNAL  temp:   std_logic_vector(15 DOWNTO 0):= (OTHERS => '0');
SIGNAL  so:     std_logic := 'U';

-------------------Aktualisierung des Zustandes--------------------------------
    BEGIN
    STATE_AKT: PROCESS (CLK, RESET)
        BEGIN   
            IF RESET = '1' THEN     
                state <= s0;
            ELSIF CLK = '1' AND CLK'event THEN
                state <= next_state ;
            END IF;
        END PROCESS STATE_AKT;

---------------------Counter---------------------------------------------------
    COUNT:  PROCESS (state, RESET)
        BEGIN   
            IF (RESET = '1') THEN   
                counter <= (OTHERS => '0');
            ELSIF (state = s4) THEN
                counter <= counter + '1'; 
            END IF;
    END PROCESS COUNT;

-------------------PiSo für die Eingabe des zu Prüfenden Vektors---------------
    PISO:       PROCESS (CLK, LOAD, X)
        BEGIN
            IF (CLK'event and CLK='1') THEN 
                IF (LOAD = '1') THEN 
                    temp(15 DOWNTO 0) <= X(15 DOWNTO 0);
                ELSE
                    so <= temp(15);
                    temp(15 DOWNTO 1) <= temp(14 DOWNTO 0);
                    temp(0) <= '0';
                END IF;
            END IF;
        END PROCESS PISO;

-------------------Zustandsabfrage und Berechnung------------------------------
    STATE_CAL: PROCESS (so,state)
        BEGIN

            next_state <= state;
            Y <= '0';

            CASE state IS
                WHEN s0 =>  
                    IF so = '1' THEN 
                        next_state <= s1  ;
                    END IF;

                WHEN s1 =>  
                    IF so = '1' THEN 
                        next_state <= s2;
                    END IF;

                WHEN s2 =>  
                    IF so = '0' THEN 
                        next_state <= s3 ;
                    END IF;

                WHEN s3 =>  
                    IF so = '0' THEN 
                        next_state <= s0 ;
                    ELSE
                        next_state <= s4 ;
                    END IF;

                WHEN s4 =>  
                    Y <= '1';
                    IF so = '0' THEN 
                        next_state <= s0;
                    ELSE
                        next_state <= s2 ;
                    END IF;

                WHEN OTHERS => NULL;
            END CASE;
        END PROCESS STATE_CAL;

-------------------7 Segment---------------------------------------------------
    SEVEN_SEG: PROCESS (counter)
        BEGIN
            CASE counter IS
                WHEN "000" => DIGIT <= "0000001";
                WHEN "001" => DIGIT <= "1001111";
                WHEN "010" => DIGIT <= "0010010";
                WHEN "011" => DIGIT <= "0000110";
                WHEN "100" => DIGIT <= "1001100";
                WHEN "101" => DIGIT <= "0100100";
                WHEN OTHERS => DIGIT <= "0000001";
            END CASE;
        END PROCESS SEVEN_SEG;


END SEQ;

EDIT: This is now my version. It will still show a "0" no matter what I do.

  • I would assume it has to do with the COUNT and counter.
  • should i realize this as synchronous too?
  • Is the numeric and unsigned really that big of a problem? We did it that way at university.
  • And will it work when i put LOAD onto a slide switch???

Best regards Adrian

2
I added an FSM example which combines two of your processes - Paebbels

2 Answers

3
votes

Your code has several problems. Btw. a running simulation does not mean your design is correct, because you can simulate actions which can not be implemented in hardware.

Here is a list of problems:

  • You can not use a switch button as a clock signal. Buttons are no clock source! Either you implement a signal cleanup circuit (at least a debounce circuit, which requires another clock) or you use you clk signal as an enable.
  • Moreover, each of your signals needs a debounce circuit if connected to external switch buttons or toggle buttons unless your test board has debounced buttons...
  • Your state machine has an init state (that's OK), but you must assign the state to state instead of next_state.
  • Your code uses std_logic_unsigned, which is obsolete. You should use numeric_std and the type unsigned for your counter signal.
  • Your code intoduces an additional register for COUT is this intended?
  • Your PISO process uses an asynchronous LOAD signal this is not supported in hardware (assuming an FPGA as target device).
  • Depending on your synthesis tool it's possible that it will not recognize a FSM because your case statement does not fit the pattern for FSMs.
  • Seeing a fixed output pattern can be causes by an FSM fault. If your synthesizer recognizes a FSM, you can go to the state diagram and identify false edges or false terminal states.

More ...

  • Your 7-segment decoder is a combinatorical process. It can not be reset.
  • Moreover, this process is not sensitive to CLK, just to counter. This cause a mismatch between simulation and hardware. (Synthesis ignores sensitivity lists)

If you fix this, your simulation should have another behavior and, if fixed, work as your hardware :).

The FSM

STATE_CAL : process(state, so)
begin
  -- Standardzuweisungen
  next_state  <= state;  -- Bleib im Zustand falls in CASE nichts abweichendes bestimmt wird
  Y <= '0';

  -- Zustandswechsel
  CASE state IS
    WHEN s0 =>
      IF (so = '1' THEN 
        next_state <= s1;
      END IF;

     WHEN s1 =>
       IF (so = '1') THEN
         next_state <= s2;
       END IF;

     WHEN s2 =>
       IF (so = '0') THEN
         next_state <= s3;
       END IF;

     WHEN s3 =>
       IF (so = '0') THEN
         next_state <= s0;
       else
         next_state <= s4;
       END IF;

     WHEN s4 =>
       Y <= '1'; -- Moore-Ausgabe
       IF (so = '0') THEN
         next_state <= s0;
       else
         next_state <= s2;
       END IF;

  END CASE;
END PROCESS;
1
votes

Paebbels already described many issues of your code. Please check also the warnings of your synthesis tool. They often indicate where the synthesizer actually outputs different logic than you have described in VHDL.

I suspect you have made another two mistakes which are not directly related to VHDL:

  • Your 7-segment display control lines seem to be low-active because you see only one active segment when you press RESET. This matches the only zero in the vector "1111110" you assigned in this case (via reseting counter to "000").
  • But even in this case, the enlighted segment should be in the middle instead on the top. Thus, your pin assignments seem to be in the reverse order.