2012-01-31 9 views
7

Mam mały problem z następującego kodu VHDL:VHDL sygnał jazdy od różnych procesów

process (zbroji) 
begin 
    if rising_edge(zbroji) then 
     oduzima <= '0'; 
     ucitanPrvi <= '1'; 
     broj1 <= ulaz_broj; 
    end if; 
end process; 

process (oduzmi) 
begin 
    if rising_edge(oduzmi) then 
     oduzima <= '1'; 
     ucitanPrvi <= '1'; 
     broj1 <= ulaz_broj; 
    end if; 

end process; 

Problem polega na tym, że sygnał ucitanPrvi zawsze ma wartość X. Jeśli nie próbować go ustawić wartość w dwóch procesów , więc nie mam żadnych problemów ... Więc wiem, że nie mogę prowadzić jednego sygnału z wielu procesów, ale nie wiem, jak napisać to inaczej ... Czy ktoś ma pomysł, jak mógłbym rozwiązać ten problem?

Dzięki!

EDYCJA: Dziękuję wszystkim za odpowiedź :) Teraz rozumiem, dlaczego nie mogę prowadzić jeden sygnał z wielu procesów (przynajmniej w sposób, w jaki chciałem go do pracy).

+0

Czy zegary odzumi i zbroji są po prostu sygnałami? –

+0

To są po prostu sygnały – xx77aBs

Odpowiedz

5

Jeśli chcesz zsyntetyzuj swój projekt dla prawdziwego układu FPGA lub ASIC, będziesz musiał pomyśleć o VHDL pod względem rzeczywistego sprzętu (przewody, klapki, bramki itp.). Jeśli chcesz wykonać wykrywanie rosnącego poziomu w sprzęcie Będziesz potrzebował zegara systemowego, który napędza flip-flop. Biorąc pod uwagę twój oryginalny przykładowy kod, nie wydaje się, że zbroji lub oduzmi są zegarami systemowymi, ale tylko sygnałami std_logic. Napisałem ten przykład kodu zakładając podstawową funkcjonalność z twojego przykładu, mam nadzieję , możesz weź mój kod i komentarze i osiągnij to, czego potrzebujesz.

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

entity example is 
    port (Reset  : in std_logic; 
     SysClk  : in std_logic; 
     zbroji  : in std_logic; 
     oduzmi  : in std_logic; 
     ulaz_broj : in std_logic; 
     oduzima : out std_logic; 
     ucitanPrvi : out std_logic; 
     broj1  : out std_logic 
     ); 

end example; 

architecture Behavioral of example is 

    -- Delayed version of input signals (1 clock cycle delay) 
    signal zbroji_d : std_logic; 
    signal oduzmi_d : std_logic; 

    signal zbrojiRE : std_logic; 
    signal oduzmiRE : std_logic; 

