Forum: FPGA, VHDL & Co. FTDI 4232 FPGA Serial Kommunikation


von Sabine M. (zizo)


Lesenswert?

Hi,

ich habe ein DE0 Board, ich möchte gern die mit FT 4232 mit PC 
verbinden, von der PC starte ich der Erzeugung der Trigger-Signal, bei 
ein steigende Flanke der Triggersignal wird ein Byte zum PC gesendet.
Ich habe mit dem  Osci die TXD von FPGA kontrolliert. Ich habe 
rausgefunden dass nicht bei jede Triggersignal ein Byte gesendet wird !

Kann jemand mir sagen, was die Fehler ist?

Danke


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity RS232v is
    Generic ( Quarz_Taktfrequenz : integer   := 50000000;  -- Hertz
              Baudrate           : integer   :=  923076      -- Bits/Sec
             );
    Port ( RXD      : in   STD_LOGIC;
           RX_Data  : inout  STD_LOGIC_VECTOR (7 downto 0);
           RX_Busy  : out  STD_LOGIC;
           TXD      : out  STD_LOGIC;
           TX_Data  : in   STD_LOGIC_VECTOR (7 downto 0);
           --TX_Start : in   STD_LOGIC;
           TX_Busy  : out  STD_LOGIC;
           Trigger : out STD_LOGIC;
           CLK      : in   STD_LOGIC
           );
end RS232v;

architecture Behavioral of RS232v is
signal txstart : std_logic := '0';
signal txsr    : std_logic_vector  (9 downto 0) := "1111111111";  -- 
Startbit, 8 Datenbits, Stopbit
signal txbitcnt : integer range 0 to 10 := 10;
signal txcnt    : integer range 0 to (Quarz_Taktfrequenz/Baudrate)-1;
signal TX_Start : std_logic:='0';
signal rxd_sr  : std_logic_vector (3 downto 0) := "1111";         -- 
Flankenerkennung und Eintakten
signal rxsr    : std_logic_vector (7 downto 0) := "00000000";     -- 8 
Datenbits
signal rxbitcnt : integer range 0 to 9 := 9;
signal rxcnt   : integer range 0 to (Quarz_Taktfrequenz/Baudrate)-1;
signal rxdenable : std_logic:='0';
signal LED_STATE0 : std_logic:='0';
signal Enable : std_logic:='0';
begin
   -- Senden
   txd1: process
   begin
      wait until rising_edge(CLK);
      txstart <= TX_Start;
      if (TX_Start='1' and txstart='0') then -- steigende Flanke, los 
gehts
         txcnt    <= 0;                      -- Zähler initialisieren
         txbitcnt <= 0;
         txsr     <= '1' & TX_Data & '0';    -- Stopbit, 8 Datenbits, 
Startbit, rechts gehts los
      else
         if(txcnt<(Quarz_Taktfrequenz/Baudrate)-1) then
            txcnt <= txcnt+1;
         else  -- nächstes Bit ausgeben
            if (txbitcnt<10) then
              txcnt    <= 0;
              txbitcnt <= txbitcnt+1;
              txsr     <= '1' & txsr(txsr'left downto 1);
            end if;
         end if;
      end if;
      --TX_Start<= '0';
   end process txd1;
   TXD     <= txsr(0);  -- LSB first
   TX_Busy <= '1' when (TX_Start='1' or txbitcnt<10) else '0';

   -- Empfangen
   rxd1: process
   begin
      wait until rising_edge(CLK);
      rxd_sr <= rxd_sr(rxd_sr'left-1 downto 0) & RXD;
      if (rxbitcnt<9) then    -- Empfang läuft
         if(rxcnt<(Quarz_Taktfrequenz/Baudrate)-1) then
            rxcnt    <= rxcnt+1;
         else
            rxcnt    <= 0;
            rxbitcnt <= rxbitcnt+1;
            rxsr     <= rxd_sr(rxd_sr'left-1) & rxsr(rxsr'left downto 
1); -- rechts schieben, weil LSB first
              end if;
      else -- warten auf Startbit
         if (rxd_sr(3 downto 2) = "10") then                 -- fallende 
Flanke Startbit
            rxcnt    <= ((Quarz_Taktfrequenz/Baudrate)-1)/2; -- erst mal 
nur halbe Bitzeit abwarten
            rxbitcnt <= 0;
         end if;
      end if;
   end process rxd1;
   RX_Data <= rxsr;
   RX_Busy <= '1' when (rxbitcnt<9) else '0';
   ----RX Daten Auswertung
   senden : process (CLK)
  begin
   if(rising_edge(CLK)) then
    if (RX_Data = "00000001") then
      rxdenable<='1';
    elsif (RX_Data = "00000010") then
      rxdenable<='0';
    end if;

  end if;
  Enable <= rxdenable;
  end process senden;
   --------
   ---------Erzeugung der Trigger/TX_Start für Senden
  test1 : process(CLK)  ----
variable cont : integer :=0;
begin
  if(rising_edge(CLK)and Enable='1') then

      if (cont < 500000) then
      cont := cont + 1 ;
      else
      cont := 0;
      LED_STATE0 <= not LED_STATE0; ---rol 1 ;
      end if;
      TX_Start <=  LED_STATE0;
      Trigger <= LED_STATE0;
  end if;


end process test1;

end Behavioral;

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


Lesenswert?

Sabine Mühller schrieb:
> von der PC starte ich der Erzeugung der Trigger-Signal, bei
> ein steigende Flanke der Triggersignal wird ein Byte zum PC gesendet.
Ich sehe das aber grundlegend anders:
1
  if(rising_edge(CLK)and Enable='1') then
2
3
      if (cont < 500000) then
4
        cont := cont + 1 ;
5
      else
6
        cont := 0;
7
        LED_STATE0 <= not LED_STATE0;
8
      end if;
9
10
      TX_Start <=  LED_STATE0;  ---- Was hat das hier mit einem PC zu tun?   
11
12
      Trigger <= LED_STATE0;
13
  end if;

Du gibst praktisch, sobald Enable='1' ist, nach jeweils 1000000 
Zählerschritten eine steigende Flanke auf TX_Start. Willst du das 
wirklich? Wenn Enable nach 999999 Takten wieder weggeht, wird auch keine 
Flanke auf TX_Start gegeben...  :-o

Sei dir sicher: an meinem RS232-Code liegts nicht, der wird anderweitig 
oft eingesetzt... ;-)

von Sabine M. (zizo)


Lesenswert?

Hi,
Danke für dein Antwort,
kannst du mir erklären wozu

if(txcnt<(Quarz_Taktfrequenz/Baudrate)-1) then
            txcnt <= txcnt+1;

ich möchte jede 10 us ein Byte senden. kannst du mir sagen wie?

S.

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


Lesenswert?

> ich möchte jede 10 us ein Byte senden
Mit einer asynchronen Schittstelle auf 1 MBit/sec? Das ist sportlich...

> kannst du mir erklären wozu
> if(txcnt<(Quarz_Taktfrequenz/Baudrate)-1) then
>            txcnt <= txcnt+1;
Naja, das ist ein Zähler, der den Bittakt (Baudrate) hochzählt. Und 
dafür sind genau soviele Takte nötig: Quarzfrequenz/Baudrate. Und weil 
der Überlauf dazukommt, wird noch eins abgezogen.
Nehmen wir als Beispiel mal das, was du willst: 50MHz und 1MBit/sec. 
Damit darf der Zähler auf (50Mio Takte/s) / 1Mio Bits/s) = 50 
(Takte/Bit) zählen. Das ist dann in der harten Wirklichkeit: 0...49.
Aber wenn du sowieso ein ziemlich knackiges Timing wünschst, dann 
solltest du das Timing besser von Hand berechnen und die Zählerstände 
direkt eintragen....

von Sabine M. (zizo)


Lesenswert?

Hi,
ich habe der Folgende Code gefunden,
kann mir jemand erklären was  COUNTER = (PRESCALE*16)-1 ?



   1.
      ------------------------------------------------------------------------ 
----------
   2.
      -- Company:
   3.
      -- Engineer:
   4.
      --
   5.
      -- Create Date:    16:05:47 06/19/2010
   6.
      -- Design Name:
   7.
      -- Module Name:    CLK_GEN - Behavioral
   8.
      -- Project Name:
   9.
      -- Target Devices:
  10.
      -- Tool versions:
  11.
      -- Description:
  12.
      --
  13.
      -- Dependencies:
  14.
      --
  15.
      -- Revision:
  16.
      -- Revision 0.01 - File Created
  17.
      -- Additional Comments:
  18.
      --
  19.
      ------------------------------------------------------------------------ 
----------
  20.
      library IEEE;
  21.
      use IEEE.STD_LOGIC_1164.ALL;
  22.
      use IEEE.STD_LOGIC_ARITH.ALL;
  23.
      use IEEE.STD_LOGIC_UNSIGNED.ALL;
  24.

  25.
      ---- Uncomment the following library declaration if instantiating
  26.
      ---- any Xilinx primitives in this code.
  27.
      --library UNISIM;
  28.
      --use UNISIM.VComponents.all;
  29.

  30.
      entity CLK_GEN is
  31.
          Port ( CLK_IN : in  STD_LOGIC;
  32.
                 PRESCALE : in integer range 0 to 255;
  33.
                 CLK_OUT : out  STD_LOGIC);
  34.
      end CLK_GEN;
  35.

  36.
      architecture Behavioral of CLK_GEN is
  37.
              SIGNAL COUNTER : integer range 0 to 4080;
  38.
      begin
  39.

  40.

  41.
              PROCESS ( CLK_IN, COUNTER, PRESCALE )
  42.
              BEGIN
  43.
                      IF RISING_EDGE(CLK_IN) THEN
  44.
                              IF (COUNTER = (PRESCALE*16)-1) THEN
  45.
                                      COUNTER <= 0;
  46.
                                      CLK_OUT <= '1';
  47.
                              ELSE
  48.
                                      COUNTER <= COUNTER + 1;
  49.
                                      CLK_OUT <= '0';
  50.
                              END IF;
  51.
                      END IF;
  52.
              END PROCESS;
  53.

  54.

  55.
      end Behavioral;

von Duke Scarring (Gast)


Lesenswert?

1
                        _
2
                    _________|_|___________
3
          |\   /|      |             |
4
          \ \___/ /   | Freilaufender Troll!  |
5
          /   O  O\___   | Bitte nicht füttern!  |
6
         /            \  |                       |
7
        /              \ |---------+-+-----------+
8
              |  _____\  \          | |
9
              | /| |_|_\   )         | |
10
             ||/ v    \  /         _| |
11
                   _|_____  _  \___/_________/ |_|
12
            /        || \/ ||            |___|
13
                 /  |     || || ||___________ |___|
14
                      /     \ ___||____||           \____|
15
          |_|_|_|   |   /             | |
16
       ____  /\    __/   /              | |
17
      *    _/ __ \_/ /   /  \   \              | |
18
       \  / _/  \___(   (   )   )             | |
19
     *__\/ /        |   |   |   |             | |
20
        /| \  |   |    |   |             | |
21
       * *  *   |   |    |   |             | |
22
              |   |    |   |_______      | |
23
             /````\    |````       \     | |
24
            (______)   |___________|     |_|

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


Lesenswert?

> Freilaufender Troll! Bitte nicht füttern!
Sieht böse aus.... ;-)

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.