logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Jak napisać program VHDL dla 6-ściennej kostki z wyświetlaczem i LED?

frites 29 Gru 2005 19:00 4063 15
REKLAMA
  • #1 2127495
    frites
    Poziom 11  
    Posty: 7
    Musze napisac program w VHDL-u symulujacy 6 cyfrowa kostke do gry.
    Liczby maja generowac sie za pomoca zegara, po nacisnieciu przycisku liczba ma wyswietlic sie na wyswietlaczu alfanumerycznym. Proces losowania tazke musi byc widoczny na wyswietlaczu. Kostke juz fizycznie zbudowalem tylko mam kolopoty z programem :/.

    Dodano po 48 [minuty]:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

    entity kost is
    Port ( ledy : out std_ulogic_vector(14 downto 0);
    w: in std_logic_vector(1 downto 0));

    end kost;

    architecture Behavioral of kost is

    begin
    if w ='1' then
    for a in 0 to 999 loop

    ledy <= "011000000001000";
    <= "110110110101000";
    <= "111100100101010";
    <= "011001111010101";
    <= "101101101011101";
    <= "101111111110111";
    end loop ;
    end if;


    end Behavioral;
    Napisalem taki programik. Zapomnialem dodac, ze kostka oprocz wyswietlacza ma takze ledy ustawione jak kropki na zwyklej kostce.
    To dobiero moje poczatki z vhdl-em wiec prosze o wyrozumialosc. Za wszytskie podpowiedzi z gory dziekuje.

    :D:D:D
    Moderowany:


    Nie stosuj ozdobników w temacie
    And!

    Załączniki:
    • Jak napisać program VHDL dla 6-ściennej kostki z wyświetlaczem i LED? kostka.JPG (80.67 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • REKLAMA
  • #2 2132218
    strdaniel
    Poziom 20  
    Posty: 357
    Pomógł: 29
    Ocena: 4
    program który napisałeś jest lekko mówiąc bez sensu
    bo syntezator nie wie co ma zrobić jak wykonać taką pętle w sprzęcie

    musisz napisać process z listą czułości, taktowany zegarem (jego zboczem) poszukaj przykłądów w literaturze
    taki proces będzie zmieniał pętle przy każdym takcie zegara jeśli bedzie spełniony twój warunek
    i taki układ syntezator już łyknie

    pozdrawiam

    ps. szukaj procesów albo zobacz sobie jakiekolwiek przykłądy
    www.opencores.com
  • #3 2132737
    bis
    Poziom 21  
    Posty: 274
    Pomógł: 54
    Ocena: 3
    Możesz to zrobić tak:
    na całość składają się cztery (niezależne) procesy. 1) kluczowanie zegara (sygnału który napedza całą zabawkę) przyciskiem. Jeżeli przycisk jest wcisnięty to zatrzymujesz zegar. 2) licznik trzy bitowy przyjmujacy tylko sześć stanów zliczający ten kluczowany sygnał zegarowy. 3) dekoder stanu licznika na kod 7'mio segmentowego wyswietlacza. 4) dekoder stanu licznika na kod kropek na ledach. Całośc działa tak, że jezeli przycisk jest puszczony to zegar napędza licznik a wyjście z licznika napędza, poprzez dekodery ledy i wyswietlacz (więc widać mrugajace zmiany, z częsotliwością zegara. Jeżeli przycisk zostanie nacisnięty, to zegar sie zatrzymuje, licznik stoi na aktualnym wskazaniu, wyswietlacz i ledy pokazują jego aktualny stan. To jest tylko jedna z możliwości wykonania. Można zmienić proces (2) na rejestr przesówny o 6 bitach długości z "krążącą jedynką" i dopowiednio zmienić dekodery (3) i (4). Albo można rozbudować wstawiając w proces (2) jakiś generator pseudolosowy (poszukaj pod hasłem LFSR).
    Wygodniej będzie tobie opisać osobno wektor ledów wyświetlacza, wektor ledów kropek, wejście przycisku i wejście jakiegoś sygnału zegarowego(do napędznia całości)(chyba go brakuje w projekcie)
  • REKLAMA
  • #4 2133183
    strdaniel
    Poziom 20  
    Posty: 357
    Pomógł: 29
    Ocena: 4
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;

    entity kost is
    Port (
    clk : in std_logic;
    ledy : out std_logic_vector(14 downto 0);
    w: in std_logic_vector(1 downto 0));

    end kost;

    architecture Behavioral of kost is

    signal ledy_q : std_logic_vector(14 downto 0);

    begin

    process (clk)
    begin
    if clk'event and clk = '1' then
    if (w = '0')
    case ledy_q is

    when "011000000001000" => ledy_q <= "110110110101000";
    when "110110110101000" => ledy_q <= "111100100101010";
    when "111100100101010" => ledy_q <= "011001111010101";
    when "011001111010101" => ledy_q <= "101111111110111";
    when "101111111110111" => ledy_q <= "011000000001000";
    when others => ledy_q <= "011000000001000";
    end case;
    end if;
    end if;

    end process;

    process (clk)

    if clk'event and clk = '1' then
    ledy <= ledy_q;
    end if;

    end process
    end Behavioral;

    mam jeszcze taką formalną uwage - jeżeli jest to model behavioralny to z założenia nie służy on to fizycznego syntezowania i uruchamiania na kostce fpga, bo jeśli poczyta się literature to behavioralne modele sa budowane z instrukcji które się nie syntezują i służą tylko jako modele referencyjne do testowania danego układu już napisanego jako syntezowalne

    :D
  • #5 2134270
    frites
    Poziom 11  
    Posty: 7
    Dzieki za podpowiedzi!. Na pewno wezme je sobie do serca :).... i do glowy!.
    To dopiero moje poczatki z vhdl-em. Nie umiem sie jeszcze przestawic z C na sposob programowania w vhdl..Usilnie nad tym pracuje.
    Pozdrawiam i zycze szczesliwego nowego roku!:D:D

    Dodano po 47 [minuty]:

    Jak na razie przetstowalem program strdaniela i troche w nim bledow. Postaram sie z nimi uporac i dam znac za kilka dni..:D
  • #6 2138352
    strdaniel
    Poziom 20  
    Posty: 357
    Pomógł: 29
    Ocena: 4
    no niestety żeby dobrze projektowac w vhdlu nie można wzorowac się na c bo to zupełnie co innego ... lepiej przestawiac się z projektowania systemów cyfrowych oraz z ich budowy, jeśli tego się nie opanuje to vhdla też pewnie nie
    :D
  • REKLAMA
  • #7 2146960
    frites
    Poziom 11  
    Posty: 7
    Sprobowalem zmienic swoj program. Zastosowalem licznik pierscieniowy i zmienilem deodery. Zrezygnowalem z wyswietlacza siedmiosegmentowego. Beda tylko kropki. W Zwolinskim znalazlem program symulujacy Licznik Johnsona i przerobilem go na pierscieniowy. Skorzytsalem z waszycvh podpowiedzi. Jednak nadal nie potrafie poprawnie napisac programu.
    Nie mam pojecia. Jak uzaleznic Dekoder od Licznika, a te od zegara. Nie wiem jak polaczyc ze sopba processy.....:/.
    Jezeli ktos wie jakie bledy popelnilem to bardzo prosze o pomoc......
    Z gory dzieki.
    Oto moj program:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.STD_LOGIC_ARITH.ALL;
    use IEEE.STD_LOGIC_UNSIGNED.ALL;
    use ieee.numeric_std.all;

    entity abba is
    generic (n: natural :=6);
    Port ( clk : inout std_ulogic;
    reset : in std_ulogic;
    count : out std_ulogic_vector(n-1 downto 0);
    w : in std_logic;
    ledy: out std_logic_vector( n downto 0) );
    end abba;
    architecture Behavioral of abba is
    signal ledy_a: std_logic_vector( n downto 0);
    begin
    p0: process(clk, reset) is
    variable reg: std_ulogic_vector(n-1 downto 0);
    begin
    if reset='1' then
    reg :=( others => '0');
    elsif rising_edge(clk) then
    if (w='0') then
    reg := reg(0) & reg(n-1 downto 0);
    case ledy_a is
    when "100000" => ledy_a <= "0001000";
    when "010000" => ledy_a <= "0100010";
    when "001000" => ledy_a <="0111001";
    when "000100" => ledy_a <="1010101";
    when "000010" => ledy_a <="1011101";
    when "000001" => ledy_a <="1110111";

    count <= reg;
    end case;
    end if;
    end if;
    end process p0;

    p1: process(clk) is
    begin
    if clk'event and clk='1' then
    ledy <= ledy_a;
    end if;
    end process p1;
    end Behavioral;
  • REKLAMA
  • #8 2149692
    strdaniel
    Poziom 20  
    Posty: 357
    Pomógł: 29
    Ocena: 4
    architecture Behavioral of abba is
    signal ledy_a: std_logic_vector( n downto 0);
    begin
    p0: process(clk, reset) is
    variable reg: std_ulogic_vector(n-1 downto 0);
    begin
    if reset='1' then
    reg :=( others => '0'); --- czemu reg a potem ledy_a
    elsif rising_edge(clk) then --- czemu nie clk'event and clk='0'
    if (w='0') then
    reg := reg(0) & reg(n-1 downto 0);
    case ledy_a is
    when "100000" => ledy_a <= "0001000";
    when "010000" => ledy_a <= "0100010";
    when "001000" => ledy_a <="0111001";
    when "000100" => ledy_a <="1010101";
    when "000010" => ledy_a <="1011101";
    when "000001" => ledy_a <="1110111";

    count <= reg;
    end case;
    end if;
    end if;
    end process p0;

    witam na wstępie chciałęm prosić żeby kolega mówił o co chodzi bo jak sie kompiluje vhd to kompilator daje nam sporo inforamcji więc po prostu niech kolega wypisuje co on albo nawet cytuje dołąnczając konkretne kawałki kodu albo i cały proces to nam ułatwi życie trzeba też pisać czy układ wysypuje się na kompilacji syntezie czy implementacji to też może pomóc
    a teraz do rzeczy - proces który się tworzy jeśli ma być syntezowalny bez błędów to powinien jeśli jest stworzony do sterowania sygnałem reg sterować tym sygnałem jeśli do ledy_a to sterowac sygałem ledy_a
    w najgorszym przypadku jeden proces jeśli steruje więcej niż jednym sygnalem to trzeba w kazdej gałęzi każdy sygnał wysterować
    a u kolegi reset resetuje reg a wogole pomija ledy_a
    dalej jadąc case w ostatniej linii powienien mieć when others co eliminuje błędne stany mogące w liczniku wystąpić
    a dalej jadąc to przypisanie count <= reg też wydaje mi sięstrasznie niefortunne bo można to zrobić w osobnym procesie bo to też nie ma sensu w tym samym procesie zmieniać sygnał i ten sam sygnał przypisywać do innego syganału -- osobny proces trzeba zrobić
    no i na koniec to rising_edge ja bym zamienił na clk'event and clk='0' szczerze mówiąc nie pamietam o co chodzi ale z tym też były jakieś problemy musiałbym poszukać - albo przynajmniej upewnić się ze jest to syntezowalne i ze się dobrze impelemntuje
    no i tak ogólnie to kolega natworzył całą mase latchy
    drobne kolekty i będzie dobrze
    pisz pytaj tylko więcej szczegółów co nie działa prosze

    :D
  • #9 2150212
    bis
    Poziom 21  
    Posty: 274
    Pomógł: 54
    Ocena: 3
    Może tak,

    
    entity abba is 
    Port ( 
       clk : inout std_ulogic; 
       reset : in std_ulogic; 
    
       w : in std_logic;    ---- gdy w jest '1' to zliczanie, w=0 zatrzymuje
       ledy: out std_logic_vector( 6 downto 0);   -- sterowanie kropkami
       ledyseg: out std_logic_vector( 7 downto 0) -- sterownie segmentami wyświetlacza
     
    ); 
    end abba; 
    
    architecture Behavioral of abba is 
       signal licznik : std_logic_vector( 2 downto 0);
       signal cntclk : std_logic;
    begin
    
    -- sterowanie zegarem
     cntclk <= '1' when (clk and w) else '0';  
    
    -- dekoder na kropki
      with( licznik ) select
       ledy <= 
                   "0001000" when "000", --1
                   "0100010" when "001", --2
                   "0111001" when "010", --3
                   "1010101" when "011", --4
                   "1011101" when "100", --5
                   "1110111" when "101", --6
                   "1110111" when others ; --6,  tak dla porządku
    
    
    -- dekoder na segmenty wyświetlacza
      with( licznik ) select
       ledyseg <= 
                   "00010000" when "000", --1
                   "01000100" when "001", --2
                   "01110010" when "010", --3
                   "10101010" when "011", --4
                   "10111010" when "100", --5
                   "11101110" when "101", --6
                   "11101110" when others ; --6,  tak dla porządku
    
    -- licznik, przyjmuje tylko 6 stanów gdy dobrze zresetowany
    Counter: process(cntclk, reset) is 
    begin
    if (reset = '1') then
       licznik <="000"
    elsif rising_edge(cntclk) then
       if( licznik = "101") then
          licznik <= "000";
       else
          licznik <= licznik+"001";
    end if;
    
     
    end Behavioral;
     


    Potraktuj to jako szkielet, nie kompilowałem tego mgą być jakieś błędy składni. Wartości wyjściowe w dekoderze wyświetlacza wpisz odpowiednio do twoich połączeń. Teoretycznie jest mały mankament tego rozwiązania, po włączeniu zasilania, ale bez resetu, początkowa wartość licznika może być błędna (stany 6 i 7) wtedy przez dwa cykle "losowania" będzie pokazywał 6 na kropkach i wyświetlaczu. Jeżeli będziesz chciał przerobić na licznik z krążącą jedynką to "tylko" zmienisz proces licznika i dekodery ale struktura będzie identyczna. (pamiętaj, że wtedy, reset musi ustawieć w liczniku tę "1" która ma potem krążyć).
    Zapis z rising_edge( signal) jest jak najbardziej prawidłowy i syntetyzowalny, a zawsze mniej pisania i widac o co chodzi.
    A (clk'event and clk=0) to będzie falling_edge(clk).
  • #10 2151034
    frites
    Poziom 11  
    Posty: 7
    Do strdaniel:
    przy case( 26 linijka) pojawia sie sie blad:
    ERROR:HDLParsers:839 - F:/xilinx_webpack/bin/abba/abba.vhd Line 26. Selector (Signal 'ledy_a' of type std_logic_vector) is a
    n unconstrained array.

    Do Bis:
    Pojawily sie 3 bledy. 2 drobne: nie dales end if ; i end process; na koncu.
    3 blad( moze tez drobny :P) W linijce 25 przy cntlk:
    ERROR:HDLParsers:826 - F:\xilinx_webpack\bin\abba/abba.vhd Line 25. When condition and is not of type boolean.
  • #12 2152308
    griva
    Poziom 17  
    Posty: 203
    Pomógł: 12
    Ocena: 1
    
    
    -- sterowanie zegarem
     cntclk <= '1' when (clk and w) else '0';  
    
     

    gate-owanie zegara to najgorsza rzecz jaka mozna zrobic w VHDL-u :), nawet narzedzia Xilinxa wykrywaja to i pisza co sadza o taki stylu kodowania ...

    takze to jest do wyremowania

    to samo uzyskamy uzywajac enable

    
    -- licznik, przyjmuje tylko 6 stanów gdy dobrze zresetowany
    Counter: process(clk, reset) is 
    begin
    if (reset = '1') then
       licznik <= (others=>'0'); -- teraz mozesz zmieniac dlugosc licznika bez potrzeby dopisaywania zer
    elsif rising_edge(clk) then
     if  w = '1'  then -- ogolnie to jestem przeciwnikiem nazywania czegos jedna literka, albo zmienna typu moja1, totalna niekonsekwencja i ....
       if( licznik = "101") then
          licznik <= (others=>'0');
       else
          licznik <= licznik + 1;
       end if;
    end if;
    
     
    end rtl; --tak jest zrozumialej
     
  • #13 2457898
    zlotawyy
    Poziom 11  
    Posty: 14
    a co byscie powiedzili o tym? jestem swiezy w VHDL i opinie beda dla mnie cenne.


    entity ise3 is
    Port ( clock: in STD_LOGIC;
    przycisk : in STD_LOGIC;
    y: out std_logic_vector (0 to 2));
    end ise3;

    architecture Behavioral of ise3 is
    type MyType is (S1,S2,S3,S4,S5,S6);
    signal aktualny, nastepny: MyType;

    begin

    process(clock)

    begin

    if (clock'event and clock = '1') then
    aktualny <= nastepny;

    end if;

    end process;

    process(aktualny,przycisk)
    begin
    case przycisk is
    when '0' => --wcisniety

    case aktualny is
    when S1 =>
    y <= "001";
    nastepny <= S2;
    when S2 =>
    y <= "010";
    nastepny <= S3;
    when S3 =>
    y <= "011";
    nastepny <= S4;
    when S4 =>
    y <= "100";
    nastepny <= S5;
    when S5 =>
    y <= "101";
    nastepny <= S6;
    when S6 =>
    y <= "110";
    nastepny <= S1;
    when others =>
    y <= "000";
    nastepny <= S1;
    end case;
    when '1' => --wycisniety

    y <= "000";



    when others =>

    y <= "000";
    end case;
    end process;

    end Behavioral;

    Dodano po 23 [minuty]:

    mam od razu pytanie.

    czy nie lepiej zamienic fragment kodu dotyczacy przycisku na

    when '1' =>

    y <= y;
    nastepny <= nastepny;



    when others =>

    y <= y;
    nastepny <= nastepny;


    to znaczy jak to jest z tym okreslaniem wszytskich wyjsc dla ukladu kombinacyjnego. czy jest to bezwzglednie konieczne? nie mozna sobie pozwolic zeby powstal zatrzask?

    ratuje mnie zapis y <= y, ale wtedy musz ezmienic port y na inout. czy to ma jakies negatywne konsekwencje?> Cadence nie chcial mi tego przesymulowac.
  • #14 2458338
    griva
    Poziom 17  
    Posty: 203
    Pomógł: 12
    Ocena: 1
    zapis y <= y jest bez sensu, bo i tak narzedzie syntezy go wywali. Pozatym jest niezgodne z syntaxem VHDL-a,
    dobra maniera jest operowanie na sygnalach wtedy moze na nie pisac i je czytac, czyli
    ...
    signal y_int : std_logic;

    begin

    y <= y_int;

    ...

    Do tego jak dla mnie to ten przycisk powinien enablowac przypis:
    if przycisk = '0' then
    aktualny <= nastepny;
    else
    aktualny <= Sx;
    end if;

    taki case w casie to dodatkowa logika kombinacyjna i brzydki kod.

    Musisz pamietac o jednym, VHDL to opis sprzetu, wszystko co napiszesz zamieni na brameczki i przerzutniki, staraj sie pomagac narzedziom sytnezy, czyli musisz kontrolowac co piszesz i mniej wiecej wiedziec co z tego powstanie. To ze rozne zapisy jakichs funkcji symuluja sie tak samo nie znaczy ze powstanie to samo, ... wierz mi takie podejscie zaowocuje przy uruchamianiu na sprzecie.

    I pamietaj, jesli nie musisz to NIGDY nie uzywaj latchy! chyba ze jestes specjalista od logiki asynchronicznej ;-))
  • #15 2458712
    zlotawyy
    Poziom 11  
    Posty: 14
    Do tego jak dla mnie to ten przycisk powinien enablowac przypis:
    if przycisk = '0' then
    aktualny <= nastepny;
    else
    aktualny <= Sx;
    end if;



    Hmm... rozdzielilem to na dwa procesy, tak aby jeden byl typowo sekwencyjny, a drugi kombinacyjny. Czy uwazasz, iz nalezy to zlac w jeden proces? I w tym procesie, najpierw sprawdzenie zbocza clocka, a od razu zanim sprawdzenie przycisku (kolejny if)?Czy tez sprawdzenie przycisku ma sie znalezc w procesie obecnie badajacym zbocze? Jakby nie bylo beda dwa ify pod rzad, tego sie nie uniknie, a taki if to chyba mniej wiecej to samo co case, przynajmniej symulacyjnie :-)


    I pamietaj, jesli nie musisz to NIGDY nie uzywaj latchy! chyba ze jestes specjalista od logiki asynchronicznej ;-))

    no wlasnie, najchetniej nigdy bym nie uzywal. z tego co zauwazylem to np. reset jest robiony asynchronicznie, choc prawde mowiac czy nie lepiej doczekac te chwileczke do zbocza zegara i dopiero wyzerowac?

    Zeby uniknac zatrzaskow, musze cos przypisac do wszystkich wyjsc, przy kazdym rozgalezieniu. czy gra jest warta swieczki? tzn. trzeba nieraz dodac mase kodu, gdy mam np. 15 wyjsc, i niezalezy mi na tym co na nich bedzie, czy musze na sile cos przypisywac?

    dzieki za wskazowki,
    pozdrawiam
    Wojtek
  • #16 2466103
    griva
    Poziom 17  
    Posty: 203
    Pomógł: 12
    Ocena: 1
    1. Ten przycisk nie stworzy dodatkwej logiki w moim procesie, to bedzie set na przerzytnikach.
    Dodawanie linii typu cos <= cos nie ma sensu bo i tak narzedzie syntezy to wyrzuci, polecam czytanie logow z syntezy, sa pouczajace ;-)

    2. Reset i zegary to podstawa ukladu, jesli masz zle zaprojektowany reset ukladu lub/i zle rozdzielone domeny czasowe to mozesz osiagnac emeryture ;-).
    Reset zawsze powinien byc! najlepiej asynchroniczny.
    To ze tam mozna poczekac kilka taktow i samo sie zresetuje to najwieksze niechlujstwo jakie slyszalem i widzialem :) - wyobras sobie ze piszesz kawalek kodu do ukladu ktory symuluje sie 3 dni, uklad nie wyszedl prawidlowo z resetu, bo jeden modulik trzyma 'U' na wyjsciu potem 'U' poszlo na wejscia i wyszlo 'X' - Twoi koledzy "pokochaja" Cie z miejsca a szczegolnie project leader ;-).
    Takie podejscie tworzy milion problemow, pierwszy z brzegu moze nie wyszukany sprobuj zasymulowac dwojke liczaca bez resetu :]