begin 

    -- Generate 1 clock cycle delayed version of 
    -- signals we want to detect the rising edge 
    -- Assumes active high reset 
    -- Note: You should only use the rising_edge macro 
    -- on an actual global or regional clock signal. FPGA's and 
    -- ASICs place timing constraints on defined clock signals 
    -- that make it possible to use rising_edge, otherwise, we have 
    -- to generate our own rising edge signals by comparing delayed 
    -- versions of a signal with the current signal. 
    -- Also, with any respectable synthesizer/simulator using 
    -- rising_edge is almos exactly the same as (clk'event and clk='1') 
    -- except rising_edge only returns a '1' when the clock makes a 
    -- valid '0' to '1' transition. (see link below) 
    EdgeDetectProc : process (Reset, SysClk) 
    begin 
    if Reset = '1' then 
     zbroji_d <= '0'; 
     oduzmi_d <= '0'; 
    elsif rising_edge(SysClk) then 
     zbroji_d <= zbroji; 
     oduzmi_d <= oduzmi; 
    end if; 
    end process EdgeDetectProc; 

    -- Assert risinge edge signals for one clock cycle 
    zbrojiRE <= '1' when zbroji = '1' and zbroji_d = '0' else '0'; 
    oduzmiRE <= '1' when oduzmi = '1' and oduzmi_d = '0' else '0'; 

    -- Assumes that you want a single cycle pulse on ucitanPrvi on the 
    -- rising edege of zbroji or oduzmi; 
    ucitanPrvi <= zbrojiRE or oduzmiRE; 

    -- Based on your example, I can't tell what you want to do with the 
    -- broj1 signal, but this logic will drive broj1 with ulaz_broj on 
    -- either the zbroji or oduzmi rising edge, otherwise '0'. 
    broj1 <= ulaz_broj when zbrojiRE = '1' else 
      ulaz_broj when oduzmiRE = '1' else 
      '0'; 

    -- Finally, it looks like you want to clear oduzima on the rising 
    -- edge of zbroji and assert oduzima on the rising edge of 
    -- oduzmi 
    LatchProc : process (Reset, SysClk) 
    begin 
    if Reset = '1' then 
     oduzima <= '0'; 
    elsif rising_edge(SysClk) then 
     if zbrojiRE = '1' then 
     oduzima <= '0'; 
     elsif oduzmiRE = '1' then 
     oduzima <= '1'; 
     end if; 
    end if; 
    end process LatchProc; 

end Behavioral; 

Poprzedni kod zakłada, że ​​masz zegar systemowy. W symulatorze jak Modelsim (w wersji bezpłatnej student), można wygenerować zegar 100 MHz z kodem nie synthesizable testbench tak ...

ClockProc : process 
begin 
    SysClk <= '0'; 
    wait for 5 ns; 
    SysClk <= '1'; 
    wait for 5 ns; 
end process ClockProc; 

w rzeczywistej FPGA/ASIC realizacji, będzie prawdopodobnie chcesz użyć zewnętrzny oscylator, który uruchamiasz w swoim chipie, przekazuje sygnał do DCM (Digital clock manager), który wyprowadzi bardzo czysty sygnał zegarowy do całej twojej logiki VHDL, dzięki czemu możesz mieć darmowy projekt.

I wreszcie, tutaj jest wielki wyjaśnienie różnic między rising_edge i (clk'event i CLK = '1')

http://vhdlguru.blogspot.com/2010/04/difference-between-risingedgeclk-and.html

nadzieję, że pomoże.

+0

Wow, dzięki za szczegółowy przykład :) – xx77aBs

3

Jeśli sterujesz sygnałem std_logic z więcej niż jednego procesu (i pamiętaj, że ciągłe przyporządkowanie poza procesem również tworzy domyślny proces!), Wszystkie z wyjątkiem jednego muszą prowadzić do sygnału Z. Do pierwszego przybliżenia, funkcja rozdzielczości (która decyduje o tym, jaka powinna być końcowa wartość) da X s, chyba że tak się stanie.

Nie jestem pewien, jak najlepiej, aby zmienić swój kod - trzeba zdecydować, kiedy dany proces powinien nie jazdy sygnał i go prowadzić Z w tym punkcie.


pełnej definicji tego, jak wielu kierowców są rozwiązane jest zdefiniowany w pakiecie ieee.std_logic_1164 i obejmuje wszystkie możliwości, takie jak 1 i L jazdy itp IEEE dostać shirty o prawie autorskim, więc jestem Nie opublikujemy tutaj nawet fragmentu, ale będziesz mógł go znaleźć w źródłowych bibliotekach symulatora.

2

Sygnały pochodzące z wielu procesów to zły pomysł, chyba że naprawdę wiesz, co robisz. Możesz ponownie napisać ten kod w jednym takim procesie.

process (zbroji, oduzmi) 
begin 
    if rising_edge(zbroji) then 
     oduzima <= '0'; 
     ucitanPrvi <= '1'; 
     broj1 <= ulaz_broj; 
    end if; 
    if rising_edge(oduzmi) then 
     oduzima <= '1'; 
     ucitanPrvi <= '1'; 
     broj1 <= ulaz_broj; 
    end if; 
end process; 

Zauważ, że jeśli to zrobisz, a otrzymasz narastającą zarówno zbroji & oduzmi następnie oduzima dostanie wartość 1 jak to się dzieje w ostatnim w tym procesie. Przed próbą ustawienia go na 0 i 1 w tym samym czasie. To by symulowało X i prawdopodobnie nie zsyntetyzowało. Gdyby to było syntezować, łączyłbyś moc i ziemię w projekcie CMOS.


Alternatywną metodą jest, aby każdy proces kierowania To własną wersję sygnału, a następnie rozwiązać je na zewnątrz, co kiedykolwiek funkcjonować lubisz (lub inny proces). W tym przypadku użyłem or:

process (zbroji) 
begin 
    if rising_edge(zbroji) then 
     ucitanPrvi_1 <= '1'; 
    end if; 
end process; 

process (oduzmi) 
begin 
    if rising_edge(oduzmi) then 
     ucitanPrvi_2 <= '1'; 
    end if; 

end process; 

ucitanPrvi <= ucitanPrvi_1 or ucitanPrvi_2; 
+0

O ile zbroji i oduzmi nie są zegarami, nie użyłbym instrukcji rising_ingge. Myślę, że alternatywna metoda jest lepsza z dwóch metod, które zaproponowałeś. –

+0

Instrukcja rosnącej krawędzi pochodzi z oryginalnego kodu. Ja też bym tego nie używał. –

1

ile zbroji i oduzmi są oddzielne zegary to moja zaleca wdrożenie

ten rejestruje zbroji i oduzmi i sprawdza, czy wartość w rejestrze jest przeciwieństwem oryginału sygnał. Powinno to nastąpić tylko wtedy, gdy zbroji/oduzmi przejdzie od 0 do 1, a rejestr nie zaktualizował jeszcze zmiany sygnału.

process (clk) 
begin 
    if rising_edge(clk) then 
     if zbroji = '1' and zbroji_old = '0' then 
      oduzima <= '0'; 
      ucitanPrvi <= '1'; 
      broj1 <= ulaz_broj; 
     elif oduzmi = '1' and oduzmi_old = '0' then 
      oduzima <= '1'; 
      ucitanPrvi <= '1'; 
      broj1 <= ulaz_broj; 
     end if; 
     zbroji_old <= zbroji; 
     oduzmi_old <= oduzmi; 
    end if; 
end process; 

Wygląda na to, że ucitanPrvi i broj1 są zawsze tym samym. Albo sygnały są bezużyteczne, to był orignally literówka lub tworzysz „Update” impulsy w takim przypadku musisz oświadczenie

ucitanPrvi <= '0' 
    broj1 <= (others=>'0') -- assumed reset? 

następstwie if (rising_edge (CLK) oświadczenie

0

Gdy zmieniasz tę samą wartość sygnału z wielu procesów, symulator będzie tworzyć wiele sterowników sygnału dla tego. Ich wyniki będą zasadniczo nierozwiązane. Pomyśl o tym jako o wyjściu wielu połączonych ze sobą bramek, czego się spodziewasz?

Aby temu zaradzić, musisz zaimplementować funkcję rozdzielczości, która steruje sygnałem wyjściowym.

http://www.csee.umbc.edu/portal/help/VHDL/misc.html#resf

Jeśli masz jakiekolwiek wątpliwości, daj mi znać.