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.

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.

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.

Das inderdaad een goed advies: denk in (digitale) hardware.

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!!!

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;

[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%)]

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%)]

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.

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!

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.

je mag niet in twee processen 1 signaal (tegelijkertijd) aansturen, dat doe je nu wel :P

[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.

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.

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.

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...

Bouw eens een reset in, die dingen zijn er niet voor niets natuurlijk

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%)]