www.mikrocontroller.net

Forum: FPGA, VHDL & Co. UART


Autor: Ulrich Kowohl (jesuz)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, besitzt jemand einen Verilog Sample code fuer ein einfaches UART?
Wuerde mich mal interessieren wie der aussieht...

vlg

Autor: Xenu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schon mal probiert "Verilog" und "UART" bei Google einzugeben...

Autor: Ulrich Kowohl (jesuz)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja das habe ich probiert ... aber wirklich viel sinnvolles habe ich dort
nicht gefunden

Autor: Uwe Bonnes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau mal auf opencores. Allerdings ist die Site gerade (14.3. 12.50)
Down...

Autor: ejd (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man findet einen UART in Verilog unter http://www.fpga4fun.com/

mfG,
ejd

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falls Du eine gute Beschreibung in VHDL gefunden hast, dann poste doch
bitte mal den Link bzw. Code.

Danke,
Sebastian

Autor: T.M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab die Tage eine kleine UART in VHDL geschrieben...vielleicht nützt
es was:

Transmitter:
library ieee;
use ieee.std_logic_1164.all;

entity transmitter is
port (reset      : in  std_logic;                     -- asynch reset
      clk        : in  std_logic;                     -- clock 40 MHz
      data       : in  std_logic_vector(7 downto 0);  -- data input
      data_ready : in  std_logic;                     -- control signal
data ready
      tx_ready   : out std_logic;                     -- transmitter
ready for new data
      tx         : out std_logic);                    -- transmitter
output
end transmitter;

architecture behavior of transmitter is

-- internal signals
signal sending       : boolean;                       -- sending mode
signal sent          : boolean;                       -- sent mode
signal count_clk     : natural range 0 to 4167;       -- clock counter
for clock divider
signal count_bit     : natural range 0 to 10;         -- bit counter
signal enable        : std_logic;                     -- clock enable
for sending mode
signal tx_ready_int  : std_logic := '1';              -- initalized
to 1 for tx_ready = 1 on start
signal data_register : std_logic_vector(7 downto 0);  -- for storage of
data input to send

begin

  
-------------------------------------
-- load tx_ready with rx_ready_int --
-------------------------------------
tx_ready <= tx_ready_int;


--------------------------------------------------
-- clock divider for baudrate generation        --
-- sensitive to clock, asynch reset by received --
-- receiving mode: generate clock enable        --
-- for wished baudrate                          --
--------------------------------------------------
clock_divider : process (clk, sent) is
begin
if sent then
  count_clk <= 0;
elsif clk'event and clk = '1' then
    if sending then
      enable <= '0';
      if count_clk = 4167 then
        count_clk <= 0;
      elsif count_clk = 0 then
        enable <= '1';
        count_clk <= count_clk + 1;
      else
        count_clk <= count_clk + 1;
      end if;
    end if;
  end if;
end process clock_divider;


-----------------------------------------------------------
-- data storage of input data                            --
-- sensitive to clock, asynch reset by reset             --
-- storage data in internal register when data_ready = 1 --
-----------------------------------------------------------
data_storage : process (clk, reset, sent) is
begin
if reset = '1' or sent then
  data_register <= (others => '0');
  sending       <= false;
elsif clk'event and clk = '1' then
  if data_ready = '1' then
    if not sending then
      data_register <= data;
      sending       <= true;
    end if;
  end if;
end if;
end process data_storage;


-------------------------------------------------------
-- send storaged data                                -- 
-- sensitive to clock, asynch reset by reset         --
-- load tx with content of data register from 0 to 9 --
-- when sending complete : ready for new data        --
-------------------------------------------------------
data_send : process (clk, reset) is
begin
if reset = '1' then
  tx        <= '1';
  count_bit <= 0;
elsif clk'event and clk = '1' then
sent <= false;
  if enable = '1' then
    tx_ready_int <= '0';
    tx           <= '1';
    case count_bit is
      when 0  => tx        <= '0';
                 count_bit <= count_bit + 1;
      when 9  => tx        <= '1';
                 count_bit <= count_bit + 1;
      when 10 => tx            <= '1';
                 count_bit     <= 0;
                 sent          <= true;
                 tx_ready_int  <= '1';
      when others => count_bit <= count_bit + 1;
                     tx        <= data_register(count_bit - 1);
    end case;
  end if;
end if;
end process data_send;
    
end architecture behavior;

Receiver:
library ieee;
use ieee.std_logic_1164.all;

entity receiver is
port (reset      : in  std_logic;                      -- asynch reset
      clk        : in  std_logic;                      -- clock 40 MHz
      rx         : in  std_logic;                      -- receive
input
      data_ready : out std_logic;                      -- status signal
data received
      data_error : out std_logic;                      -- status signal
receive error
      data_out   : out std_logic_vector(7 downto 0));  -- received
data
end receiver;

architecture behaviour of receiver is

signal received      : boolean;                       -- for received
mode
signal receiving     : boolean;                       -- for receive
mode
signal count_start   : natural range 0 to 2083;       -- start counter
for detecting middle of startbit
signal count_clk     : natural range 0 to 4167;       -- clock counter
for clock divider
signal count_bit     : natural range 0 to 9;          -- bit counter
for received bits
signal enable        : std_logic;                     -- clock enable
for receive mode
signal data_register : std_logic_vector(7 downto 0);  -- data register
for received bits


begin


--------------------------------------------------
-- detecting startbit                           --
-- sensitive to clock, asynch reset by received --
-- if rx = 0 counts to 2083 to know if there is --
-- a startbit                                   --
-- when startbit:   go in receiving mode        --
-- when no starbit: count again from 0 to 2083  --
--------------------------------------------------
sampling : process (clk, received) is
begin
if received then
  receiving <= false;
  count_start <= 0;
elsif clk'event and clk = '1' then
  if rx = '0' then
    if count_start = 2083 then
      receiving <= true;
    else
      count_start <= count_start + 1;
    end if;
  end if;
end if;
end process sampling;


--------------------------------------------------
-- clock divider for baudrate generation        --
-- sensitive to clock, asynch reset by received --
-- receiving mode: generate clock enable        --
-- for wished baudrate                          --
--------------------------------------------------
clock_divider: process (clk, received) is
begin
if received then
count_clk <= 0;
elsif clk'event and clk = '1' then
    if receiving then
      enable <= '0';
      if count_clk = 4167 then
        count_clk <= 0;
      elsif count_clk = 0 then
        enable <= '1';
        count_clk <= count_clk + 1;
      else
        count_clk <= count_clk + 1;
      end if;
    end if;
  end if;
end process clock_divider;


--------------------------------------------------------
-- receive data                                       --
-- sensitive to clock. asynch reset by reset          --
-- clock enable by enable                             --
-- load 9 bit in data register & put data on data out --
-- last bit = 1 : valid stopbit => data ready         --
-- last bit = 0 : invalid stopbit => data error       --
--------------------------------------------------------
data_read: process (clk, reset) is
begin
if reset = '1' then
  data_register <= (others => '0');
elsif clk'event and clk = '1' then
received   <= false;  
  if enable = '1' then
     data_ready <= '0';
     data_error <= '0';
     case count_bit is
       when 0 => count_bit <= count_bit + 1;
       when 9 => count_bit <= 0;
                 received  <= true;
     data_out  <= data_register;
                 if rx = '1' then
                   data_ready <= '1';
                 else
                   data_error <= '1';
                 end if;
       when others => count_bit <= count_bit + 1;
                      data_register(count_bit-1) <= rx;
     end case;
  end if;
end if;
end process data_read;
                
end behaviour;

Testbench kann ich wenn erwünscht auch liefern...

Autor: T.M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hä? Was muss denn seit neusten für VHDL code eingeben? Früher ging mal
mal c in eckigen Klammern....

Autor: FPGA-User (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sieht nicht schlecht aus, aber warum nimmst Du für
data_register() kein Schieberegister ?
Und jeweils oben in TX und RX sollte eine Konstante
sein, wo man den Teiler einfach an die Taktfrequenz
anpassen kann. Dann wäre es ganz hübsch ... ;-)

Autor: axel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ T.M. gute arbeit. Aber ein c in klammern sagt, das es ein c-Code ist.
Mit vhdl am anfang und /VHDL am ende gehts besser :-) Natürlich in
eckige klammern.

Autor: T.M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, ich wollte eh noch generics einführen für die Einstellung der
Baudrate... Sowas mach ich immer nachdem ich weiss, dass es prinzipiell
funzt ;-)
Das mit dem Schieberegister ist natürlich ne Alternative. Muss ich dann
mal guggn.
Danke :-)

Autor: Ralf Hagemann (hagemann)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hy T.M.,

dein Beitrag ist zwar schon ne Weile her, aber immer noch interessant.
Läuft dein UART stabil ?
Ich habe bei meinem UART-CORE immer das Problem, das Zeichen beim lesen 
verschluckt weden ?

Hat du vielleicht eine Testbench für deinen UART ?

Gruss
Ralf

Ps.:
Ich verwende das Xilinx Spartan3 StarterKitBoard mit dem
"PicoBlaze Core von Ken Chapman (Xilinx Ltd)
October 2002" und den "UART Transmitter Version 1.00 von Ken Chapman,
Xilinx Ltd, Benchmark House".



Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.