Forum: FPGA, VHDL & Co. Modelsim Problem- bidirektionaler Bus


von Daniel (Gast)


Lesenswert?

Hallo Leute,

habe ein Problem bei meiner Simulation mit Modelsim:
Habe einen bidirektionalen Bus (16Bit) der vom I/O-Pad aus mit einem
IBUF16 + IBUFT16 meinen Eingangsbus treibt und meinen Ausgangsbus
arbeitet mittels eines OBUFT16 auf das selbe I/O-PAD.
Wenn ich nun in der Simulation (beide Buffer tristate) irgendwelche
Daten auf den BUS lege, so zeigt mir die Simulation jedoch immer
z-state, obwohl ich sicher Signale auf dem Bus habe. Ich lasse mir
explizit die Signale direkt am (Pad-)Bus anzeigen, also eingansseitig
"vor" den Buffern.
Hier müßte eigentlich das, in der Testbench erzeugt Datum, sichtbar
werden. Es ist aber immer z-State, außer ich enable den Ausgangstreiber
(OBUF). Dann wird der Ausgangsbus sichtbar durchgeschaltet.
Woran mag das liegen und wie kann ich das umgehen?
Danke, Daniel

von Joachim Müller (Gast)


Lesenswert?

Komisch, keine Antwort?
Scheint wohl niemand das Problem zu haben.
Ich jedenfalls habe dasselbe Problem.
Alle Eingangsdaten auf einen Tristatebus, welche ich in der Testbench
erzeuge, werden nur als Z-State dargestellt, also quasi ignoriert.
Bin Anfänger.
Habe das Problem provisorisch umgangen, indem ich den Eingangstreiber
durchschalte und mir die Daten HINTER dem Eingangstreiber anzeigen
lasse.

von Jörn (Gast)


Lesenswert?

Postet mal euren Code bzw. Schaltpläne und macht am besten noch einen
Screenshot vom Modelsim-Wavefenster.

@Daniel: Warum hast du den IBUF und OBUF als Tristate ausgelegt (wenn
ich das richtig verstanden habe)? Es ist wichtig, dass der OBUF
Tristate fähig ist.

Gruß Jörn

von ope (Gast)


Lesenswert?

Welch Ironie: Ich hänge gerade an einem ähnlichen Problem, weshalb ich
(erstmal) keinen neuen Thread aufmache.