Podsumowanie tematu

✨ Dyskusja dotyczyła problemów z napisaniem programu w VHDL symulującego 6-ścienną kostkę do gry z wyświetlaczem alfanumerycznym i diodami LED. Autor chciał, aby liczby generowały się za pomocą zegara, a po naciśnięciu przycisku aktualna liczba była wyświetlana, przy czym proces losowania miał być widoczny na wyświetlaczu. Wskazano, że użycie pętli for w architekturze jest niepoprawne, ponieważ syntezator sprzętu nie potrafi jej zrealizować. Zamiast tego zalecano implementację procesów taktowanych zegarem z listą czułości, które zmieniają stan licznika lub rejestru pierścieniowego. Zaproponowano podział funkcjonalności na kilka procesów: sterowanie zegarem przyciskiem, licznik 3-bitowy z sześcioma stanami, dekoder stanu licznika na kod wyświetlacza 7-segmentowego oraz dekoder na diody LED. Podkreślono, że zamiast "gate'owania" zegara lepiej stosować sygnał enable. Wskazano na konieczność stosowania resetu asynchronicznego i unikania latchy. Przykłady kodu zawierały implementacje liczników pierścieniowych i Johnsona, dekoderów oraz obsługi przycisku. Zwrócono uwagę na różnice między programowaniem w C a opisywaniem sprzętu w VHDL, podkreślając potrzebę zrozumienia projektowania systemów cyfrowych. Dyskusja zawierała także uwagi dotyczące poprawnej składni VHDL, obsługi sygnałów i procesów sekwencyjnych oraz kombinacyjnych, a także praktyczne wskazówki dotyczące syntezy i testowania kodu.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA