Skocz do zawartości

Pomocna odpowiedź

Napisano

Cześć,

ponieważ lepiej znam język VHDL niż Verilog (i VHDL'a używam w swoich projektach) staram się aby cały kod projektu był napisany w jednym języku - VHDL. Czasami jednak, szukając rozwiązania jakiegoś problemu znajduję ciekawe rozwiązanie w Języku Verilog (tak. np było w przypadku implementacji UART w FPGA). Przykładowa realizacja UART wykonana w języku Verilog była prostsza(i bardziej dla mnie zrozumiała niż kod rozwiązań w VHDL). Teraz jednak chciałbym przetłumaczyć tą sprawdzoną praktycznie implementację na kod VHDL (i włączyć ją do innego projektu).

Przeszukiwałem fora dyskusyjne dot. układów programowalnych i istnieje kilka takich automatycznych translatorów Verilog na VHDL. Kilka komercyjnych narzędzi jest niedostępnych ze względu na licencję, a chyba niezłego darmowego:

http://www.edautils.com/vhdl2verilog.html

nie mogę wypróbować, bo nikt nie odpowiada na mojego maila z prośbą o hasło do ściągnięcia softu z ich strony.

Po kilku "podejściach" stwierdziłem, że chyba najlepiej z darmowych translatorów sprawdza się Icarus Verilog (oczywiście możecie się ze mną nie zgodzić i podać lepiej działające rozwiązania). Podaję linki do "Icarus Verilog":

http://iverilog.icarus.com/

http://bleyer.org/icarus/

http://iverilog.icarus.com/page/plug-ins

A tutaj linki do dokumentacji:

http://iverilog.wikia.com/wiki/User_Guide

https://www.swarthmore.edu/NatSci/mzucker1/e15_f2014/iverilog.html

http://manpages.ubuntu.com/manpages/wily/man1/iverilog.1.html

Po instalacji kompilatora z pakietu instalacyjnego Windows (64-bit):

Dodałem ścieżkę z plikami binarnymi programu do zmiennej PATH: z Windowsa (u mnie jest to D:\IcarusVerilog\bin). Podstawowa wersja wywołania kompilatora to (command line Windows):

iverilog -o simple  simple.v

gdzie: iverilog - to program kompilatora

-o simple - plik wyjściowy (object z kompilatora C)

simple.v - plik wejściowy projektu w j. Verilog (może być ich wiele)

Dzięki dokumentacji po kilku próbach udało mi się wypracować z jakimi parametrami należy wywołać kompilator aby uzyskać źródła przetłumaczone na VHDL:

iverilog -o UART -t vhdl txstr.v uart_tx.v baudgen_tx.v

Kluczowy jest tu parametr: -t vhd (target: VHDL)

Teraz w pliku UART będziemy mieć kod VHDL z opisami przetłumaczony z Verilog.

Można też podać dodatkowe parametry, aby mieć informację z procesu translacji Verilog2VHDL:

D:\IcarusVerilog\_Projects\UART>iverilog -o UART -t vhdl -pdebug=1 -pdepth=3 txstr.v uart_tx.v baudgen_tx.v
[DEBUG] Initial visit to scope type txstr at depth 0
[DEBUG] Initial visit to scope type uart_tx at depth 1
[DEBUG] Initial visit to scope type baudgen_tx at depth 2
[DEBUG] Declaring signals in scope type txstr
[DEBUG] Declaring signals in scope type uart_tx
[DEBUG] Declaring signals in scope type baudgen_tx
[DEBUG] Declaring logic in scope type txstr
[DEBUG] Declaring logic in scope type uart_tx
[DEBUG] Declaring logic in scope type baudgen_tx
[DEBUG] Translating process in scope type baudgen_tx (baudgen_tx.v:45)
[DEBUG] Translating process in scope type baudgen_tx (baudgen_tx.v:47)
[DEBUG] Translating process in scope type uart_tx (uart_tx.v:62)
[DEBUG] Translating process in scope type uart_tx (uart_tx.v:75)
[DEBUG] Translating process in scope type uart_tx (uart_tx.v:91)
[DEBUG] Translating process in scope type uart_tx (uart_tx.v:103)
[DEBUG] Translating process in scope type uart_tx (uart_tx.v:121)
[DEBUG] Translating process in scope type uart_tx (uart_tx.v:128)
[DEBUG] Translating process in scope type txstr (txstr.v:26)
[DEBUG] Translating process in scope type txstr (txstr.v:46)
[DEBUG] Translating process in scope type txstr (txstr.v:62)
[DEBUG] Generated wait-for-0 for txstr.v:66
[DEBUG] Translating process in scope type txstr (txstr.v:81)
[DEBUG] Translating process in scope type txstr (txstr.v:89)
[DEBUG] Deallocated 860 VHDL syntax objects
[DEBUG] 83552 total bytes used for VHDL syntax objects

D:\IcarusVerilog\_Projects\UART>

Parametr: -pdepth=3 mówi ile poziomów zagłębień modułów Verilog ma być tłumaczonych.

A tutaj plik z wynikiej translacji Verilog 2 VHDL (generuje też komentarze):

-- This VHDL was converted from Verilog using the
-- Icarus Verilog VHDL Code Generator 10.1 (stable) (v10_1_1)

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

-- Generated from Verilog module txstr (txstr.v:16)
--   BAUDRATE = 1250
--   INI = 0
--   NEXTCAR = 2
--   STOP = 3
--   TXCAR = 1
entity txstr is
 port (
   clk : in std_logic;
   rstn : in std_logic;
   tx : out std_logic
 );
end entity; 

-- Generated from Verilog module txstr (txstr.v:16)
--   BAUDRATE = 1250
--   INI = 0
--   NEXTCAR = 2
--   STOP = 3
--   TXCAR = 1
architecture from_verilog of txstr is
 signal cena : std_logic;  -- Declared at txstr.v:43
 signal char_count : unsigned(2 downto 0);  -- Declared at txstr.v:42
 signal data : unsigned(7 downto 0);  -- Declared at txstr.v:27
 signal next_state : unsigned(1 downto 0);  -- Declared at txstr.v:78
 signal ready : std_logic;  -- Declared at txstr.v:25
 signal start : std_logic := '0';  -- Declared at txstr.v:26
 signal state : unsigned(1 downto 0);  -- Declared at txstr.v:77

 component uart_tx is
   port (
     clk : in std_logic;
     data : in unsigned(7 downto 0);
     ready : out std_logic;
     rstn : in std_logic;
     start : in std_logic;
     tx : out std_logic
   );
 end component;
 signal tx_Readable : std_logic;  -- Needed to connect outputs
begin
 tx <= tx_Readable;

 -- Generated from instantiation at txstr.v:33
 TX0: uart_tx
   port map (
     clk => clk,
     data => data,
     ready => ready,
     rstn => rstn,
     start => start,
     tx => tx_Readable
   );
 -- Removed one empty process


 -- Generated from always process in txstr (txstr.v:46)
 process (char_count) is
 begin
   case char_count is
     when "000" =>
       data <= Resize(unsigned("H"), 8);
     when "001" =>
       data <= Resize(unsigned("e"), 8);
     when "010" =>
       data <= Resize(unsigned("l"), 8);
     when "011" =>
       data <= Resize(unsigned("l"), 8);
     when "100" =>
       data <= Resize(unsigned("o"), 8);
     when "101" =>
       data <= Resize(unsigned("!"), 8);
     when "110" =>
       data <= Resize(unsigned("."), 8);
     when "111" =>
       data <= Resize(unsigned("."), 8);
     when others =>
       data <= Resize(unsigned("."), 8);
   end case;
 end process;

 -- Generated from always process in txstr (txstr.v:62)
 process is
 begin
   wait until rising_edge(clk);
   if (not rstn) = '1' then
     char_count <= "000";
   else
     if cena = '1' then
       wait for 0 ns;  -- Read target of blocking assignment (txstr.v:66)
       char_count <= char_count + "001";
     end if;
   end if;
 end process;

 -- Generated from always process in txstr (txstr.v:81)
 process (clk) is
 begin
   if rising_edge(clk) then
     if (not rstn) = '1' then
       state <= "00";
     else
       state <= next_state;
     end if;
   end if;
 end process;

 -- Generated from always process in txstr (txstr.v:89)
 process (state, ready, char_count) is
 begin
   next_state <= state;
   start <= '0';
   cena <= '0';
   case state is
     when "00" =>
       start <= '1';
       next_state <= "01";
     when "01" =>
       if ready = '1' then
         next_state <= "10";
       end if;
     when "10" =>
       cena <= '1';
       if Resize(char_count, 32) = X"00000007" then
         next_state <= "11";
       else
         next_state <= "00";
       end if;
     when others =>
       null;
   end case;
 end process;
end architecture;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

-- Generated from Verilog module uart_tx (uart_tx.v:22)
--   BAUDRATE = 1250
--   IDLE = 0
--   START = 1
--   TRANS = 2
entity uart_tx is
 port (
   clk : in std_logic;
   data : in unsigned(7 downto 0);
   ready : out std_logic;
   rstn : in std_logic;
   start : in std_logic;
   tx : out std_logic
 );
end entity; 

-- Generated from Verilog module uart_tx (uart_tx.v:22)
--   BAUDRATE = 1250
--   IDLE = 0
--   START = 1
--   TRANS = 2
architecture from_verilog of uart_tx is
 signal ready_Reg : std_logic;
 signal tx_Reg : std_logic;
 signal baud_en : std_logic;  -- Declared at uart_tx.v:45
 signal bitc : unsigned(3 downto 0);  -- Declared at uart_tx.v:38
 signal clk_baud : std_logic;  -- Declared at uart_tx.v:35
 signal data_r : unsigned(7 downto 0);  -- Declared at uart_tx.v:41
 signal load : std_logic;  -- Declared at uart_tx.v:44
 signal next_state : unsigned(1 downto 0);  -- Declared at uart_tx.v:54
 signal shifter : unsigned(9 downto 0);  -- Declared at uart_tx.v:69
 signal state : unsigned(1 downto 0);  -- Declared at uart_tx.v:53

 component baudgen_tx is
   port (
     clk : in std_logic;
     clk_ena : in std_logic;
     clk_out : out std_logic;
     rstn : in std_logic
   );
 end component;
begin
 ready <= ready_Reg;
 tx <= tx_Reg;

 -- Generated from instantiation at uart_tx.v:108
 BAUD0: baudgen_tx
   port map (
     clk => clk,
     clk_ena => baud_en,
     clk_out => clk_baud,
     rstn => rstn
   );

 -- Generated from always process in uart_tx (uart_tx.v:62)
 process (clk) is
 begin
   if rising_edge(clk) then
     if ((unsigned'("0000000000000000000000000000000") & start) = X"00000001") and (Resize(state, 32) = X"00000000") then
       data_r <= data;
     end if;
   end if;
 end process;

 -- Generated from always process in uart_tx (uart_tx.v:75)
 process (clk) is
 begin
   if rising_edge(clk) then
     if (unsigned'("0000000000000000000000000000000") & rstn) = X"00000000" then
       shifter <= "1111111111";
     else
       if (unsigned'("0000000000000000000000000000000") & load) = X"00000001" then
         shifter <= data_r & "01";
       else
         if ((unsigned'("0000000000000000000000000000000") & load) = X"00000000") and ((unsigned'("0000000000000000000000000000000") & clk_baud) = X"00000001") then
           shifter <= '1' & shifter(1 + 8 downto 1);
         end if;
       end if;
     end if;
   end if;
 end process;

 -- Generated from always process in uart_tx (uart_tx.v:91)
 process (clk) is
 begin
   if rising_edge(clk) then
     if (not rstn) = '1' then
       bitc <= X"0";
     else
       if (unsigned'("0000000000000000000000000000000") & load) = X"00000001" then
         bitc <= X"0";
       else
         if ((unsigned'("0000000000000000000000000000000") & load) = X"00000000") and ((unsigned'("0000000000000000000000000000000") & clk_baud) = X"00000001") then
           bitc <= bitc + X"1";
         end if;
       end if;
     end if;
   end if;
 end process;

 -- Generated from always process in uart_tx (uart_tx.v:103)
 process (clk) is
 begin
   if rising_edge(clk) then
     tx_Reg <= shifter(0);
   end if;
 end process;

 -- Generated from always process in uart_tx (uart_tx.v:121)
 process (clk) is
 begin
   if rising_edge(clk) then
     if (not rstn) = '1' then
       state <= "00";
     else
       state <= next_state;
     end if;
   end if;
 end process;

 -- Generated from always process in uart_tx (uart_tx.v:128)
 process (state, start, bitc) is
 begin
   next_state <= state;
   load <= '0';
   baud_en <= '0';
   case state is
     when "00" =>
       ready_Reg <= '1';
       if (unsigned'("0000000000000000000000000000000") & start) = X"00000001" then
         next_state <= "01";
       end if;
     when "01" =>
       load <= '1';
       baud_en <= '1';
       ready_Reg <= '0';
       next_state <= "10";
     when "10" =>
       baud_en <= '1';
       ready_Reg <= '0';
       if Resize(bitc, 32) = X"0000000b" then
         next_state <= "00";
       end if;
     when others =>
       ready_Reg <= '0';
   end case;
 end process;
end architecture;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

-- Generated from Verilog module baudgen_tx (baudgen_tx.v:30)
--   BAUDRATE = 1250
--   N = 17
entity baudgen_tx is
 port (
   clk : in std_logic;
   clk_ena : in std_logic;
   clk_out : out std_logic;
   rstn : in std_logic
 );
end entity; 

-- Generated from Verilog module baudgen_tx (baudgen_tx.v:30)
--   BAUDRATE = 1250
--   N = 17
architecture from_verilog of baudgen_tx is
 signal tmp_s0 : unsigned(31 downto 0);  -- Temporary created at baudgen_tx.v:62
 signal tmp_s3 : unsigned(14 downto 0);  -- Temporary created at baudgen_tx.v:62
 signal tmp_s4 : unsigned(31 downto 0);  -- Temporary created at baudgen_tx.v:62
 signal tmp_s6 : std_logic;  -- Temporary created at baudgen_tx.v:62
 signal tmp_s8 : std_logic;  -- Temporary created at baudgen_tx.v:62
 signal divcounter : unsigned(16 downto 0) := "00000000000000000";  -- Declared at baudgen_tx.v:45
begin
 tmp_s0 <= tmp_s3 & divcounter;
 tmp_s6 <= '1' when tmp_s0 = tmp_s4 else '0';
 clk_out <= clk_ena when tmp_s6 = '1' else tmp_s8;
 tmp_s3 <= "000000000000000";
 tmp_s4 <= X"00000000";
 tmp_s8 <= '0';
 -- Removed one empty process


 -- Generated from always process in baudgen_tx (baudgen_tx.v:47)
 process (clk) is
 begin
   if rising_edge(clk) then
     if (not rstn) = '1' then
       divcounter <= "00000000000000000";
     else
       if clk_ena = '1' then
         if Resize(divcounter, 32) = X"000004e1" then
           divcounter <= "00000000000000000";
         else
           divcounter <= divcounter + "00000000000000001";
         end if;
       else
         divcounter <= "00000010011100001";
       end if;
     end if;
   end if;
 end process;
end architecture;

Plik został wygenerowany z plików projektu Verilog (uart_tx), w załączniku zamieszczam te pliki projektu Verilog spakowane zip.

UART.zip

Ja to mimo wszystko ze sceptycyzmem podchodzę do takich rozwiązań (automatycznie konwertuje, ale nie zawsze w zoptymalizowany sposób ^^)

Cześć Jakub,

ja też, ale jeśli tłumaczę większą ilość kodu z Verilog'a na VHDL to zaoszczędzam sporo czasu (mam wygenerowany "szkielet" projektu, który trzeba w niektórych punktach ręcznie zmodyfikować. To mniej więcej jak z syntezą HLS, też musisz dopisać część kodu ręcznie).

BTW: już teraz mogę powiedzieć, że ten translator nie generuje optymalnego kodu i to w kilku aspektach. Przykład: zupełnie pomija konstrukcje parameter w modułach Veriloga, chociaż mógłby to z powodzeniem przetłumaczyć na generic w entity VHDL.

Niektóre konwersje przez niego wykonane są komiczne 🤣

Tutaj link pomagający konwertować podstawowe konstrukcje Verilog <-> VHDL:

ftp://ece.buap.mx/pub/Secretaria_Academica/SDC/Active_HDL_4.2_Student_Version_Installer/Doc/avhdl/Avh00213.htm

Pozdrawiam

Oooo i widzę, że się ze mną zgadzasz co do optymalności - i cieszę się, że nie odebrałeś tego jako krytyki (ufffff....). Domyślam się, że chodzi o to aby jakiś szkielet uzyskać z większych porcji kodów (a tym samym oszczędzić jak to ująłeś czas - to tak jak właśnie z byle językiem wyższego poziomu typu C i asemblerem, co się stało przełomem i doprowadziło do wykwitu różnorakich rozwiązań mikrokontrolerowych i mikroprocesorowych ze względu na szybkość - tylko tam to prosta sprawa bo zamieniasz wszystko na pojedyncze instrukcje, a tu musisz jedną konstrukcję w drugą zamienić i to jest kłopotliwe - a żeby się już połapać to już w ogóle, szczególnie przy rozbudowanych rzeczach, i żeby jeszcze przy tym zachować wymagają funkcjonalność w całości - to jest prawdziwy wyczyn już). Oczywiście to też nie jest krytyka, tylko wymiana spostrzeżeń ^^

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...