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
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.
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
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
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
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; |
??? 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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.