Hallo,
Ik ben net wat beginnen programeren in ISE 9.2 software van Xilinx. Dit in VHDL. Als testboard gebruik ik de Spartan 3AN starter kit.
In het begin probeer ik altijd enkele simpele dingen zoals ledjes aansteken en tellers enzo.
Nu krijg ik het maar niet gedaan om ergens een tijdsvertraging in te bouwen. Een soort monostabiele multivibrator. Niet om te simuleren maar om op een testboard te programeren.
Ook dacht ik dat er ergens een instructie "constant" is. Is dit om een interne clock te bouwen? kan deze dan ook naar buiten gebracht worden?
Alvast bedankt.
Jochem
If you want to succeed, double your failure rate.
Wait kan als tijdsvertraging alleen in simulatie. Hoe moet jouw FPGA/CPLD weten hoe snel een seconde verloopt?
Het antwoord is simpel: bied een klok aan, waarvan je weet hoe snel die is, en ga pulsen tellen. Als er genoeg pulsen voorbij zijn, zet je een vlaggetje. Afhankelijk van dat vlaggetje toggle je dan bijvoorbeeld een uitgang.
flipflop
"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein
Niels, als algemene regel kun je aannemen dat alles wat je in "echte" digitale hardware kunt maken, je ook in de FPGA kunt maken. Een vertraging, hoe zou die er in gewone logica eruit zien? Nee, niet met een R en C, da's analoog.
Een vertraging kun je maken door een teller. Bij een pulsje start je de teller en als ie bij een bepaalde stand is aangekomen doe je iets anders, bv een puls genereren of een led laten branden.
Jochem
If you want to succeed, double your failure rate.
Het hele VHDL is gedoe is voor mij nog wat nieuw. dus vandaar misschien rare en domme vragen, maar het is van niet beter weten he mannen 
ik heb volgende code:
entity testifthenelse is
Port ( clk : in STD_LOGIC;
W21led1 : out STD_LOGIC);
end testifthenelse;
architecture Behavioral of testifthenelse is
signal teller : integer range 0 to 1001;
signal uitg: std_logic;
begin
process (clk,teller)
begin
if rising_edge(clk) then
teller <= teller + 1;
else
teller <= teller;
end if;
if (teller = 4) then
uitg <= not uitg;
teller <= 0;
end if;
end process;
W21led1 <= uitg;
end Behavioral;
Nu dacht ik mij vaag te herinneren dat de processen iets de maken had met dingen die op hardware-niveau naast elkaar draaien.
Op de stijgende flank van de clock laat ik de integer optellen en erna kijk ik de waarde na van de integer. Als deze hoog genoeg is ga ik de uitgang toggle-en en de integer terug naar 0 zetten. Zoals jullie allemaal wel kunnen zien 
Nu wil dat bij mij maar niet werken terwijl ik volgens mij niets fout doe. Of wel?
Alvast bedankt!!!
Tommyboy
Zo goed als het vroeger was, is het nooit geweest.
Ik ben dan wel geen VHDL guru, maar ik zie een paar dingen die niet kloppen en/of overbodig zijn.
Om te beginnen hoef je "teller" niet op te nemen in de sensitivitylist van je process.
In je eerste if-statement is de "else" conditie overbodig, je statement kan dus als volgt geschreven worden:
if rising_edge(clk) then
teller <= teller + 1;
end if;
En als laatste: Je maakt een integer "teller" aan, welke van 0 tot 1001 loopt (das decimaal!), vervolgens ga je daar telkens 1 bij optellen, tot je bij 4 zit, dan reset je hem. Waarom laat je je integer niet gewoon tot 4 lopen, maar neem je 997 dingessen te groot?
Edit:
Nog een tip voor je:
Als ik het goed begrijp, wil je je klokfrequentie door 8 delen. Als je gewoon een 4 bits vector neemt, en bij elke klokpuls daar een bij optelt, kan je de "most significant bit" naar buiten voeren.
[Bericht gewijzigd door Tommyboy op (15%)]
De eigenlijke bedoeling is dat ik ergens een clock ingeef, en als ik daarna op een knopje druk, bijvoorbeeld 3 seconden erna een ledje aangaat. daarvoor had ik gedacht om vanaf dat je op het knopje drukt de pulsen van die externe clock te tellen en dan wacht tot je de gewenste tijd hebt. Vandaar dat de interger voorzien was van 0 tot 1000, om op hogere frequentie te werken. Maar voor de eerste probeersels, werkte ik op 4Hz ofzo.
Voor het ogenblik test ik volgende code, maar ik heb de indruk dat de compiler de "if" in de "if" niet leuk vind.
entity testifthenelse is
Port ( clk,T9sw1 : in STD_LOGIC; --T9sw1 is de schakelaar aan de ingang
B4mes,W21led1 : out STD_LOGIC);
end testifthenelse;
architecture Behavioral of testifthenelse is
signal teller : integer range 0 to 1001;
signal uitg: std_logic;
begin
process (T9sw1,clk)
begin
if rising_edge(T9sw1) then
if rising_edge(clk) then
teller <= teller + 1;
else
teller <= teller;
end if
end if;
if (teller = 10) then
uitg <= not uitg;
teller <= 0;
end if;
end process;
B4mes <= uitg;
W21led1 <= uitg;
end Behavioral;
flipflop
"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein
[edit] Oh, je had net zelf gepost. Even beter bekijken.
Alles wat Tommy typt, mee eens (bijna). Integers moet je eigenlijk niet gebruiken. Als je hardware "schrijft", neem dan gewoon een vector, dan weet je precies wat dat aan hw oplevert.
teller moet in jou geval wel in de sens.list omdat teller gelezen wordt buiten het rising_edge(clk) deel. Echter, da's niet fraai en dus heeft Tommy toch, indirect, gelijk.
Ik zou het zo doen:
(Met code tags wordt het beter leesbaar)
entity testifthenelse is
Port ( clk : in STD_LOGIC;
W21led1 : out STD_LOGIC);
end testifthenelse;
architecture Behavioral of testifthenelse is
signal teller : std_logic_vector(2 downto 0);
signal uitg: std_logic;
begin
process (clk)
begin
if rising_edge(clk) then
if (teller = 4) then
uitg <= not uitg;
teller <= 0;
else
teller <= teller + 1;
end if;
end if;
end process;
W21led1 <= uitg;
end Behavioral;
Hmm,nog korter ook. Paar opmerkingen:
- Je maakt hier een periode van 5 clk cycles (0,1,2,3,4,0,1..). De teller wordt dus eerst 4, en een cycle daarna wordt ie pas 0. Da's vaak lastig in te zien voor beginners. Desnoods even in een simulatie bekijken, dan zie je het zo.
- Omdat uitg ook binnen het geclockte process zit, krijg je hier ook een flipflop die toggled als de teller "over de kop" gaat. Da's extra hardware die je mogelijk zou kunnen besparen. Maar goed, het is er maar 1 hier dus who cares.
[edit] Nu over je 2e post:
Je hebt twee rising edge statements binnen elkaar staan. Dat gaat nooit werken want je hebt NOOIT twee edges tegelijkertijd. Daar zit altijd wel een ps verschil tussen. Je teller zal niet lopen. DENK HARDWARE.
Wat je moet doen is het maken van een edge detector in een apart process. Niet alles in 1 process proppen.
process (clk)
signal rising_edge_detected :std_logic;
begin
if rising_edge(clk) then
pre_input = input;
end if;
end process;
rising_edge_detected = 1 when (input=1 and pre_input=0)
else 0;
falling_edge_detected = 1 when (input=0 and pre_input=1)
else 0;
Dat detected signaal lees je dan in het process waar je het nodig hebt, dus in de code die hierboven staat.
[Bericht gewijzigd door flipflop op (20%)]
Tommyboy
Zo goed als het vroeger was, is het nooit geweest.
Het probleem in je nieuwe stuk code zit hem hierin:
if rising_edge(T9sw1) then
if rising_edge(clk) then
teller <= teller + 1;
else
teller <= teller;
end if
end if;
De dubbele "rising_edge" doet het hem: dit is onmogelijk. Tijdens de rising edge van T9sw1 ga je kijken of je een rising edge hebt op clk. Dit is onsynthetiseerbaar.
Overigens zijn nested if-statements heel goed mogelijk, alleen kan je maar 1 keer per tak een event dinges gebruiken (xxx'event, rising_edge, falling_edge, enzovoort).
[Bericht gewijzigd door Tommyboy op (19%)]
free_electron
Silicon Member
Professioneel ElectronenTemmer - siliconvalleygarage.com - De voltooid verleden tijd van 'halfgeleider' is 'zand' ... US 8,032,693 / US 7,714,746 / US 7,355,303 / US 7,098,557 / US 6,762,632 / EP 1804159 - Real programmers write Hex into ROM
dat is een van de grote problemen bij HDL talen. die dingen zijn eignelijk otwikkeld om te modelleren. pas later is men daar synthese gaan op doen.
De meeste boeken behandelen de HDL in het algemeen. voor gebruik als synthesetool is de helft van de instreucties onbruikbaar.
flipflop
"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein
Je kunt het ook omdraaien: Dat is het MOOIE van HDL talen. Je kunt ze zowel voor modellering gebruiken als voor implementatie. Geweldig toch, alles in één taal!
Ik heb toch nog een vraagje in verband met die processen. Een proces is dus eigenlijk een reeks instructies die wordt afgelopen zoals bij een microcontroller. Maar verschillende processen lopen op hardware-gebied naast elkaar?
Of zit ik er volledig naast?
Heb wat zitten proberen en ik denk dat ik hardware gedacht heb. En ik denk dat ik niet ver van de oplossing zit. Er is nog 1 ERROR in het programma.
entity testifthenelse is
Port ( clk,T9sw1 : in STD_LOGIC; --T9sw1 is de schakelaar aan de ingang
B4mes,W21led1 : out STD_LOGIC);
end testifthenelse;
architecture Behavioral of testifthenelse is
signal teller : integer range 0 to 1001;
signal uitg: std_logic;
signal flag: std_logic;
begin
process (T9sw1)
begin
if rising_edge(T9sw1) then
teller <= 0;
flag <= '1';
end if;
end process;
process (clk,teller)
begin
if (flag = '1') then
if (clk'event and clk = '1') then
teller <= teller + 1;
end if;
end if;
if (teller = 10) then
uitg <= not uitg;
flag <= '0';
end if;
end process;
B4mes <= uitg;
W21led1 <= uitg;
end Behavioral;
De fout gaat over regel 53. dit is de regel teller <= teller + 1; onder de IF met clk'event. De error is de volgende:
ERROR:HDLParsers:834 - "D:/data/Desmetn/My Documents/progs VHDL/testifthenelse/testifthenelse.vhd" Line 53. Signal teller has a multi source.
Wat wordt er hier bedoeld met multi source? Volgens mij gaat het hier over een stomme fout.
Alvast bedankt!
Jochem
If you want to succeed, double your failure rate.
Dikke vette sluiting, rookwolken, etc! 
Als flag=1 en risingedge(clk) en risingedge(t9sw1), dan wordt je teller op 2 plaatsen gestuurd.
Ik ben ook niet helemaal gelukkig met de rest van je constructie, maargoed.
Daan Timmer
Ik ben programmeur! geen electronicus! http://www.daantimmer.nl/ Er is een ontwerp! nu nog inhoud :-)
je mag niet in twee processen 1 signaal (tegelijkertijd) aansturen, dat doe je nu wel 
[Bericht gewijzigd door Daan Timmer op (11%)]
je 'wait' probleem zou je het beste kunnen oplossen met een frequentie deler. Je neemt de oscilator op je experimenteerbord en maak daarmee dan een klokdeler tot je de bepaalde tijd hebt die je nodig hebt.
En zet dit dan in een package zodat je in het top-design de component 'klokdeler' gaat implementeren.
Dan kan je je component verbinden met je Top-design vie 'PORT MAP'
grtz
Jochem,
Heb je concrete opmerking op de structuur of is het helemaal fout? Alleen met commentaar te geven en door op het negatieve gewezen te worden kan ik mij verbeteren he.
De bedoeling is om een ingang te testen, vanaf deze hoog gaat zal een teller voor een vertraging zorgen en nadien een uitgang inschakelen. Volgens mij moet ik dus zeker met 2 processen werken aangezien ik in 1 proces niet meerdere malen op een stijgende flank mag triggeren.
Dus de oplossing is om een variable te creeeren voor mijn 2e proces en erna buiten de processen de waarde's te verwerken.
Jochem
If you want to succeed, double your failure rate.
Ik zou alles op de flank van de clock laten gebeuren, dus dat de buitenste IF laten zijn, en die flag-constructie vergeten.
De schakelaar dan eerst synchroniseren (dubbele flipflop stage) omdat hij van buiten komt, en gewoon op je klokflank checken.
Tommyboy
Zo goed als het vroeger was, is het nooit geweest.
Ik zou dat als volgt doen:
if rising_edge(clk) then
if flag = '0' then
if T9sw1 = '1' then
flag <= '1';
end if;
else
if teller = 10 then
teller < 0;
flag <= '0';
uitg <= not uitg;
else
teller <= teller + 1;
end if;
end if;
end if;
Wat deze code doet, is volgens mij goed te begrijpen.
Er kunnen wat kleine schoonheidsfoutjes in zitten, misschien verkeerde namen of waarden, maar zoals ik het zo zie, zou ditmoeten complieren, en doen wat je wil.
flipflop
"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein
Niels, je doet een paar dingen die helemaal fout zijn:
- Je kijkt niet naar mij briljante voorbeelden
(let op de smile)
- Je hebt meerdere processen met verschillende klokken. Elke keer als je rising_edge(xx) schrijft, maak je een klok aan met de naam xx. In een FPGA moet je zoveel mogelijk 1 klok-domein houden anders ga je timing problemen krijgen. Als je meer ervaren wordt kun je er meerdere maken (als nodig), maar hou het ajb bij 1 voorlopig.
- Je hebt ergens halverwege in een proces staan: if rising_edge(xx). Da's harstikke fout. Wat je nl doet als je test op een rising edge, is een flipflop opschrijven. Als je daaromheen nog bv een if zet, dan weet ik niet meer wat voor hw dat wordt, en de synthese denk ik ook niet. Dus... een proces begint altijd met if risig_edge, of er zit helemaal geen rising edge in. In het eerste geval krijg je flipflops, in het laatste geval krijg je alleen ANDs and ORs (combinatorische logica).
Wat Tommy hier schrijft is ook goed, maar ik haal het zelf liever uit elkaar zoals in mijn laatste post hierboven. Dat doet volgens mij precies wat je wilt. Laat maar horen als je daar iets niet in snapt.
Beste,
Het is alweer een tijdje geleden dat ik dit topic begonnen was, maar door omstandigheden heb ik een hele tijd me niet met dit kunnen bezig houden. Ik ben opnieuw begonnen met dit proberen af te werken en sprak er met enkele mensen over maar dit lijkt toch niet zo simpel te zijn...
Voor het ogenblik heb ik volgende code:
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 monostable2 is
Port ( clk : in STD_logic;
interupt : in STD_LOGIC;
output : out std_logic;
output1 : out std_logic);
end monostable2;
architecture Behavioral of monostable2 is
signal teller: integer range 0 to 200000001;
signal uitg: std_logic := '0';
signal flag: std_logic;
signal flag1: std_logic;
begin
trig_f: process (interupt)
begin
if rising_edge(interupt) then
flag1 <= '1';
end if;
end process trig_f;
mono: process (clk)
begin
if rising_edge(clk) then
if flag = '0' then
if flag1 = '1' then
uitg <= '1';
flag <= '1';
end if;
else
if teller >= 200000000 then
teller <= 0;
uitg <= '0';
flag <= '0';
else
teller <= teller + 1;
end if;
end if;
end if;
end process mono;
output <= uitg;
output1 <= flag1;
end Behavioral;
Nu is het probleem dat ik bij het aanleggen van de testprint, meteen "output1" op 1 heb. Dit wil zeggen dat er bij het initialiseren van de FPGA een stijgende flank gedetecteerd wordt op de ingang? Valt dit te verklaren? Wanneer ik het volgende doe:
signal flag1: std_logic :=0;
dan krijg ik een fout bij het synthetiseren...
Iemand ervaring met dit?
Alvast bedankt...
Jochem
If you want to succeed, double your failure rate.
flipflop
"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein
Reset hoeft niet per-se als je voor een fpga programmeert. Daar wordt vanzelf al gezorgt dat alle FFs op '0' (default) komen te staan bij opstarten. Een echte reset is wel nodig als je de zaak warm wilt resetten, dus zonder de configuratie opnieuw te laden.
Niels, op zich niet zo raar wat er gebeurt toch? Je hebt een ingang "interrupt" die je als clk op een FF "flag1" gebruikt. Een ongeinitialiseerde fpga heeft alle ingangen Z staan. Op het moment dat het laden klaar is, schakeld de hele boel om zoals je het geprogrammeerd hebt (dus interrupt wordt een ingang etc). Het zou best kunnen dat dat als een flank gezien wordt door die FF. Een pull-down op de ingang zou kunnen helpen, maar fraai is anders.
Dat presetten door :=0 niet gaat lijkt me logisch. Wat zou de hardware hiervoor moeten zijn? Kan niet dus. Die constructie is alleen bedoeld voor testbenches.
(ik weet niet meer wat je precies wilde maken, dus misschien goed om nog eens uit te leggen?)
[Bericht gewijzigd door flipflop op (58%)]