RS-232 Sendemodul

#3456235
Lesenswert?

Hallo allerseits, ich möchte kurz gesagt einen Prozess realisieren, der 
per RS232 Daten versendet. Ich hab also einfach mal drauf los gemacht 
und unten seht ihr was dabei herausgekommen ist. Problem ist jetzt 
folgendes. Wenn ich eine einfache Behavioral Sim mache (ohne 
Testbench-Datei) scheint alles zu funktionieren. Jetzt hab ich mal eine 
Testbench geschrieben, aber alle Ausgänge behalten in der Simulation 
frech einfach ihre Werte, als würde nichts passieren.

Also ich würde mich freuen wenn der ein oder andere mal rüberguckt, 
Tipps oder Vorschläge zum Fehler oder auch allgemeiner Natur hat. Danke 
soweit :)
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5

6

7
entity rs232 is
8
  generic( FTeiler_Vorwahl: natural := 433 );                -- (Takt/BAUD)-1 { (50 MHz/115.200)-1 = 433 }
9
  port(    clk:      in STD_LOGIC;                      -- Basistakt (50 MHz)
10
        Res:      in STD_LOGIC;                      -- Reset
11
        TxD_in:    in STD_LOGIC_VECTOR(7 downto 0);          -- Eingang f. zu sendenden Wert
12
        TxD_Start:  in STD_LOGIC;                      -- Eingang zum Start der Übertragung
13
        TxD:      out STD_LOGIC;                      -- Ausgang TxD
14
        TxD_Busy:  out STD_LOGIC );                    -- Ausgang f. z.B. Sende-LED
15
end rs232;
16

17
architecture Behavioral of rs232 is
18
  signal Intclk: STD_LOGIC := '0';                        -- interner Takt f. Sendeprozess
19
  signal vTxD_Start: STD_LOGIC := '0';                    -- Variable zur Erkennung einer st. Taktflanke
20
  signal BitCount: natural range 0 to 10 := 10;              -- Zählvariable (10 steht für warten)
21
  signal TxD_Buffer: STD_LOGIC_VECTOR(9 downto 0) := "1111111111";  -- Datenpuffer (+ Start- u. Stopbit)
22
begin
23
  
24
  
25
  -- Sendeprozess
26
  Sender:  process(Res, Intclk)
27
          --variable vTxD_Start: STD_LOGIC := '0';                      -- Variable zur Erkennung einer st. Taktflanke
28
          --variable BitCount: natural range 0 to 10 := 10;                -- Zählvariable (10 steht für warten)
29
          --variable TxD_Buffer: STD_LOGIC_VECTOR(9 downto 0) := "1111111111";  -- Datenpuffer (+ Start- u. Stopbit)
30
        begin
31
          
32
          if Res='1' then  -- Reset?
33
          
34
            TxD      <= '1';
35
            TxD_Busy    <= '0';
36
            vTxD_Start  <= '0';
37
            BitCount    <= 10;                    -- 10 steht für warten
38
            TxD_Buffer  <= "1111111111";
39
          
