Najczęściej popełniane błędy w VHDL’u

1 Najczęściej popełniane błędy w VHDL’uErnest Jamro Kat. ...
Author: Bolesław Węglewski
0 downloads 2 Views

1 Najczęściej popełniane błędy w VHDL’uErnest Jamro Kat. Elektroniki AGH

2 Wzory poprawnej syntezyActiveHDL: Menu/Tools/Language Assistant: Synthesis Templates ISE Procject Navigator: Menu/Edit/Language Templates: VHDL / Synthesis Constructs / (Coding Example)

3 Poprawna składnia przerzutnika typu Dprocess (CLK, RESET) begin if RESET='1' then – reset asynchroniczny DOUT <= '0'; elsif (CLK'event and CLK='1') then DOUT <= DIN; end if; end process;

4 Najczęstsze błędy process (CLK, RESET) – brak sygnału reset beginif RESET='1' then – reset asynchroniczny DOUT <= '0'; elsif (CLK'event and CLK='1') then DOUT <= DIN; end if; end process;

5 Przerzutnik D z Clock Enable (CE)process (, ) begin if =‘1' then <= '0'; elsif ('event and ='1') then if = '1' then -- lub inna logika synchroniczna <= ; end if; end process;

6 Błędy: Przerzutnik z CEprocess (, , ) begin if ='0' then <= '0'; elsif ('event and ='1‘ and = '1' ) <= ; end if; end process;

7 Błąd: Wymuszenie tego samego sygnału w dwóch procesachA0: process(...) begin .... if ( ...) a<= ‘0’; end if; end process; A1: process(...) begin a<= ‘1’;

8 Przerzutnik typu Latchprocess (GATE, DIN) begin if GATE='1' then --GATE active High DOUT <= DIN; end if; end process; Przerzutników Latch należy raczej unikać – z reguły powstają one w wyniku błędu a nie zamierzonego projektowania

9 Multiplekser (lub inna logika kombinacyjna)process (SEL, A, B, C) begin case SEL is when "00" => MUX_OUT <= A; when "01" => MUX_OUT <= B; when "10" => MUX_OUT <= C; when others => MUX_OUT <= 'X'; end case; end process;

10 Multiplekser Błędy process (SEL, A, B, C) – brak jednego z sygnałów wejściowych (latch) begin case SEL is when "00" => MUX_OUT <= A; when "01" => MUX_OUT <= B; when "10" => MUX_OUT <= C; when others => MUX_OUT <= 'X'; end case; end process;

11 Process – magiczne słowoPoza procesem nie można używać następujących składni: If ... Then ... Elsif ... End if For .... Loop Uwaga: Wiele operacji (szczególnie logiki kombinacyjnej) można umieścić poza procesem

12 Alternatywne rozwiązanie MultiplekserMux_out<= A when sel = "00" else B when sel = "01" else C when sel = "10" else '-'; LUB WITH sel SELECT Mux_out <= A when "00", B when "01", C when "10" '-' when others; inB AFTER 10 NS WHEN OTHERS;

13 Umiejscawianie komponentów 1entity FULL_ADDER port ( a, b, cin: in std_logic; s, cout: out std_logic); end FULL_ADDER; architecture arch of FULL_ADDER is begin s<= a xor b xor c; cout<= a when a=b else cin; end arch;

14 Umiejscawianie komponentów 2entity MY_ADDER generic (width: integer); port ( a, b: in std_logic_vector(0 to width-1); s: out std_logic_vector(0 to width-1); end MY_ADDER; architecture arch of MY_ADDER is component FULL_ADDER -- deklaracja komponentu port ( a, b, cin: in std_logic; s, cout: out std_logic); end component; signal carry: std_logic_vector(0 to dwidth); begin

15 Umiejscawianie komponentów 3Ciąg dalszy z poprzedniej strony (rozwiązanie nieoptymalne) Carry(0)<= ‘0’; Gi: for i in 0 to width-1 generate – wielokrotne użycie elementu! g: full_adder port map (a=> a(i), b=> b(i), cin=> carry(i), cout=> carry(i+1), s=> s(i)); end generate; end arch; Lepsze rozwiązanie (użyta dedykowana logika dodająca) s<= a+ b;

16 Wartości domyślne, uaktualnienie modułówStary komponent component and_gate port ( din1, din2: in std_logic; dout: out std_logic); end component; Nowy komponent component and_gate generic (invert_output: integer:= 0); -- dodanie dodatkowego parametru port ( din1, din2, din3: in std_logic:= ‘1’; -- wartość domyślna ‘1’

17 Użycie zmodyfikowanego komponentuStary kod używa nowego elementu z nowymi wartościami w formie domyślnej A: and_gate port map (din1=> a, din2=> b, dout => y); Równoważne i zalecane w nowym kodzie: generic map (invert_output=>0) port map (din1=> a, din2=> b, din3=> ‘1’, dout => y);

18 Po co wartości domyślneRozważany element jest elementem nadrzędnym podczas symulacji lub implementacji Zgodność z poprzednimi wersjami tego samego elementu bez konieczności zmiany całego starego kodu

19 Ustawianie wartości parametrówArchitecture arch of my_gate is component and_gate generic (invert_output: integer:= 1); -- nie zmieniamy wartości parametru tutaj port ( din1, din2, din3: in std_logic:= ‘0’; -- nie zmieniamy wartości domyślnej tutaj dout: out std_logic); end component; begin a: and_gate -- użycie elementu generic map (invert_output=> 1) -- umieszczamy wartość każdego parametru port map (din1=> a, din2=> b, din3=> ‘0’); -- staramy się określić wartość każdego wejścia End arch;

20 Dodawanie bibliotek library ieee;use ieee.std_logic_1164.all; -- użycie std_logic use ieee.std_logic_unsigned.all; -- każda wartość std_logic_vector jest traktowana jako integer bez znaku use ieee.std_logic_signed.all; -- każda wartość std_logic_vector jest traktowana jako integer ze znaku Nie można równocześnie użyć obu bibliotek: std_logic_unsigned oraz std_logic_signed. W tym wypadku należy użyć biblioteki: use ieee.std_logic_arith.all; oraz zamiast słowa kluczowego std_logic_vector należy użyć słów unsigned lub signed (wada: konieczność używania konwersji std_logic_vector  unsigned (lub signed))

21 Programowanie pod kątem sprzętuPamięć RAM 16x1 (distributed RAM) type mem_type is array (0 to 15) od std_logic_vector(0 to 7) signal mem: mem_type; begin process () if ('event and = '1') then if ( = '1') then mem(conv_integer(

)) <= ; end if; end if; end process; <= mem(conv_integer(
));

22 Programowanie pod kątem sprzętuPamięć blokowa BRAM (dwuportowa) PortA: process () begin if ('event and = '1') then if ( = '1') then (conv_integer()) <= ; end if; <= ; end process; PortB: process () begin if ('event and = '1') then <= ; <= (conv_integer()); <= (conv_integer());

23 Programowanie pod kątem sprzętuBiblioteka: unisim a pamięć blokowa BRAM entity RAMB16_S36_S36 is generic ( INIT_00 : bit_vector := X" "; .... INIT_3F : bit_vector := X" " ); port( DOA : out STD_LOGIC_VECTOR (31 downto 0); DOB : out STD_LOGIC_VECTOR (31 downto 0); DOPA : out STD_LOGIC_VECTOR (3 downto 0); DOPB : out STD_LOGIC_VECTOR (3 downto 0); ADDRA : in STD_LOGIC_VECTOR (8 downto 0); ADDRB : in STD_LOGIC_VECTOR (8 downto 0); CLKA : in STD_ULOGIC; CLKB : in STD_ULOGIC; DIA : in STD_LOGIC_VECTOR (31 downto 0); DIB : in STD_LOGIC_VECTOR (31 downto 0); DIPA : in STD_LOGIC_VECTOR (3 downto 0); DIPB : in STD_LOGIC_VECTOR (3 downto 0); ENA : in STD_ULOGIC; ENB : in STD_ULOGIC; SSRA : in STD_ULOGIC; SSRB : in STD_ULOGIC; WEA : in STD_ULOGIC; WEB : in STD_ULOGIC

24 Programowanie pod kątem sprzętuBiblioteka unisim: Pętla DLL (delay lock loop – działająca podobnie jak PLL) entity CLKDLL is port ( CLK0 : out std_ulogic := '0'; CLK180 : out std_ulogic := '0'; CLK270 : out std_ulogic := '0'; CLK2X : out std_ulogic := '0'; CLK90 : out std_ulogic := '0'; CLKDV : out std_ulogic := '0'; LOCKED : out std_ulogic := '0'; CLKFB : in std_ulogic := '0'; CLKIN : in std_ulogic := '0'; RST : in std_ulogic := '0‘ )

25 Programowanie pod kątem sprzętulibrary UNISIM; use unisim.all; -- for global set reset signal component ROC port ( O : out std_ulogic := '1' ); end component Każdy przerzutnik powinien być zerowany (ustawiany) asynchronicznie tym sygnałem – jest to potrzebne zarówno do celów symulacyjnych jak i dla potrzeb ustawiania (wartość ‘1’) po procesie konfiguracji.

26 Reset synchroniczny i asynchronicznyReset asynchroniczny należy używać jako reset inicjalizujący pracę układu FPGA po konfiguracji – jest on wspomagany sprzętowo Reset synchroniczny (np. opb_rst) należy używać jako sygnał zerujący w pozostałych przypadkach np. podczas zerowania liczników, powtórnej inicjalizacji automatów, itd. Nie należy mieszać resetów synchronicznych i asynchronicznych

27 Poziomy logiczne Standard std_logic zawiera wiele poziomów nie tylko ‘0’, ‘1’, co może powodować inne zachowanie układu podczas symulacji funkcjonalnej, po syntezie i w rzeczywistym układzie. Przykład: if ce=‘1’ then Q<= D; end if; Co się stanie jeżeli dana wejściowa ce jest typu: ‘H’, ‘X’, ‘Z’ itd

28 Operacje na wektorach - przesunięciasignal a, b: std_logic_vector(dwidth-1 downto 0); -- deklaracja wektorów, dwidth- szerokość wektora Przesuniecie o jeden bit w lewo (pomnożenie przez 2): a<= b(dwidth-2 downto 0) & ‘0’ Przesuwający o jeden bit w prawo (dzielenie liczb dodatnich przez 2): a<= ‘0’ & ‘b(dwidth-1 downto 1) ; Dzielenie liczb w kodzie uzupełnień do 2 przez 2: a<= b(dwidth-1) & b(dwidth-1) & b(dwidth-2 downto 1); -- kopiowanie bitu znaku b(dwidth-1) Przesunięcie o n-bitów w lewo (n- constant lub generic): a(dwidth-1 downto n)<= b(dwidth-1-n downto 0); a(n-1 downto 0)<= (others=>’0’); Podzielenie przez 2n liczby w kodzie U2: a(dwidth-1 downto dwidth-n-1)<= (others=> b(dwidth-1)); a(dwidth-2-n downto 0)<= b(dwidth-2 downto n);

29 Operacje logiczne na wektorachsignal c, a, b: std_logic_vector(dwidth-1 downto 0); -- deklaracja wektorów c<= a and b; Równoważne: Gi: for i in 0 to dwidth-1 generate c(i)<= a(i) and b(i); end generate;

30 Operacje logiczne w ramach jednego wektoraOperacje logicze w ramach jednego wektora: library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_MISC.all; -- dodatkowa biblioteka signal a: std_logic_vector(dwidth-1 downto 0); signal y: std_logic; y<= OR_REDUCE(a); Równoważne: y<= a(0) or a(1) or a(2) or or a(dwidth-1); Process(a) variable b: std_logic; begin b:= ‘0’; for i in 0 to dwidth-1 loop b:= b or a(i); end loop; end process;