Das Problem: Der TB funktioniert für Lese- und Schreib-Operationen
getrennt (jeweils andere sukommentiert), erst wenn ich die im TB
zusammen scharf mache, kollieren die beiden rd/wr Operationen, sprich
es gibt 'nen Kurzen ('X'):
1
entity la_register is
2
   generic (
3
      BIT_WIDTH      : natural   := 16;
4
      ...
5
   port (
6
      rd               : in    std_logic;
7
      wr               : in    std_logic;
8
      address          : in    addr_t;
9
      data             : inout std_logic_vector(BIT_WIDTH-1 downto 0);
10
   ...
11
end entity la_register;
12
13
architecture behaviorial of la_register is
14
begin
15
   ....
16
   translate : process (clk, reset) is
17
   begin    
18
      if (reset = RESET_ACTIVE) then
19
         ....
20
         data                            <= (others => 'Z');
21
      elsif rising_edge(clk) then
22
         if (wr = '1') and (rd = '0') then
23
            case address
24
              ....
25
              a_register <= data;
26
         elsif (rd = '1') and (wr = '0') then
27
            case address
28
               ...
29
               data <= a_register;
30
         else
31
            data <= (others => 'Z');
32
         end if;
33
      end if;
34
   end process translate;
35
end architecture behaviorial;

Habe ich hier irgendwo einen Denkfehler?

Viele Grüße
Olaf

von Jörn (Gast)


Lesenswert?

Hallo Olaf,

wie sieht die TB dazu aus?

Gruß Jörn

von ope (Gast)


Angehängte Dateien:

Lesenswert?

recht harmlos =)  Ich hänge ihn mal komplett ran. In den packages sind
viele Konstanten und Records drinnen. Konstanten sind gross
geschrieben, wie zB. Adressen und Addressoffsets bzw. Bits.

Interessant sind evtl. die trigger records:
1
package pkg_trigger is
2
3
   type pattern_edge_comb_t is (
4
      unknown,
5
      and_comb,
6
      or_comb,
7
      xor_comb);
8
9
   constant LA_HIT_LENGTH : positive := 8;
10
11
   type trigger_cond_t is
12
   record
13
      -- pattern trigger config registers
14
      pattern_value     : la_vector_t;
15
      pattern_mask      : la_vector_t;
16
      -- edge trigger config registers
17
      edge_rising       : la_vector_t;
18
      edge_falling      : la_vector_t;
19
      edge_mask         : la_vector_t;
20
      -- internal trigger extensions
21
      pattern_edge_comb : pattern_edge_comb_t;
22
      length_value      : unsigned(LA_HIT_LENGTH-1 downto 0);
23
      invert            : std_logic;
24
   end record;
25
26
   type trigger_match_t is record -- list what matched
27
      pattern : std_logic;
28
      edge    : std_logic;
29
      length  : std_logic;
30
   end record trigger_match_t;
31
32
   type ext_trigger_cond_t is
33
   record
34
      active_level : std_logic;
35
   end record;
36
   
37
end package pkg_trigger;

Viele Grüße
Olaf

von ope (Gast)


Angehängte Dateien:

Lesenswert?

und hier das komplette file.

von ope (Gast)


Angehängte Dateien:

Lesenswert?

ok, da das Problem anscheinend öfter mal auftaucht, hier ein kurzes Bsp.
wie es funktioniert. Bei meinem TB muss der Wurm also irgendwo noch
versteckt sein. Also ein ganz gewöhlicher, gemeiner und hinterhältiger,
fieser Fehler :/

Viele Grüße
Olaf
1
library ieee;
2
use ieee.std_logic_1164.all;
3
4
entity bus_test is
5
end entity bus_test;
6
7
architecture behaviorial of bus_test is
8
   signal   done       : boolean                         := false;
9
   signal   clk, reset : std_logic                       := '0';
10
   signal   address    : std_logic_vector(7 downto 0);
11
   signal   data       : std_logic_vector(7 downto 0);
12
   signal   my_data    : std_logic_vector(data'range);
13
   signal   rd, wr     : std_logic;
14
   signal   m_register : std_logic_vector(data'range);
15
   constant MY_ADDRESS : std_logic_vector(address'range) :=
16
b"10000000";
17
   constant TST_DATA   : std_logic_vector(data'range)    :=
18
b"10101010";
19
begin
20
21
   clk_proc : process is
22
      constant PERIOD : time := 10 ns;
23
   begin
24
      clk <= '0';
25
      if done then wait; end if;
26
      wait for PERIOD/2;
27
      clk <= '1';
28
      wait for PERIOD/2;
29
   end process clk_proc;
30
31
   rst : reset <= '1', '0' after 15 ns;
32
33
   rdwr_proc : process (clk, reset) is
34
   begin
35
      if (reset = '1') then
36
         data <= (others => 'Z');
37
      elsif rising_edge(clk) then
38
         if (wr = '1') and (rd = '0') then
39
            case address is
40
               when MY_ADDRESS => m_register <= data;
41
               when others     => null;
42
            end case;
43
         elsif (wr = '0') and (rd = '1') then
44
            case address is
45
               when MY_ADDRESS => data <= m_register;
46
               when others     => null;
47
            end case;
48
         else
49
            data <= (others => 'Z');
50
         end if;
51
      end if;
52
   end process rdwr_proc;
53
54
   TB : process
55
      is
56
57
      procedure tic is
58
      begin
59
         wait until rising_edge(clk);
60
      end procedure tic;
61
62
      procedure do_wr is
63
      begin
64
         wr      <= '1';
65
         address <= MY_ADDRESS;
66
         data    <= TST_DATA;
67
         tic;
68
         wr      <= '0';
69
      end procedure do_wr;
70
71
      procedure do_rd is
72
      begin
73
         rd      <= '1';
74
         address <= MY_ADDRESS;
75
         tic;
76
         my_data <= data;
77
         rd      <= '0';
78
      end procedure do_rd;
79
      
80
   begin
81
      my_data <= (others => '0');
82
      rd      <= '0';
83
      wr      <= '0';
84
      wait until (reset = '0');
85
      tic;
86
      tic;
87
88
      do_wr;
89
      tic;
90
      do_rd;
91
      assert (my_data = TST_DATA) report "* shit *" severity error;
92
      tic;
93
      done <= true;
94
95
   end process TB;
96
end architecture behaviorial;

von Jörn (Gast)


Lesenswert?

???

Ich seh in deinem Screenshot nur, dass du mache Signal nicht
initialisierst ('U'). Die Ursache liegt in deinem Design.Die Signal
werden nicht vom Reset in einen definierten Zustand gebracht.

Gruß Jörn

von ope (Gast)


Lesenswert?

das ist richtig, Address-, Datenbus und das Register sind uninitialized.
Im richtigen Design sollten sie einen def. Wert erhalten. Hier werden
sie im Prozess des schreibens/lesens sukzessive mit Werten befüllt. Ich
habe sie extra frei gelassen um die Zuweisung 'augenfällig' zu
bekommen, für die Funktion des rd/wr tut's aber keinen Abbruch (darauf
kam es mir bei dem Testfile an).

Viele Grüße
Olaf

von ope (Gast)


Angehängte Dateien:

Lesenswert?

OK, noch eine Lösung mit mehreren Registern ohne Kollision:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity bus_test is
6
end entity bus_test;
7
8
architecture behaviorial of bus_test is
9
   signal   done        : boolean    := false;
10
   signal   clk, reset  : std_logic  := '0';
11
   signal   address     : unsigned(7 downto 0);
12
   signal   data        : std_logic_vector(7 downto 0);
13
   signal   my_data     : std_logic_vector(data'range);
14
   signal   rd, wr      : std_logic;
15
   constant MY_ADDRESS1 : unsigned(address'range) := b"1000_0000";
16
   constant MY_ADDRESS2 : unsigned(address'range) := b"1001_0000";
17
   constant TST_DATA1   : std_logic_vector(data'range)
18
      := b"10101010";
19
   constant TST_DATA2   : std_logic_vector(data'range)
20
      := b"01010101";
21
begin
22
23
   clk_proc : process is
24
      constant PERIOD : time := 10 ns;
25
   begin
26
      clk <= '0';
27
      if done then wait; end if;
28
      wait for PERIOD/2;
29
      clk <= '1';
30
      wait for PERIOD/2;
31
   end process clk_proc;
32
33
   rst : reset <= '1', '0' after 15 ns;
34
35
   register_set : block is
36
      signal m_register1 : std_logic_vector(data'range);
37
      signal m_register2 : std_logic_vector(data'range);
38
   begin
39
      rdwr_proc : process (clk, reset) is
40
      begin
41
         if (reset = '1') then
42
            data <= (others => 'Z');
43
         elsif rising_edge(clk) then
44
            if (wr = '1') and (rd = '0') then
45
               case address is
46
                  when MY_ADDRESS1 => m_register1 <= data;
47
                  when MY_ADDRESS2 => m_register2 <= data;
48
                  when others      => null;
49
               end case;
50
            elsif (wr = '0') and (rd = '1') then
51
               case address is
52
                  when MY_ADDRESS1 => data <= m_register1;
53
                  when MY_ADDRESS2 => data <= m_register2;
54
                  when others      => null;
55
               end case;
56
            else
57
               data <= (others => 'Z');
58
            end if;
59
         end if;
60
      end process rdwr_proc;
61
   end block register_set;
62
63
   TB : process is
64
      ------------------------------------------
65
      procedure tic is
66
      begin
67
         wait until rising_edge(clk);
68
      end procedure tic;
69
      ------------------------------------------
70
      procedure do_wr (
71
         constant addr : in unsigned;
72
         constant dat  : in std_logic_vector) is
73
      begin
74
         wr      <= '1';
75
         address <= addr;
76
         data    <= dat;
77
         tic;
78
         wr      <= '0';
79
         data    <= (others => 'Z'); 
80
      end procedure do_wr;
81
      ------------------------------------------
82
      procedure do_rd (
83
         constant addr : in  unsigned;
84
         signal   dat  : out std_logic_vector) is
85
      begin
86
         rd      <= '1';
87
         address <= addr;
88
         tic;tic;
89
         dat     <= data;
90
         rd      <= '0';
91
      end procedure do_rd;
92
      ------------------------------------------
93
   begin
94
      my_data <= (others => '0');
95
      rd      <= '0';
96
      wr      <= '0';
97
      address <= (others => '0');
98
      data    <= (others => '0');
99
      wait until (reset = '0');
100
      tic; tic;
101
102
      do_wr(MY_ADDRESS1, TST_DATA1);
103
      do_wr(MY_ADDRESS2, TST_DATA2);
104
105
      do_rd(MY_ADDRESS1, my_data);
106
      do_rd(MY_ADDRESS2, my_data);
107
108
      assert (my_data = TST_DATA1)
109
         report "* missmatch 1 *" severity error;
110
      tic;
111
      assert (my_data = TST_DATA2)
112
         report "* missmatch 2 *" severity error;
113
114
      tic;
115
      done <= true;
116
117
   end process TB;
118
end architecture behaviorial;

Allerdings wird damit die Leserate halbiert. Gibt's einen schnelleren
Weg des Lesens?

Viele Grüße
Olaf

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.