40
          elsif(Intclk'event and Intclk='1') then
41
          
42
            -- steigende Flanke von Start erfassen
43
            if(TxD_Start='1' and vTxD_Start='0') then
44
            
45
              -- Übertragung soll gestartet werden:
46
              -- Zählvariable wird gesetzt und Puffer beschrieben
47
              
48
              BitCount    <= 0;
49
              TxD_Buffer   <= '1' & TxD_in & '0';        -- Stopbit & Datenbits & Startbit
50
              TxD_Busy    <= '1';
51
              
52
            elsif(BitCount < 10) then
53
              
54
              TxD <= TxD_Buffer(BitCount);
55
              
56
              if(BitCount = 9) then
57
                -- letztes Bit gesendet, alles zurücksetzen
58
                
59
                BitCount   <= 10;
60
                TxD_Buffer   <= "1111111111";
61
                TxD_Busy    <= '0';
62
              
63
              else
64
              
65
                BitCount <= BitCount+1;
66
                
67
              end if;
68
            end if;
69
            
70
            vTxD_Start <= TxD_Start;
71
          
72
          end if;
73
        
74
        end process Sender;
75

76
  
77
  -- Frequenzteiler
78
  FTeiler:  process(Res, clk)
79
          variable zaehl: natural range 0 to FTeiler_Vorwahl-1;
80
        begin
81
          if Res='1' then  -- Reset?
82
          
83
            zaehl := FTeiler_Vorwahl-1;
84
            Intclk <= '0';
85
            
86
          elsif(clk'event and clk='1') then
87
          
88
            Intclk <= '0';
89
            if zaehl = 0 then
90
            
91
              zaehl := FTeiler_Vorwahl-1;
92
              
93
            elsif zaehl > (FTeiler_Vorwahl-1)/2 then
94
            
95
              zaehl := zaehl-1;
96
              Intclk <= '1';
97
            
98
            else
99
              
100
              zaehl := zaehl-1;
101
            
102
            end if;
103
          
104
          end if;
105
        end process FTeiler;
106
  
107
end Behavioral;
Gast #3456273
Lesenswert?

Johannes Beyer schrieb:
> Wenn ich eine einfache Behavioral Sim mache (ohne
> Testbench-Datei) scheint alles zu funktionieren.

??? Simulation ohne  Testbench (aka Stimuli) ???


> Jetzt hab ich mal eine
> Testbench geschrieben, aber alle Ausgänge behalten in der Simulation
> frech einfach ihre Werte, als würde nichts passieren.

Mglw. passiert auch nichts in deiner Testbench. Da die Testbench nicht 
vorliegt kann man nichst dazu sagen. Mit welchen Kommandos hast du die 
Simulation gestartet?

Dann sollte man sich mal die Variable zähl anschauen ob sich da was in 
der gewünschten Art und Weise tut.

MfG
#3456288
Lesenswert?

Ohne Testbench, indem ich einfach die Behavorial Simulation, halt ohne 
vorher eine Testbench zu erstellen, starte. Im Simulator muss man dann 
halt alle Signale manuell setzen. Und so funktioniert es scheinbar auch.

Anschließend habe ich folgende Testbench geschrieben. Die Eingänge 
werden in der Simulation auch wie gewünscht gesetzt. Die Ausgänge 
reagieren jetzt aber plötzlich überhaupt nichtmehr..


Testbench:
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
 
4
ENTITY Test_Beh IS
5
END Test_Beh;
6
 
7
ARCHITECTURE behavior OF Test_Beh IS 
8
 
9
    -- Component Declaration for the Unit Under Test (UUT)
10
 
11
    COMPONENT rs232
12
    PORT(
13
         clk : IN  std_logic;
14
         Res : IN  std_logic;
15
         TxD_in : IN  std_logic_vector(7 downto 0);
16
         TxD_Start : IN  std_logic;
17
         TxD : OUT  std_logic;
18
         TxD_Busy : OUT  std_logic
19
        );
20
    END COMPONENT;
21
    
22

23
   --Inputs
24
   signal clk : std_logic := '0';
25
   signal Res : std_logic := '0';
26
   signal TxD_in : std_logic_vector(7 downto 0) := (others => '0');
27
   signal TxD_Start : std_logic := '0';
28

29
   --Outputs
30
   signal TxD : std_logic;
31
   signal TxD_Busy : std_logic;
32

33
   -- Clock period definitions
34
   --constant clk_period : time := 10 ns;
35
 
36
BEGIN
37
 
38
  -- Instantiate the Unit Under Test (UUT)
39
   uut: rs232 PORT MAP (
40
          clk => clk,
41
          Res => Res,
42
          TxD_in => TxD_in,
43
          TxD_Start => TxD_Start,
44
          TxD => TxD,
45
          TxD_Busy => TxD_Busy
46
        );
47

48

49

50
  Res <=  '0', 
51
        '1' after 20 us,
52
        '0' after 21 us;
53
  
54
  
55
  -- Sendedauer (1/115200 = 8.68 us)
56
  TxD_in <=  "11111111",
57
          "00100100" after 1.4 us,
58
          "11011011" after 1.8 us,
59
          "00000000" after 12.1 us,
60
          "10110010" after 22 us,
61
          "11111111" after 25 us;
62
          
63
  TxD_Start <=  '0',
64
            '1' after 1.5 us,
65
            '0' after 1.6 us,
66
            '1' after 10 us,
67
            '0' after 12 us,
68
            '1' after 22.1 us,
69
            '0' after 25 us;
70

71

72
  process
73
  begin
74
    clk <= '0';
75
    wait for 10 ns;
76
    clk <= '1';
77
    wait for 10 ns;
78
  end process;
79

80
   -- Clock process definitions
81
   --clk_process :process
82
   --begin
83
  --  clk <= '0';
84
  --  wait for clk_period/2;
85
  --  clk <= '1';
86
  --  wait for clk_period/2;
87
   --end process;
88
 
89

90
   -- Stimulus process
91
   --stim_proc: process
92
   --begin    
93
      -- hold reset state for 100 ns.
94
      --wait for 100 ns;  
95

96
      --wait for clk_period*10;
97

98
      -- insert stimulus here 
99

100
      --wait;
101
   --end process;
102

103
END;
Gast #3456553
Lesenswert?

Johannes Beyer schrieb:
> Ohne besonderen Grund. Was spricht für ein Signal?

Es ist ein signal. Zaehl ist ein digitaler counter, also ein paar FF mit 
Drähten zur Verteilung der elektrischen Signale. Elektrische Signale 
sind nicht unendlich schnell sondern haben eine gewisse 
Verzögerungszeit. Dementsprechend behandelt sie auch der Simulator, es 
wird nicht nur der Wert simuliert (berechnet) sondern auch das zeitliche 
Verhalten. So wird ein neu berechneter Wert erst am ende eines prozesses 
zugewiesen, bei einer variablen sofort.

Es gibt eine einfache Faustregel für die Verwendung von Variablen:
Benutze keine Variablen!

Wenn man einige Erfahrung hat und VHDL soweit versteht, das man keine 
Faustregeln mehr braucht, dann kann man sie in Testbenches verwenden. 
Wenn Du zaehl für den process kapseln willst, dann schreib das in einen 
Block:

1
architecture abc of xyz is
2
signal something: std_logic;
3
--
4
--in der gesamten architecture sichtbare signale
5
begin
6

7
b_teiler:block is
8
 signal lokaler_zahler: std_logic_vector(7 downto 0);
9
begin
10
 process(clk)
11
 begin
12
 --
13
 end process;
14
end block b_teiler;
15
end architecture;
Gast #3456698
Lesenswert?

du legst erst nach 20us einen Reset an, bis dahin sind Teile deiner 
Signale/Variablen auf einem undefinierten Wert.

Nach dem Reset ist alles in einem definierten Zustand, und du versuchst 
mit IntCLK eine Flankenerkennung auf TXDStart zu machen. IntCLK hat aber 
eine Periode von 8,6µs, der High-Puls auf TXDSTart ist nur 2,9µs lang -> 
du verpasst den Highpuls auf TXDStart uns startest nie den Transmitter. 
Deshalb tut sich nichts an den Ausgängen.

Johannes Beyer schrieb:
> Was spricht für ein Signal?

z.B. dass man bei der Simulation das folgende Problem vermeidet:

WARNING: Simulation object /test_beh/uut/:FTeiler/zaehl was not 
traceable in the design for the following reason:
ISim does not yet support tracing of VHDL variables.

Du kannst dir in einer Simulation nicht nur die Ausgänge sondern auch 
die internen Signale anschauen. Damit verstehst du auch sofort, warum 
sich die Ausgänge in deiner Simulation nicht ändern. (Interne Variablen 
lassen sich hingegen zumindest in meiner ISIM-Version nicht anzeigen.)



Unabhängig von den Simulationsproblemen sollte dir für die Synthese klar 
sein, dass du hier ein Logiksignal als Takt missbrauchst:

Johannes Beyer schrieb:
> elsif(Intclk'event and Intclk='1') then

Das kann beim Betrieb im FPGA alle möglichen unschönen Effekte geben. 
Implementiere sowas als ein Clock Enable, nicht als ein mit Logik 
erzeugtes Taktsignal
Angehängte Dateien:
Moderator (Firma: Titel) Persönliche Seite #3456865
Lesenswert?

Johannes Beyer schrieb:
1
   generic( FTeiler_Vorwahl: natural := 433 ); --  (Takt/BAUD)-1 { (50 MHz/115.200)-1 = 433 }
Lass das doch den Synthesizer rechnen...

> Also ich würde mich freuen wenn der ein oder andere mal rüberguckt,
> Tipps oder Vorschläge ... hat
Sieh dir das mal an:
http://www.lothar-miller.de/s9y/categories/42-RS232

> ich möchte kurz gesagt einen Prozess realisieren, der per RS232 Daten
> versendet.
Das ist eine krude Denkweise. Du kannst Hardware nicht so einfach in 
einzelen Prozesse kapseln. Oft geht das gut, zeimlich oft aber auch 
nicht, und dann stehst du mit dieser "Prozess=Bauteil" Denkweise sauber 
im Regen. Nicht umsonst werden in VHDL ganze Einheiten (entities) als 
Bauteil (components) in anderen Einheiten instantiiert...

Johannes Beyer schrieb:
> Was spricht für ein Signal?
Alles, was gegen eine Variable spricht. Siehe den Klassiker: 
Beitrag "Variable vs Signal"
#3458893
Lesenswert?

Achim S. schrieb:
> Unabhängig von den Simulationsproblemen sollte dir für die Synthese klar
> sein, dass du hier ein Logiksignal als Takt missbrauchst:
>
> Johannes Beyer schrieb:
>> elsif(Intclk'event and Intclk='1') then
>
> Das kann beim Betrieb im FPGA alle möglichen unschönen Effekte geben.
> Implementiere sowas als ein Clock Enable, nicht als ein mit Logik
> erzeugtes Taktsignal

kannst du mir bitte konkret zeigen wie ich das mache?
Gast #3459078
Lesenswert?

Johannes Beyer schrieb:
>> Implementiere sowas als ein Clock Enable, nicht als ein mit Logik
>> erzeugtes Taktsignal
>
> kannst du mir bitte konkret zeigen wie ich das mache?

du findest hier ein Beispiel für die Nutzung eines Clock-Enable Signals:

http://www.mikrocontroller.net/articles/Taktung_FPGA/CPLD

Im Abschnitt "Kombinatorik im Taktpfad" wird auch beschrieben, welche 
Nachteile bisheriger Ansatz hat.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren