Forum: FPGA, VHDL & Co. Problem mit Testbench Prozedur


von Thomas (Gast)


Lesenswert?

Hallo,

ich bin grade dabei einen eigentlich simplen Wishbone Adressdekoder zu 
testen und hänge an der Testbench. Einen Teil der wb_write procedure 
habe ich aus bestehendem code von jemandem übernommen, der sich im 
gegensatz zu mir gut mit VHDL auskennt:
1
    process
2
    begin
3
       m0_CLK_I <= '1';
4
       wait for 20 ns;
5
       m0_CLK_I <= '0';
6
       wait for 20 ns;
7
    end process;
8
    
9
10
    process
11
      variable my_line : line;
12
      -- Write to wishbone bus
13
      procedure wb_write (
14
         data   : in std_logic_vector(15 downto 0);
15
         adress : in std_logic_vector(23 downto 0)
16
         ) is
17
      begin
18
         wait until rising_edge(m0_CLK_I);
19
         m0_ADR_I <= adress;
20
         m0_DAT_I <= std_logic_vector(to_unsigned(0,16)) & data;
21
         m0_CYC_I <= '1';
22
         m0_STB_I <= '1';
23
         m0_WE_I  <= '1';
24
         while (m0_ACK_O = '0') loop
25
            wait until rising_edge(m0_CLK_I);
26
         end loop;
27
         m0_CYC_I <= '0';
28
         m0_STB_I <= '0';
29
         return;
30
      end procedure;
31
      
32
      begin
33
        m0_RST_I <= '1';
34
        wait for 100 ns;
35
        m0_RST_I <= '0';
36
        write(my_line, string'("------testing adressrange------"));
37
        writeline(output, my_line);
38
        for i in 0 to 100 loop
39
          write(my_line, string'("  Checking Adress "));
40
          write(my_line, i);
41
          writeline(output, my_line);
42
          wb_write("1010101010101010",std_logic_vector(to_unsigned(i,24)));
43
          wait for 100 ns;
44
        end loop;
45
      wait;
46
    end process;

Das Problem ist, dass das m0_CYC_I und m0_STB_I signal (das zum DUT 
führt) in der procedure wb_write durchgehend 0 bleibt. Die Signale 
werden an keiner anderen Stelle im Code getrieben. Sieht jemand von Euch 
auf die Schnelle, woran das liegt? Wenn noch Code drum herum fehlt, kann 
ich den gern noch hochladen.

Vielen Dank schon mal und einen schönen Abend,

Thomas

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Wird das wait in der Schleife erreicht?
1
         while (m0_ACK_O = '0') loop
2
            wait until rising_edge(m0_CLK_I);
3
         end loop;
Wenn nein, dann sieht der Ablauf nämlich so aus:
1
         m0_CYC_I <= '1';
2
         m0_STB_I <= '1';
3
         m0_WE_I  <= '1';
4
         -- Schleife ausser Funktion, weil nicht aufgerufen
5
         m0_CYC_I <= '0';
6
         m0_STB_I <= '0';
7
         return;
Und dann wird klar, dass die '1' nie auftaucht. Denn Signale werden erst 
beim nächsten wait aktualisiert! Und das kömmt erst nach der Prozedur:
1
  wait for 100 ns;

von Sigi (Gast)


Lesenswert?

Das Problem ist wahrscheinlich eine "Race Condition"-Geschichte:
Du rufst deine Prozedure in 100ns'er Schritten auf, d.h. das

wait until rising_edge(m0_CLK_I);

hat die gleiche Wirkung wie eine NULL-Anweisung und es wird
sofort zum letzten Teil der Prozedur gesprungen. Das Ganze
in einem Prozess macht also den Pegelwechsel "unsichtbar.


P.S. wo wird m0_ACK_O gesetzt (in DUT?)?

von cfgardiner (Gast)


Lesenswert?

probiere mal folgendes:

         wait until rising_edge(m0_CLK_I);
         m0_ADR_I <= adress;
         m0_DAT_I <= std_logic_vector(to_unsigned(0,16)) & data;
         m0_CYC_I <= '1';
         m0_STB_I <= '1';
         m0_WE_I  <= '1';
         wait until rising_edge(m0_CLK_I); -- Neue Zeile !!!!!!
         while (m0_ACK_O = '0') loop
            wait until rising_edge(m0_CLK_I);
         end loop;
         m0_CYC_I <= '0';
         m0_STB_I <= '0';

Ich denke auch, es ist wie der Vorposter gesagt hat. Wenn du wegen 
rising_edge(m0_clk_I) hier hinein läufst und m0_ack_o schon gesetzt ist, 
(wäre nach Wishbone erlaubt, ein spekulatives Ready vom Slave) läufst du 
in die zweite 'Wait' gar nicht hinein. Mit der Änderung, wartest auf 
jeden Fall bis zur nächsten Flanke nach dem setzen von m0_CYC_I und 
zusätzlich weitere Zyklen aber sofern m0_ack_o inaktiv ist.


Viel Erfolg,
Charles

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.