Textbasiertes Testing: Aufbau Inputfile

File mit Testwerten

1 00000001 00000001 00000002 0
1 FFFFFFFF FFFFFFFF 00000000 1
2 00000004 00000005 FFFFFFFE 1
2 FFFFFFFF FFFFFFFF 00000000 0

wr_ram 0001 00F1  11
wr_ram 0002 0015  11
wr_rm  0002 F632  10

rd_ram 0001 00F1  99
rd_ram 0002 F615  99

reset 00 00 00 00 00 00 00 00 00
check 00 00 00 00 00 00 00 00 00
singl 13 01 00 00 00 00 00 00 00
check 13 00 00 00 00 00 00 00 00

Die Daten werden entweder als string  mit der Funktion read(<von>,<zu>)  oder als Hex-Zahl hread(<von>,<zu>)  eingelesen (vgl. std_logic_textio.vhd).

Richtige Zahlenwerte eintragen
Weil die Zahlen als Hex interpretiert werden, entspricht eine 0  4 Bits. Und die Zahl 10  entspricht dem dezimalen Wert 15.

Aus diesem Grund enstehen folgende Anzahl Bits:
00  im File    ->      std_logic_vector(7 downto 0)  beim Einlesen in der Testbench
0   im File    ->     std_logic_vector(3 downto 0)
7  im File     ->     std_logic_vector(3 downto 0)
0F5  im File  ->     std_logic_vector(11 downto 0)


Aufbau der Token
Die Token können alle vom selben Datentyp sein und über alle Testtyps die gleiche Struktur beinhalten. Das vereinfacht ihre Verarbeitung.

<Testtyp>  <Wert1>   <Wert2>    <Ergebnis_Addition> <Ueberlaufbit>
1          00000001  00000001   00000002             0

Im zweiten Beispiel hängt die Funktion der Token von dem Testtyp ab.

<Testtyp>  <adress>  <value>   <byte enable>
wr_ram     0001      00F1      11
<Testtyp>  <address>  <result>  <byte enable>
rd_ram     0001       00F1      01

Tipp: Fixe Tokenstruktur mit Auslassungen

singl 14 01 00 00 00 00 00 00 00   // verwerfen
polyp 13 01 14 01 15 01 14 00 02

Zum Decodieren wird es schwer, wenn unterschiedliche Verarbeitungs-Strukturen je nach Testtyp aufgebaut werden müssen.

Zu empfehlen ist, dass alle Test-Werte in einer Linie stehen und beim Verarbeiten gewisse Token verworfen werden.

Umsetzung in VHDL

Metastabilität bei Flip-Flop

Wechselt das Inputsignal eines Flip-Flops zur falschen Zeit, ist das Ausgangssignal unsicher. Im besten Fall nimmt der Ausgang dann einen selbst gewählten Wert an (Q ode Q), im schlechten Fall „hängt“ sich das Flip-Flop „auf“ und toggelt permanent zwischen Q und Q.

Kritische Zeit beim Eingang
t_setup:   so lange müssen Daten vor dem Clock da sein
.                  (3 bis 12 ns. Cyclone IV: 8 – 10 ns)
t_hold:     so lange müssen Daten nach dem Clock anliegen  (0 bis 1 ns)
.                  Diese Zeit muss grösser sein, als die Durchlaufverzögerung des FF.
t_pd:         Durchlaufverzögerung: Zeit der Daten, bis sie am Ausgang anliegen.
kritscheZeit_FF

 

Treffen neue Daten vor der minimalen Haltezeit ein, so ist unklar, was am Ausgang anliegt.

Ursache für das Nichteinhalten der t_su
Die Clk-Frequenz hängt vom längsten Verzögerungspfad ab. Ist der eingestellte CLK schneller, so  kommt bei mindestens einem FF die Daten zu spät an. Die t_su kann dort nicht eingehalten werden.

Warum ist (nur ein) FF  bereits ein Problem?
Weil das FF im schlimmsten Fall zu Toggeln beginnt. Dadurch erhalten alle nachfolgenden FF toggelnde Signale und die ganze Linie ist unbrauchbar.
Ein metastabiles FF zieht die anderen FF mit sich.

Artikel 1

Timing Durchlaufverzögerung t_pd

Durchlaufverzögerung (propagation delay)
Ein Signal am Eingang erscheint (theortisch) direkt Ausgang. Real jedoch hat jedes Signal eine Gatter- oder Flip-Flop-Verzögerung.

Verzögerung bei Logik
Jedes Gatter braucht eine kurze Zeit, um die Logik auszugeben. Diese nennt man Gatter-Verzögerung bzw. auf englisch progagation delay.
delay_gatter
Nimmt man pro Gatter eine Verzögerung von 5 ns, so hat man nach 3 Gattern einen Pfad von 15 ns.

Verzögerung bei Flip-Flop
Auch jedes Flip-Flop hat nach dem Clk noch eine Verzögerung. Das Signal liegt nicht unmittelbar nach dem Clk am Ausgang an.
Durchlaufverzoegerung_FF

Die Verzögerung (t_pd) darf nicht zu lange sein, weil sonst das Signal nicht mehr anliegt. Die Regel ist, dass die Verzögerung küzer sein muss, als die minimale Haltezeit des Signal (t_hold). Bei den Flip-Flops muss zusätzlich noch die Zeit vor dem Clock berücksichtig werden (t_setup). Mehr dazu unter Metastabilität.

 

 

 

VHDL Latch

In Zustand hängen bleiben
Ein Latch ist ein Verharren in einem Zustand (latch = Zuschnappen, Schliessen). Dies geschieht z.B. wenn bei einer switch-case-Struktur nicht alle Fälle abgefragt werden. Trifft ein nicht definierter Fall ein, so verharrt das System in diesem.

Urachen im Code

// kein else nach if
// .................
begin
        if (cnt = 15) then
            pulse <= '1';
        end if;
 end process;
// kein others in case
// ....................
case state is
            when s0 =>   LEDR_0  <= '1';
            when s1 =>   LEDR_1  <= '1'; GPIO_0_0 <= '1';
            when OTHERS =>  LEDG_7 <= '1';
        
    end case;

 

VHDL State Machine One Hot

One Hot
Ist ein VHDL-Endcoding-BEgriff und bezieht sich auf die Umsetzung der Zustände in Hardware.
Bei One Hot wird für jeden Zustand s ein weiteres Bit gebraucht wird bzw. ein neues FF eingebaut.

s1 = 0001    -> 4 Flip-Flop
s2 = 0010
s3 = 0100
s4 = 1000

Der Vorteil von One Hot ist, dass sich die Input-Logik (das Decodieren der Zustände) vereinfacht. Man muss nur 1 Bit kontrollieren.

Minimal Bit Endocding
Ist der Gegenbegriff. Die Zustände werden mit möglichst wenigen Bits in VHDL umgesetzt.

s1 = 00    -> 2 Flip-Flop
s2 = 01
s3 = 10
s4 = 11

Einstellen in quartus
Menu Settings/ Analyse & Synthese/   Klicken auf Feld: More Settings:
Scrollen  bis zum Betriff  State Machine Processing:
Dort unter diversen Optionen One-Hot oder minimal-Bit auswählen

State Machine VHDL

states bitweise definieren

constant s0         : std_logic_vector(2 downto 0) := "000";
constant s1         : std_logic_vector(2 downto 0) := "100";
constant s2         : std_logic_vector(2 downto 0) := "110";
constant s3         : std_logic_vector(2 downto 0) := "011";
constant s4         : std_logic_vector(2 downto 0) := "001";
constant s5         : std_logic_vector(2 downto 0) := "111";

signal state :        std_logic_vector(2 downto 0);
signal next_state:    std_logic_vector(2 downto 0);

states als type

type actual_state is (s0, s1, s2, s3, s4, s5, s6, s7);
        
signal state:          actual_state  := s0;  
signal next_state:     actual_state  ;


Enumeriter Type

type actual_state is (s0, s1, s2, s3);

attribute enum_encoding : string;
attribute enum_encoding of actual_state: type is "00 01 10 11";  

// nicht sicher:     
signal state:          actual_state  := s0;  
signal next_state:     actual_state  ;


State-Zuweisung

fsm: process (all)
    begin
        if (KEY_1 = '0') then
            state <= s0;
        elsif (rising_edge(CLOCK_27)) then
          state <= next_state;
        end if;
    end process;


Logik Events

fsm_input: process (all)        
begin     
    case state is
       when s0 =>
          if(pulse ='1') then
            next_state <= s1;
          else
            next_state <= s0;
          end if;           
       when s1 =>    
          if(pulse ='1') then
             if SW_17 = '1' the
                next_state <= s2;  
             else
                next_state <= s0;
             end if;
          else
             next_state <= s1;
          end if;
       when s2 =>   next_state <= s3;
       when s3 =>   next_state <= s4;
       when s4 =>   next_state <= s5;
       when s5 =>   next_state <= s6;
       when s6 =>   next_state <= s7
       when s7 =>   next_state <= s7;    
    end case;        
 end process;

Output Action

fsm_output: process (all)
begin   
    case state is
            when s0 =>   out     <= "001"; 
            when s1 =>   out     <= "011"; GPIO_0_0 <= '1';
            when s2 =>   LEDR_2  <= '1';
            when s3 =>   LEDR_3  <= '1';
   
            when OTHERS =>   NULL;
      end case;
end process;

 

 

 

Tristate: Pull Up, Pull Down

Tristate ist die Zustandsbezeichnung von digitalen IOs. Diese können den Zustand ‚0‘, ‚1‘ oder (je nach Verdrahtung) ‚Z‘ oder ‚Z‚ sein. Der Grund dafür ist, dass Ausgänge getrieben werden müssen, was Transistoren bedingt. Diese können in der Luft hängen und dadurch den dritten Zustand erzeugen.

Pull up (‚Z‘)
Im Ruhezustand fehlt die Verbindung zu GND, aber die Verbindung zu VCC ist über den Widerstand gegeben.
Pull_up

Im Ruhezustand erhält der Ausgang aufgrund der Verbindung mit VCC einen definierten Zustand:  logisch HIGH.

Pull down (‚Z‚)
Im Ruhezustand erhält die Leitung durch die Verbindung zu GND einen klaren Zustand: Logisch LOW.

Pull_down

 

Tri-State Transistoren treiben Ausgang / Bus

Transistoren vor IO
In der Digitaltechnik müssen IOs getrieben werden. Das heisst, dass der Input nicht „von selbst“ an den Ausgang übertragen wird, sondern nur, verstärkt den Zustand übergeben kann. Dazu dienen Transistoren.

npnbuffr
IO-Logik hat deshalb nicht nur zwei, sondern drei Leitungen zu verwalten (In, Out und enable).

tristate

Zustand des Ausgangs

Durch das Transistoren-Bild sieht man, dass der Output, beim Nichtleiten, vom Rest abgehängt ist.  Aus diesem Grund gibt es in der Digitaltechnik für die IOs den dritten Zustand ‚Z‚, was so viel wie in der Luft hängen bez. hochomig bedeutet.

Diese gute Visualisierung habe ich von folgender Website.