Codice vhdl per uart RS232

Sezione dedicata al linguaggio di descrizione hardware per logiche programmabili

Codice vhdl per uart RS232

Postby lukarusso89 » 21 Nov 2012, 10:32

Ciao a tutti, mi sto impelagando nella simulazione di una porta uart RS232 che prenda 8 bit in ingresso , e me li restituisca in uscita ( in seguito vorrei mandare i dati ad un display ma questo in una fase successiva).
Ho implementato il codice dopo avere cercato di capire a fondo il suo funzionamento su internet, ma non riesco in modelsim a settare i parametri giusti per potere ottenere i bit esatti in uscita. Io forzo ad 1 i parametri Rx,Tx, DSR ( segnala che la periferica è pronta ad operare) e CTS( il canale dati è pronto per la trasmissione), il resto a zero ed il clock a 50 Mhz(con un divisore). Il reset funziona perfettamente invece (l'ho predisposto come suggerito da flz :P).
Spero in un vostro aiuto e allego il codice qui di seguito.

Code: Select all
--RS232
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity rs_232 is
port (     Rx      : in  std_logic;
           Clock   : in  std_logic;
           Reset   : in  std_logic;
           CTS     : in  std_logic;
           DTR_in  : in  std_logic;
           Data_in : in  std_logic_vector (7 downto 0);
           DSR     : in  std_logic;
           RTS_in  : in  std_logic;
           RTS_out : out std_logic;
           DTR_out : out std_logic;
           Tx      : out  std_logic;
           Data_out: out  std_logic_vector (7 downto 0)
           );
   end rs_232;
   
   architecture behavioral of rs_232 is
   
   component Div_clk
   port(
          clk_in   : in  std_logic;   
          reset   : in  std_logic;    -- reset asincrono
          clk_out  : out std_logic    
       );
 
end component;

   component uart
      port (
         
         clk_div     :in  std_logic;
         reset       :in  std_logic;
         ld_tx_data  :in  std_logic;
         tx_data     :in  std_logic_vector (7 downto 0);
         tx_enable   :in  std_logic;
         rx_enable   :in  std_logic;
         uld_rx_data :in  std_logic;
         rx_in       :in  std_logic;
         tx_out      :out std_logic;
         rx_data     :out std_logic_vector (7 downto 0)
         
         );
         
end component;
   signal div_clk_1 : std_logic;
   signal DTR_1 : std_logic;
   signal RTS_1 : std_logic;
   
begin
      
      uart_component : uart port map (    reset => reset,
                                          clk_div => div_clk_1,
                                          ld_tx_data => DTR_in,
                                          tx_data => Data_in,
                                          tx_enable => RTS_in, 
                                          tx_out => Tx,
                                          uld_rx_data => DSR,
                                          rx_data => Data_out,
                                          rx_enable => CTS,
                                          rx_in => Rx
                                          );
                                          
   clock_component : Div_clk port map (   clk_in => Clock,
                                          reset => reset,
                                          clk_out => div_clk_1
                                          );
                                       
   DTR_1 <= DTR_in;
   RTS_1 <= RTS_in;
   DTR_out <= DTR_1;
   RTS_out <= RTS_1;                                 
                                          
   end architecture;                                    
   


Code: Select all
--Divisore Clock
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity Div_clk is

 
port(
    clk_in   : in  std_logic;    -- Input Clock
    reset   : in  std_logic;    -- reset asincrono
    clk_out  : out std_logic     -- uscita
  );
 
end Div_clk;


architecture Behavioral of Div_clk is


signal clk_flag : std_logic  := '0';

begin

process (clk_in, reset)
variable count : integer :=1;

begin
if (clk_in 'event ) and (clk_in ='1') then
   if (reset = '1') then
   count := 0;
   end if;
   
   if (count mod 10)= 0 then         
      clk_flag <= not clk_flag;
      end if;
      
      if (count  = 10) then
         count :=1;
      
   else
      count := count + 1;
   end if;
end if;
end process;

clk_out <= clk_flag;
end Behavioral;


Code: Select all
--uart
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity uart is
        port (
         
         clk_div     :in  std_logic;
         reset       :in  std_logic;
         ld_tx_data  :in  std_logic;
         tx_data     :in  std_logic_vector (7 downto 0);
         tx_enable   :in  std_logic;
         rx_enable   :in  std_logic;
         uld_rx_data :in  std_logic;
         rx_in       :in  std_logic;
         tx_out      :out std_logic;
         rx_data     :out std_logic_vector (7 downto 0)
         
         );
         
end entity;

architecture rtl of uart is

     signal tx_reg         :   std_logic_vector (7 downto 0);
     signal tx_cnt         :   std_logic_vector (3 downto 0);
     signal rx_reg         :   std_logic_vector (7 downto 0);
     signal rx_sample_cnt  :   std_logic_vector (3 downto 0);
     signal rx_cnt         :   std_logic_vector (3 downto 0);
     signal rx_s1          :   std_logic;
     signal rx_s2          :   std_logic;
     
begin
-- TRASMISSIONE
process (clk_div, reset)
begin
if (reset = '1') then
              tx_reg        <= (others=>'0');
              tx_out        <= '1';
              tx_cnt        <= (others=>'0');
             
elsif (rising_edge(clk_div)) then
      if (ld_tx_data ='1') then
      tx_reg <= tx_data;
      end if;
      end if;
      
   if (tx_enable ='1') then
   tx_cnt <= tx_cnt +1;
   if (tx_cnt = 0) then
       tx_out <= '0';
   end if;
   if (tx_cnt > 0 and tx_cnt < 9) then
       tx_out <= tx_reg(conv_integer(tx_cnt) - 1);
       end if;
   if (tx_cnt = 9) then
        tx_out <= '1';
        tx_cnt <= "0000"; 
         end if;
         end if;
   if (tx_enable = '0') then
        tx_cnt <= X"0";
         end if;
         
         
      end process;
-- RICEZIONE
process (clk_div, reset) begin
     if (reset = '1') then
         rx_reg        <= (others=>'0');
         rx_data       <= (others=>'0');
         rx_sample_cnt <= (others=>'0');
         rx_cnt        <= (others=>'0');
         rx_s1         <= '1';
         rx_s2         <= '1';
         
      elsif (rising_edge(clk_div)) then
      -- sincronizzazione del segnale di ingresso
              rx_s1 <= rx_in;
              rx_s2 <= rx_s1;
             
       if (uld_rx_data = '1') then
               rx_data  <= rx_reg;
               
         end if;
         if (rx_enable = '1') then
         
              rx_sample_cnt <= rx_sample_cnt + 1;
         if (rx_sample_cnt = 9) then
              rx_cnt <= rx_cnt + 1;
         -- carico dati sul registro parallelo
         if (rx_cnt < 8) then
             rx_reg(conv_integer(rx_cnt)) <= rx_s2;
         
          end if;
          end if;
          end if;
           end if;
         
      end process;
      end architecture;
         
lukarusso89
 
Posts: 12
Joined: 21 Oct 2012, 18:05

Re: Codice vhdl per uart RS232

Postby flz47655 » 21 Nov 2012, 10:52

Mumble... sembra che ci sia qualche end if di troppo..

Code: Select all
elsif (rising_edge(clk_div)) then
         if (ld_tx_data ='1') then
         tx_reg <= tx_data;
         end if;
      end if;


PS: Come consiglio generale guarda sempre i Warning generati da Quartus, predicono quasi sempre qualche problema
flz47655
 
Posts: 639
Joined: 19 Jan 2012, 21:16

Re: Codice vhdl per uart RS232

Postby lukarusso89 » 21 Nov 2012, 12:19

Mamma mia...sono impazzito con tutti questi if!:P Ma hai provato se il codice in simulazione va? Adesso corrego e riprovo anche io!
Grazie mille comunque!:)
lukarusso89
 
Posts: 12
Joined: 21 Oct 2012, 18:05

Re: Codice vhdl per uart RS232

Postby flz47655 » 21 Nov 2012, 13:20

Per esperienza bisogna dare molta importanza all'indentazione del codice.
Non l'ho provato con ModelSim per mancanza di tempo, ti ho dato una dritta sulla prima cosa che mi è balzata all'occhio, ma cosa intendi con:
non riesco in modelsim a settare i parametri giusti per potere ottenere i bit esatti in uscita

Più che parametri devi semplicemente impostare i segnali a dei valori fittizi per simulare una comunicazione.

Ciao
flz47655
 
Posts: 639
Joined: 19 Jan 2012, 21:16

Re: Codice vhdl per uart RS232

Postby lukarusso89 » 21 Nov 2012, 13:55

Nel senso che ho dato dei valori di 1 e 0 in base a cosa volevo abilitare o disabilitare, ma non sono riuscito ad ottenere in uscita la sequenza di bit desiderata.
Quello che intendevo dire è che magari ho sbagliato ad assegnare dei valori in simulazione, piuttosto che fatto errori nel codice (anche se sono probabili entrambe le opzioni :P)
lukarusso89
 
Posts: 12
Joined: 21 Oct 2012, 18:05

Re: Codice vhdl per uart RS232

Postby flz47655 » 21 Nov 2012, 14:01

ModelSim ha una sorta di debugger che permette di impostare dei breakpoint, eseguire passo passo i processi e cosette di questo genere che aiutano a trovare gli errori, magari prova a darci un'occhiata.

Ciao
flz47655
 
Posts: 639
Joined: 19 Jan 2012, 21:16


Return to VHDL x FPGA

Who is online

Users browsing this forum: No registered users and 9 guests

cron