Aktyw Forum
Zarejestruj się na forum.ep.com.pl i zgłoś swój akces do Aktywu Forum. Jeśli jesteś już zarejestrowany wystarczy, że się zalogujesz.
Sprawdź punkty Zarejestruj sięVHDL - licznik mod100
Moderatorzy:Jacek Bogusz, Moderatorzy
Mam problem ze zrobieniem licznika mod100, który zlicza impulsy zegarowe (niekoniecznie pokolei, że 1,2,3 itp. tylko aby tak zliczał, aby oko ludzkie na wyświetlaczu zobaczyło liczby). Licznik w zależności od tego czy switch o nazwie 'kierunek' jest 1 lub 0 to liczy w górę lub w dół. No i właśnie mam 2 problemy, że jak układowi powiedzieć, aby zliczał z pewnym opóźnieniem żeby oko ludzkie zdąrzyło zobaczyć te liczby (jak wprowadzę instrukcję wait fo 50ms w process(C) to mi błąd wywala przy Check syntax) oraz drugi problem to jak zrobić, że jak dojdzie zliczanie jednostek do 9 to, żeby potem na drugim wyświetlaczu mi powiększyło dziesiątki o 1 (coś kombinuje z nr-led). Mógłby ktoś popatrzeć, może by wiedział jak zmodyfikowac ten program by działał poprawnie.
I czy jest jakaś mozliwość nie mając płytki SPartana aby sprawdzić czy program działa poprawnie? Testembenchem tylko???
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity licznik is
port(C: in std_logic;
kierunek: in std_logic;
led: out std_logic_vector(0 to 6);
wys_led: out std_logic_vector(0 to 3));
end licznik;
architecture a1 of licznik is
signal nr_led: std_logic;
signal wyswietl: std_logic_vector(3 downto 0);
signal jednostki: std_logic_vector(3 downto 0);
signal dziesiatki: std_logic_vector(3 downto 0);
begin
clock: process(C)
begin --tutaj proboje wait for 50ms wprowadzic i sie nie da:(
if C'event and C='1' then
if kierunek = '0' then
jednostki <= jednostki + "0001";
if jednostki = "1001" then
jednostki <= "0000";
dziesiatki <= dziesiatki + "0001";
nr_led <= '1';
if dziesiatki = "1001" then
dziesiatki <= "0000";
end if;
end if;
else
jednostki <= jednostki - "0001";
if jednostki = "0000" then
jednostki <= "1001";
dziesiatki <= dziesiatki - "0001";
nr_led <= '1';
if dziesiatki = "0000" then
dziesiatki <= "1001";
end if;
end if;
end if;
end if;
end process clock;
--wybor wyswietlacz
with nr_led select
wys_led <= "1110" when '0',
"1101" when '1',
"1111" when others;
--wybor wartosci do wyswietlania
with nr_led select
wyswietl <= jednostki when '0',
dziesiatki when '1',
"1111" when others;
--konwerter kodu
with wyswietl select
led <= "1000000" when "0000",
"1111001" when "0001",
"0100100" when "0010",
"0110000" when "0011",
"0011001" when "0100",
"0010010" when "0101",
"0000010" when "0110",
"1111000" when "0111",
"0000000" when "1000",
"0010000" when "1001",
"1111111" when others;
end a1;
I czy jest jakaś mozliwość nie mając płytki SPartana aby sprawdzić czy program działa poprawnie? Testembenchem tylko???
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity licznik is
port(C: in std_logic;
kierunek: in std_logic;
led: out std_logic_vector(0 to 6);
wys_led: out std_logic_vector(0 to 3));
end licznik;
architecture a1 of licznik is
signal nr_led: std_logic;
signal wyswietl: std_logic_vector(3 downto 0);
signal jednostki: std_logic_vector(3 downto 0);
signal dziesiatki: std_logic_vector(3 downto 0);
begin
clock: process(C)
begin --tutaj proboje wait for 50ms wprowadzic i sie nie da:(
if C'event and C='1' then
if kierunek = '0' then
jednostki <= jednostki + "0001";
if jednostki = "1001" then
jednostki <= "0000";
dziesiatki <= dziesiatki + "0001";
nr_led <= '1';
if dziesiatki = "1001" then
dziesiatki <= "0000";
end if;
end if;
else
jednostki <= jednostki - "0001";
if jednostki = "0000" then
jednostki <= "1001";
dziesiatki <= dziesiatki - "0001";
nr_led <= '1';
if dziesiatki = "0000" then
dziesiatki <= "1001";
end if;
end if;
end if;
end if;
end process clock;
--wybor wyswietlacz
with nr_led select
wys_led <= "1110" when '0',
"1101" when '1',
"1111" when others;
--wybor wartosci do wyswietlania
with nr_led select
wyswietl <= jednostki when '0',
dziesiatki when '1',
"1111" when others;
--konwerter kodu
with wyswietl select
led <= "1000000" when "0000",
"1111001" when "0001",
"0100100" when "0010",
"0110000" when "0011",
"0011001" when "0100",
"0010010" when "0101",
"0000010" when "0110",
"1111000" when "0111",
"0000000" when "1000",
"0010000" when "1001",
"1111111" when others;
end a1;
A co to jest wait 50 w przypadku ukladu programowalnego?? VHDL to nie jest jeyzk sekwencyjny. Komendy nie "wykonuja" sie jedna po drugiej tak jak to ma miejsce w C/Pascalu. A stad m.in wynika ze w tym wypadku zaden wait Ci nic nie da.
Teraz co bys chcial? Licznik ma zliczac jakies konkretne impulsy, czy tez poprostu demonstrowac ze takie cos dziala.
Jesli to pierwsze, to... ekhem, jak sobie wyobrazasz, chce cos zmierzyc, ale to ja mu powiem ile chce uzyskac, a zrodlo sie ma DOSTOSOWAC do tego co ma mi wyjsci??
Jesli drugie, to... podziel sobie clock przez x, tak zeby taktowanie licznika wynosilo ilestam ms. (i raczej wiecej niz 50ms, bo tego raczej tez nie zauwazysz).
Teraz co bys chcial? Licznik ma zliczac jakies konkretne impulsy, czy tez poprostu demonstrowac ze takie cos dziala.
Jesli to pierwsze, to... ekhem, jak sobie wyobrazasz, chce cos zmierzyc, ale to ja mu powiem ile chce uzyskac, a zrodlo sie ma DOSTOSOWAC do tego co ma mi wyjsci??
Jesli drugie, to... podziel sobie clock przez x, tak zeby taktowanie licznika wynosilo ilestam ms. (i raczej wiecej niz 50ms, bo tego raczej tez nie zauwazysz).
Odpowiedź druga. Właśnie chodzi mi o to, żeby taktowanie licznika wynosiło ileśtam ms żeby oko ludzkie zauważało zmiany tych cyferek. Niestety nie wiem jak zrobić taktowanie. Co, jak i gdzie dzielić? Przypuszczam, że coś trzeba dodac do tego fragmentu kodu:??
....
clock: process(C)
begin
if C'event and C='1' then
if kierunek = '0' then
....
bo chyba nie tak dzielić:
...
clock: process(C)
begin
C/100ms; --????
if C'event and C='1' then
if kierunek = '0' then
...
Wydawało mi się, że w process instrukcje wykonywane są sekwencyjnie i wait powinno zadziałać. A tak to wiem, że w architecture wszystkie instrukcje są współbieżne.
A takto poza tym wydaje się wszystko być dobrze ta współpraca wyswietlacza dziesiątek i jedności?
A nie ma żadnego takiego symulatora płytki takiego wirtualnego???
....
clock: process(C)
begin
if C'event and C='1' then
if kierunek = '0' then
....
bo chyba nie tak dzielić:
...
clock: process(C)
begin
C/100ms; --????
if C'event and C='1' then
if kierunek = '0' then
...
Wydawało mi się, że w process instrukcje wykonywane są sekwencyjnie i wait powinno zadziałać. A tak to wiem, że w architecture wszystkie instrukcje są współbieżne.
A takto poza tym wydaje się wszystko być dobrze ta współpraca wyswietlacza dziesiątek i jedności?
A nie ma żadnego takiego symulatora płytki takiego wirtualnego???
-
- -
- Posty:57
- Rejestracja:10 lis 2006, o 11:50
- Lokalizacja:Gdansk
Witam
A ja bym to zrobił tak ( zakładam kwarc 4MHz ):
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity COUNTER_MOD10 is
generic (
TIME_INTERVAL : integer := 800000; -- powinno byc 25 razy na sekunde
port (
CLK : in std_logic;
DIRECTION : in std_logic;
OUT : std_logic_vector(3 downto 0)
);
end COUNTER_MOD100;
architecture STRUCTURE of COUNTER_MOD10 is
signal REGISTER : std_logic_vector(3 downto 0);
signal PRESCALER : std_logic_vector(21 downto 0);
sognal INT_CLK : std_logic;
begin
PRESCALER_PROCESS: process(CLK,PRESCALER,INT_CLK)
begin
if CLK'event and CLK='1' then
if PRESCALER=INTERVAL then
PRESCALER<=(others=>'0');
else
PRESCALER<=PRESCALER+1;
INT_CLK<=not INT_CLK;
end if;
end if;
end process;
COUNTER_PROCESS: process(INT_CLK,REGISTER)
begin
if INT_CLK'event and INT_CLK='1' then
if DIRECTION='1' then
if REGISTER='0' then
REGISTER<="1001";
else
REGISTER<=REGISTER-1;
end if;
else
if REGISTER=9 then
REGSITER<="0000";
else
REGISTER<=REGISTER+1;
end if;
end if;
end if;
end process;
OUT<=REGISTER;
end STRUCTURE;
No ale nie sprawdziłem oczywiście kodu, przedstawilem tylko idee jak ja bym to zrobil.
I nie umiescilem tam dekodera na wyswietlacz ( powinien byc taki jak u kolegi ).
Powyższy kod ma jednak pare wad. W pozniejszym etapie zamienilbym binary countera ( PRESCALER ) na ripple countera ( zaoszczędzilbym w ten sposob duuuuuzo zasobow ).
Kazdy nastepny COUNTER_PROCESS moglby byc taki sam dla nastenych liczb mod10.
A jesli chodzi o symulator to mozesz urzyc MODELSIMA, tylko bys musial napisac TEST BENCH'a i zamienic CLK'event'y na rising_edge(CLK).
pozdrawiam
Bartek
A ja bym to zrobił tak ( zakładam kwarc 4MHz ):
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity COUNTER_MOD10 is
generic (
TIME_INTERVAL : integer := 800000; -- powinno byc 25 razy na sekunde
port (
CLK : in std_logic;
DIRECTION : in std_logic;
OUT : std_logic_vector(3 downto 0)
);
end COUNTER_MOD100;
architecture STRUCTURE of COUNTER_MOD10 is
signal REGISTER : std_logic_vector(3 downto 0);
signal PRESCALER : std_logic_vector(21 downto 0);
sognal INT_CLK : std_logic;
begin
PRESCALER_PROCESS: process(CLK,PRESCALER,INT_CLK)
begin
if CLK'event and CLK='1' then
if PRESCALER=INTERVAL then
PRESCALER<=(others=>'0');
else
PRESCALER<=PRESCALER+1;
INT_CLK<=not INT_CLK;
end if;
end if;
end process;
COUNTER_PROCESS: process(INT_CLK,REGISTER)
begin
if INT_CLK'event and INT_CLK='1' then
if DIRECTION='1' then
if REGISTER='0' then
REGISTER<="1001";
else
REGISTER<=REGISTER-1;
end if;
else
if REGISTER=9 then
REGSITER<="0000";
else
REGISTER<=REGISTER+1;
end if;
end if;
end if;
end process;
OUT<=REGISTER;
end STRUCTURE;
No ale nie sprawdziłem oczywiście kodu, przedstawilem tylko idee jak ja bym to zrobil.
I nie umiescilem tam dekodera na wyswietlacz ( powinien byc taki jak u kolegi ).
Powyższy kod ma jednak pare wad. W pozniejszym etapie zamienilbym binary countera ( PRESCALER ) na ripple countera ( zaoszczędzilbym w ten sposob duuuuuzo zasobow ).
Kazdy nastepny COUNTER_PROCESS moglby byc taki sam dla nastenych liczb mod10.
A jesli chodzi o symulator to mozesz urzyc MODELSIMA, tylko bys musial napisac TEST BENCH'a i zamienic CLK'event'y na rising_edge(CLK).
pozdrawiam
Bartek
Ok, dzięki Bartek. Rozumiem idee. Chodzi o to, że dzięki temu:
PRESCALER_PROCESS: process(CLK,PRESCALER,INT_CLK)
begin
if CLK'event and CLK='1' then
if PRESCALER=INTERVAL then
PRESCALER<=(others=>'0');
else
PRESCALER<=PRESCALER+1;
INT_CLK<=not INT_CLK;
end if;
end if;
end process;
tworzymy tak jakby drugi zegar, który ma stan = 0 przez 800000 cykli zegara CLK a stan =1 przez 1 cykl zegara CLK i potem wykorzystujemy ten drugi zegar przy powiększaniu o 1 licznika. Oczywiście trzeba zmodyfikować to powyżej, bo powinno wyglądać chyba tak:
PRESCALER_PROCESS: process(CLK,PRESCALER,INT_CLK)
begin
if CLK'event and CLK='1' then
if PRESCALER/=INTERVAL then
PRESCALER<=PRESCALER+1;
else
INT_CLK<=not INT_CLK;
PRESCALER<=(others=>'0');
end if;
end if;
end process;
no ale dzięki za idee. A jeszcze pytanie jak obliczyć ile to sekundy te 800000 cykli 1/800000s???
PRESCALER_PROCESS: process(CLK,PRESCALER,INT_CLK)
begin
if CLK'event and CLK='1' then
if PRESCALER=INTERVAL then
PRESCALER<=(others=>'0');
else
PRESCALER<=PRESCALER+1;
INT_CLK<=not INT_CLK;
end if;
end if;
end process;
tworzymy tak jakby drugi zegar, który ma stan = 0 przez 800000 cykli zegara CLK a stan =1 przez 1 cykl zegara CLK i potem wykorzystujemy ten drugi zegar przy powiększaniu o 1 licznika. Oczywiście trzeba zmodyfikować to powyżej, bo powinno wyglądać chyba tak:
PRESCALER_PROCESS: process(CLK,PRESCALER,INT_CLK)
begin
if CLK'event and CLK='1' then
if PRESCALER/=INTERVAL then
PRESCALER<=PRESCALER+1;
else
INT_CLK<=not INT_CLK;
PRESCALER<=(others=>'0');
end if;
end if;
end process;
no ale dzięki za idee. A jeszcze pytanie jak obliczyć ile to sekundy te 800000 cykli 1/800000s???
Mniej wiecej o to mi wlasnie chodzilo, choc przyznaje ze Bartek wyrazil to jasniej i przejrzysciej
Co do obliczen. A jakim zegarem taktujesz ten preskaler, inaczej mowiac ile Hz ma CLK? Bo stad by wynikalo ze Presc_CLK = CLK/800000. A stad juz blisko do time = 1/f = 1/Presc_CLK .
Bartek: czy tam nie powinno byc raczej time_interval = 160000 jesli chcemy 25Hz (? A moze to ja cos pominalem, dopiero zglebiam VHDL wiec tego nie wykluczam (pozatym mam wrazenie ze lekko niekompletny jest ten Twoj kod).
Ps. Mam prosbe na przyszlosc... kozystajcie ze znacznika
Co do obliczen. A jakim zegarem taktujesz ten preskaler, inaczej mowiac ile Hz ma CLK? Bo stad by wynikalo ze Presc_CLK = CLK/800000. A stad juz blisko do time = 1/f = 1/Presc_CLK .
Bartek: czy tam nie powinno byc raczej time_interval = 160000 jesli chcemy 25Hz (? A moze to ja cos pominalem, dopiero zglebiam VHDL wiec tego nie wykluczam (pozatym mam wrazenie ze lekko niekompletny jest ten Twoj kod).
Ps. Mam prosbe na przyszlosc... kozystajcie ze znacznika
Kod: Zaznacz cały
do zamieszczania listingow, znaczaco poprawia to ich czytelnosc.
Na plytce jest kwarc (albo kwarce), ktory dostarcza sygnaly taktujace do ukladu (jako ze FPGA/PLD tak jak i wiekszosc ukladow zdolnych pracowac synchronicznie - mikroprocesory, pamieci, przerzutniki... - potrzebuje jakiegos taktowania).
FPGA/PLD moga jednak tez pracowac kombinacyjnie (jak pewnie wiesz), wowczas nie potrzebuja zadnego taktowania, jednak kombinacyjnie nie zrealizujesz licznika, no bo jak (przyjmujac zalozenie ze impulsy zliczane sa wlasnie taktowaniem licznika, co jest chyba usprawiedliwione jak spojrzymy na sposob pracy).
Przykladowo na podrecznym starterkicie cyclone II mam 3 generatorki: 24, 27 i 50 MHz. Zestaw ZL7PLD ma generator 3,6864 MHz w podstawce, zas modul ZL10PLD (spartan3 z avt) z tego co widze ma podstawke i rowniez taki generator (3,6864 MHz). Przyjrzyj sie plytce, i poszukaj takiej niewielkiej metalowej prostokatnej "puszeczki" (choc sa rowniez wersje kwadratowe - oczywiscie upraszam opis)
FPGA/PLD moga jednak tez pracowac kombinacyjnie (jak pewnie wiesz), wowczas nie potrzebuja zadnego taktowania, jednak kombinacyjnie nie zrealizujesz licznika, no bo jak (przyjmujac zalozenie ze impulsy zliczane sa wlasnie taktowaniem licznika, co jest chyba usprawiedliwione jak spojrzymy na sposob pracy).
Przykladowo na podrecznym starterkicie cyclone II mam 3 generatorki: 24, 27 i 50 MHz. Zestaw ZL7PLD ma generator 3,6864 MHz w podstawce, zas modul ZL10PLD (spartan3 z avt) z tego co widze ma podstawke i rowniez taki generator (3,6864 MHz). Przyjrzyj sie plytce, i poszukaj takiej niewielkiej metalowej prostokatnej "puszeczki" (choc sa rowniez wersje kwadratowe - oczywiscie upraszam opis)
-
- -
- Posty:57
- Rejestracja:10 lis 2006, o 11:50
- Lokalizacja:Gdansk
Bartek: Aaa.. to by juz bardziej pasowalo, tyle ze w pierwszym listingu masz 800 tys, a nie 80 tys ... o jedno 0 za daleko
I faktycznie... z tego preskalera to Presc_CLK = CLK/(INTERVAL*2) . Jako ze tam jest not INT_CLK raz na "Interval" cykli zegara, a to dodatkowo zwieksza 2 krotnie podzial zegara.
I faktycznie... z tego preskalera to Presc_CLK = CLK/(INTERVAL*2) . Jako ze tam jest not INT_CLK raz na "Interval" cykli zegara, a to dodatkowo zwieksza 2 krotnie podzial zegara.
Mam pytanie takie nie do programu powyższego tylko ogólnie odnośnie VHDL. Mianowicie załóżmy, że mam jakiś PROCESS i w nim zadeklarowaną zmienną np. w takiej postaci:
variable x : unsigned(19 downto 0);
Biblioteka na początku programu IEEE.NUMERIC_STD.ALL jest dodana.
Dlaczego więc ten język jest taki niespójny, że wywala mi podczas CHECK SYNTAX błąd przy instrukcji:
if x/=X"F4240" then
że "C:/Documents and Settings/Tomek/Moje dokumenty/Xlinix/licznik/licznik.vhd" Line 56. /= has two or more possible definitions in this scope. For example, parameter 2 (string value) can be: SIGNED or UNSIGNED
Na uwagę zasługuje fakt, że tej linijki się nie czepia:
x:=x+X"00001";
Jakby ktoś nie wiedział to /= to oznacza różne. No i jakby ktoś nie wiedział typ unsigned to typ bez znaku, więc po prostu Check Syntax nie powinien się czepiać, bo no bo to typ unsigned. Bez sensu. Czy po prostu Xilinx ma bugi, bo zgodnie z teorią powinno być dobrze, może dopiero za 10 lat będzie taka wersja XILINXa już ok.
variable x : unsigned(19 downto 0);
Biblioteka na początku programu IEEE.NUMERIC_STD.ALL jest dodana.
Dlaczego więc ten język jest taki niespójny, że wywala mi podczas CHECK SYNTAX błąd przy instrukcji:
if x/=X"F4240" then
że "C:/Documents and Settings/Tomek/Moje dokumenty/Xlinix/licznik/licznik.vhd" Line 56. /= has two or more possible definitions in this scope. For example, parameter 2 (string value) can be: SIGNED or UNSIGNED
Na uwagę zasługuje fakt, że tej linijki się nie czepia:
x:=x+X"00001";
Jakby ktoś nie wiedział to /= to oznacza różne. No i jakby ktoś nie wiedział typ unsigned to typ bez znaku, więc po prostu Check Syntax nie powinien się czepiać, bo no bo to typ unsigned. Bez sensu. Czy po prostu Xilinx ma bugi, bo zgodnie z teorią powinno być dobrze, może dopiero za 10 lat będzie taka wersja XILINXa już ok.
To nie Xilinx ma błędy tylko taki jest po prostu (niesympatyczny) ten VHDL. VHDLa używam bardzo sporadycznie, zdecydowanie preferując Verilog. Z tego co pamiętam to VHDL ma bardzo rygorystyczną kontrolę typów. I faktycznie - co prawda zadeklarowałeś x jako unsigned, ale co ze stałą F4240h? Stała ta może być potraktowana jako liczba ze znakiem (najstarszy bit zapalony – więc byłaby to liczba ujemna) albo liczba bez znaku. W zależności od tego jak potraktować tę stałą to wynik relacji może być różny. I to właśnie sugeruje Ci kompilator w cytowanym komunikacie. W linijce z dodawaniem takiej niejednoznaczności już nie ma. Niezależnie od tego czy tą stałą traktować jak liczbę ze znakiem czy bez znaku jej wartość w obydwu przypadkach będzie wynosić 1 (najstarszy bit zgaszony). Tak przynajmniej bym to interpretował.
Tą stałą F4240h oczywiście, że bez znaku chcę potraktować. Dlatego dałem x unsigned i myślałem, że XILINX jest na tyle dobrze zaprogramowany, że to zrozumie. Ale już chyba czaje o co chodzi. Po prostu trzeba chyba x dać unsigned ale nie (19 downto 0) tylko (23 downto 0) a stałą jako 0F4240h i wtedy może nie wyświetli dziadostwo błędu.
albo sprobowac
lub, chyba lepiej (w tym pierwszym nie jestem pewny rezultatu)
Ziggy: wlasnie czytam ksiazke, w ktorej autor co 2-3 strony zamieszcza to zdanie: "VHDL jest jezykiem z bardzo silna kontrola typow, dlatego trzeba uwazac"
Kod: Zaznacz cały
x/=unsigned(X"F240")
Kod: Zaznacz cały
constant stala : unsigned(rozmiar) := X"F240";
...
if x/=stala then
Kto jest online
Użytkownicy przeglądający to forum: Obecnie na forum nie ma żadnego zarejestrowanego użytkownika i 13 gości