Acties:
  • 0 Henk 'm!

  • Tommienator
  • Registratie: Maart 2011
  • Laatst online: 10-05-2024
Goedenamiddag iedereen,

Zit best met een probleempje dat ik niet opgelost krijg.. De bedoeling is om op een fpga bordje met een frequentie van 100mhz een puls Deler/Teller te maken die om de seconden telt (dit met een 4 bit teller)
(Het is in VHDL te doen btw.)

Zal even m'n codes die ik geschreven heb hier zetten en me vervolgens nader verklaren..

Teller
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use ieee.numeric_std.all;

entity Teller is
Port ( Clk : in STD_LOGIC;
Reset : in STD_LOGIC;
Teller_Out : out STD_LOGIC_VECTOR (3 downto 0));
end Teller;

architecture Behavioral of Teller is
signal Teller_In : integer range 0 to 15;
begin

Cnt_In : process (Clk, Reset)
begin
if reset = '1' then
Teller_In <= 0;
elsif rising_edge(Clk) then
if Teller_In = 15 then
Teller_In <= 0;
else
Teller_In <= Teller_In + 1;
end if;
end if;
end process;

Teller_Out <= STD_LOGIC_Vector(to_unsigned(Teller_In,4)); -- Signaal Count_in veranderen naar een 4 bit tekenloze vector,
-- en kan dan naar een 4 bit vector omgezet worden voor Count_Out.
end Behavioral;
Deler
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Deler is
Port (
Deler_in : in STD_LOGIC;
Reset : in STD_LOGIC;
Deler_out: out STD_LOGIC
);
end Deler;

architecture Behavioral of Deler is
signal Tijdelijk: STD_LOGIC;
signal Teller : integer range 0 to 99999999 := 0;
begin
frequency_Deler: process (Reset, Deler_in) begin
if (Reset = '1') then
Tijdelijk <= '0';
Teller <= 0;
elsif rising_edge(Deler_in) then
if (Teller = 99999999) then
Tijdelijk <= NOT(Tijdelijk);
Teller <= 0;
else
Teller <= Teller + 1;
end if;
end if;
end process;

Deler_out <= Tijdelijk;
end Behavioral;
Deler_Teller port mapping
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Deler_Teller is
Port ( Deler_in, Reset : in STD_LOGIC;
Teller_Out : out STD_LOGIC_Vector (3 downto 0));
end Deler_Teller;

architecture Behavioral of Deler_Teller is

component Deler is
port (Deler_in, Reset : in STD_Logic;
Deler_Out : out STD_Logic);
end component;
component Teller is
port (Clk, Reset : in STD_Logic;
Teller_Out : out STD_Logic_Vector (3 downto 0));
end component;

signal s1 : STD_Logic;

begin
D1 : Deler port map (Deler_In => Deler_In, Reset => Reset, Deler_Out => s1);
T1 : Teller port map (Clk => s1, Reset => Reset, Teller_Out => Teller_Out);
end Behavioral;
Dus waar zit hem juist het probleem.. Gezien ik in de teller met een rising edge werk.. Denk ik dus te delen door (100*10^6/2)-1 waarom.. Omdat hij 50% van de tijd een 0 geeft en 50% van de tijd een 1.
Als ik dit dus implanteer werkt het naar behoren.. Het enkele probleem is dat hij pas begint te tellen na 500ms.

Als ik zoals in de code de deler laat delen door 100*10^6-1 dan begint hij pas vanaf 0 en na 1 sec begint hij te tellen maar dan telt hij maar om de 2 sec..

Dus weet iemand wat ik fout doe :)?

Mvg,
Levi.

"Small minds discuss persons. Average minds discuss events. Great minds discuss ideas. Really great minds discuss mathematics."


Acties:
  • 0 Henk 'm!

  • Bravo51
  • Registratie: April 2008
  • Laatst online: 18:32
Gebeurd dit in je simulatie? Zo ja, kijk eens naar je testbench, of daar geen reset getriggerd word voor die 500ms.

Acties:
  • 0 Henk 'm!

  • Tommienator
  • Registratie: Maart 2011
  • Laatst online: 10-05-2024
Jep dit gebeurd in de simulatie..
Ik heb mijn reset eventjes op 1 gezet voor 10 ns seconden om het spel in gang te krijgen vervolgens gaat deze terug op 0 :).

Ergens is het wel logisch dat hij pas na 500 ms begint te tellen.. Gezien de deler zijn eerste rising edge heeft op 500 ms en ik bij de teller een rising edge hier heb opgezet is het wel logisch dat ie vanaf daar begint..

Heb enkel de vraag hoe ik dit uiteraard op 0 kan laten beginnen?

Hier is de testbench btw.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY tb_Deler_Teller IS
END tb_Deler_Teller;

ARCHITECTURE behavior OF tb_Deler_Teller IS

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT Deler_Teller
PORT(
Deler_in : IN std_logic;
Reset : IN std_logic;
Teller_Out : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;


--Inputs
signal Deler_in : std_logic := '0';
signal Reset : std_logic := '0';

--Outputs
signal Teller_Out : std_logic_vector(3 downto 0);
-- No clocks detected in port list. Replace <clock> below with
-- appropriate port name

constant Deler_In_period : time := 10 ns;

BEGIN

-- Instantiate the Unit Under Test (UUT)
uut: Deler_Teller PORT MAP (
Deler_in => Deler_in,
Reset => Reset,
Teller_Out => Teller_Out
);

-- Clock process definitions
Deler_In_process :process
begin
Deler_In <= '0';
wait for Deler_In_period/2;
Deler_In <= '1';
wait for Deler_In_period/2;
end process;


-- Stimulus process
stim_proc: process
begin

Reset <= '1';
wait for 10 ns;
Reset <= '0';
wait;

end process;

END;

[ Voor 107% gewijzigd door Tommienator op 30-03-2014 19:10 ]

"Small minds discuss persons. Average minds discuss events. Great minds discuss ideas. Really great minds discuss mathematics."


Acties:
  • 0 Henk 'm!

  • RocketKoen
  • Registratie: December 2001
  • Laatst online: 21:08
10ns reset? Dat is 1 klokcycle.
Je moet er vanuit gaan dat je FPGA per bewerking een aantal klokcycles nodig heeft.
Ik gok dat hij niet de tijd krijgt om je reset uit te lezen. En dat je pas een reset krijgt als je register overflowt.

TheS4ndm4n#1919


Acties:
  • 0 Henk 'm!

  • Tommienator
  • Registratie: Maart 2011
  • Laatst online: 10-05-2024
Goed, dan ga ik hem even op 100 ns instellen en zien wat dit geeft :).

"Small minds discuss persons. Average minds discuss events. Great minds discuss ideas. Really great minds discuss mathematics."


Acties:
  • 0 Henk 'm!

  • RocketKoen
  • Registratie: December 2001
  • Laatst online: 21:08
Doe voor de zekerheid gewoon 1 seconde. Dan weet je het zeker.

TheS4ndm4n#1919


Acties:
  • 0 Henk 'm!

  • Tommienator
  • Registratie: Maart 2011
  • Laatst online: 10-05-2024
Had hem nu al op 100 ns gezet, achteraf las ik pas je bericht..
Hij registreerd hem hoor.. Zie hem 1st op 1 springen vervolgens terug op 0..

Maar goed, hier even wat screenshotjes..
Dit is enkel een simulatie van de deler.
Afbeeldingslocatie: http://plaatjesdump.nl/upload/306f3274291b5dc4bc67202d266b5150.png

Zoals je kan zien is de eerste rising edge na 500 ms dit is ook wel af te leiden van de code (anders om dit op een sec te krijgen zou ik moeten delen door 100*10^6-1)

En hier is de Deler_Teller in zijn totaal..

Afbeeldingslocatie: http://plaatjesdump.nl/upload/d2db9be4411fe0e02c2dba14082962d8.png

Dus hij begint pas te registeren na 500ms en te tellen om de sec, dit omdat er maar 1 rising edge per seconden volgens mijn deler is.

Maar hoe kan ik nu dit naarvoor laten schuiven.. Dus ik wil (uiteraard steekt er een beetje vertraging op) dat hij op 0s begint te tellen en dan om de seconden pulsen..

Kan ik misschien met 2 rising edge's werken?
Of wat me beter lijkt is een falling edge, maar weet niet juist hoe ik dat moet implanteren?

[ Voor 4% gewijzigd door Tommienator op 30-03-2014 19:30 ]

"Small minds discuss persons. Average minds discuss events. Great minds discuss ideas. Really great minds discuss mathematics."


Acties:
  • 0 Henk 'm!

  • the12be
  • Registratie: November 2000
  • Laatst online: 08-10 08:24
Kan ik misschien met 2 rising edge's werken?
Of wat me beter lijkt is een falling edge, maar weet niet juist hoe ik dat moet implanteren?
Doe dit vooral niet!

Wat je nu gedaan hebt is een 2e kloknetwerk maken in je design, en dit is vragen om problemen. (Waarschijnlijk geeft je synthese tool hierop ook wel een waarschuwing, iets met "inferred clock" ).

Een nette oplossing voor wat je wil is werken met een clock enable.

google eens op "vhdl clock enable example" en er komen wel een aantal goede voorbeelden naar boven.

Kijk anders eens naar de 10 gouden regels van digitaal design (pdfje). Er zijn een hoop valkuilen, en deze regels voorkomen een hoop "vage" problemen.

Acties:
  • 0 Henk 'm!

  • Tommienator
  • Registratie: Maart 2011
  • Laatst online: 10-05-2024
Bedankt voor de input.. Goed.. Dit ga ik dan eens even bekijken en alsnog mijn design aanpassen!

Maar heb het op de moment al werkend gekregen.. Het probleem was gewoon dat ik met een falling edge ipv rising moest werken.. En dan begin ik mooi bij 0 en tel om te seconden..
Wilt uiteraard niet zeggen dat het alsnog slordige code is :p.

Het pdfje doet btw niets?
Het enige wat ik gekregen heb is hetvolgende..
-- No clocks detected in port list. Replace <clock> below with
-- appropriate port name
Heb mijn reset veranderd naar "wait for Deler_In_Period*2;" ipv "wait for 100 ns;"
Was het dit wat je bedoelde?

Werk met ISE.

Afbeeldingslocatie: http://plaatjesdump.nl/upload/7ab17170e2e8ab55c9cd8ac18380b43d.png

[ Voor 27% gewijzigd door Tommienator op 30-03-2014 20:08 ]

"Small minds discuss persons. Average minds discuss events. Great minds discuss ideas. Really great minds discuss mathematics."


Acties:
  • 0 Henk 'm!

  • the12be
  • Registratie: November 2000
  • Laatst online: 08-10 08:24
URL gefixed. Dat het werkt is opzich mooi, maar het gevaar van dit soort constructies is dat niet betrouwbaar is. Met dit soort klok-snelheden ga je er vast geen last van krijgen, maar je kan het jezelf beter direct goed aanleren :D.

Ben wel eens van dit soort constructies tegen gekomen in productie designs, en dan krijg je problemen van het werkt alleen als het board al "warm" is enzo. Dat zijn dingen waar je dus niet echt blij van wordt :P.

Ben je voor de hobby bezig, of is dit school werk?

Acties:
  • 0 Henk 'm!

  • Tommienator
  • Registratie: Maart 2011
  • Laatst online: 10-05-2024
the12be schreef op zondag 30 maart 2014 @ 20:42:
URL gefixed. Dat het werkt is opzich mooi, maar het gevaar van dit soort constructies is dat niet betrouwbaar is. Met dit soort klok-snelheden ga je er vast geen last van krijgen, maar je kan het jezelf beter direct goed aanleren :D.

Ben wel eens van dit soort constructies tegen gekomen in productie designs, en dan krijg je problemen van het werkt alleen als het board al "warm" is enzo. Dat zijn dingen waar je dus niet echt blij van wordt :P.

Ben je voor de hobby bezig, of is dit school werk?
Schoolwerk, studeer voor ingenieur elektronica :).

Het probleem is, heb voorbeeld code van mijn proffen gekregen en doe het aan de hand daarvan. (allé ben wel helemaal overnieuw begonnen om het echt te begrijpen) maar wel hun code als draadlijn.
En dit is eigenlijk de draadlijn hoe zij het ook hebben gemaakt, is dit goed of slecht ben ik niet om me erover uit te spreken.. Maar kan moeilijk tegen hen gaan zeggen van heeej mannen, je bent fout (misschien zelf al wel ondervonden hoe 'ego'trippend proffen zijn ;)!)

"Small minds discuss persons. Average minds discuss events. Great minds discuss ideas. Really great minds discuss mathematics."


Acties:
  • 0 Henk 'm!

  • peterpv
  • Registratie: Februari 2003
  • Laatst online: 08-10 11:59
Zo'n Professor weet vast ook wel dat z'n code niet werkt. Maar straks heb jij code die wel werkt.
=> doel van jou en je Prof bereikt: Je hebt geleerd hoe je werkende code krijgt :*)
Dat wat anderen je aanleveren werkt vaak niet of niet zoals jij denkt dat het zou moeten werken.
Wen er maar aan en leer ervan :) (doe ik al zo'n 20 jaar, ook in de electronica zij het zonder VHDL).

Acties:
  • 0 Henk 'm!

  • Tommienator
  • Registratie: Maart 2011
  • Laatst online: 10-05-2024
Haha! Nu snap ik uiteraard wel alles door het zelf werkend gekregen te hebben..
Maar het dan toch weer niet goed genoeg voor mij.. Als ik dan zo'n reactie krijg zoals die van the12be dat het goed is dat de code werkt, maar er toch een design flater inzit.. Dan zou ik die er nog al te graag ook uitkrijgen.. Als snap ik niet bepaald wat hij bedoeld?!

Dus als iemand mij hier mee kan voorthelpen, dat zou echt goddelijk zijn ;)!

Edit:

Heb hier nog even een andere versie geschreven die hetzelfde doed.. Is dit dan misschien wat je bedoeld of..?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;

entity deler is
Port ( clk : in STD_LOGIC;
clr : in STD_LOGIC;
T : out STD_LOGIC);
end deler;

architecture behavioral of deler is
signal q: std_logic_vector(27 downto 0);
signal Tijdelijk: std_logic;
begin

process (clk, clr)
begin
if clr = '1'
then
q <= X"0000000";
Tijdelijk <= '0';
elsif rising_edge(clk)
then
q <= q + 1;
end if;

if q(26)='1' and q(24)='1' and q(23)='1' and q(22)='1' and q(21)='1' and q(20)='1' and q(18)='1' and q(16)='1' and q(15)='1' and q(14)='1' and q(13)='1' and q(8)='1'
then
Tijdelijk <= NOT(Tijdelijk);
q <= X"0000000";
end if;

end process;

T <= output;
end behavioral;
Bedankt ^^.

[ Voor 62% gewijzigd door Tommienator op 30-03-2014 21:28 ]

"Small minds discuss persons. Average minds discuss events. Great minds discuss ideas. Really great minds discuss mathematics."


Acties:
  • 0 Henk 'm!

  • the12be
  • Registratie: November 2000
  • Laatst online: 08-10 08:24
Technische gezien wel OK, maar niet echt leesbaar en dat is ook weer niet fijn.

Maar ik zal even een voorbeeld geven, excuseer the mogelijke typo's. Verder wat achtergrond info, met wat redenering:

De output moet in dit geval een buffer zijn ipv een output. ( gedraagt zich hetzelfde als een output, je mag dan alleen de huidige waarde "gebruiken"). Het grote voordeel is dat je geen tijdelijke signalen hebt, wat de leesbaarheid van je code ten goede komt.

Verder tel ik terug naar naar 0, ipv optellen. Dit omdat dit in sommige situaties "goedkoper" is in HW. ( dit is vooral waar als je een variabel aantal wil tellen, maar het is een goede gewoonte om altijd terug te tellen.

Het stukje waar ik de "teller_uit" optel kan ingewikkeld lijken, maar VHDL is nogal strikt met types, en dit soort cast kijk je met een beetje ervaring gewoon doorheen.

Ik gebruik voor de teller een unsigned type ipv van een integer. Dit is een stukje persoonlijke voorkeur, maar het heeft een aantal voordelen:
* een unsigned mag je zo groot maken als je wil, een integer is 32 bit max. Bij een grotere delay ga je dus de mist in.
* Je kan een signed/unsigned direct mappen op een std_logic_vector, en dus op een aantal flip-floppen. Sta er bij stil dat je HW aan het maken bent, en dus eigenlijk altijd een idee wil hebben wat er aan HW gemaakt wordt door je synthese tool.

Integers gebruik ik persoonlijk alleen voor TB code, en als je slimme dingen met generate statements aan het doen bent. Eigenlijk bijna nooit in code die direct gebruikt wordt.

Je output teller "loopt" nu nog wel steeds op dezelfde frequentie als clk, hij wordt alleen niet altijd verhoogt. Het kan voorkomen dat dit qua timing wat problemen oplevert. Dit is waar je gaat kijken naar "multi-cycle" paden. In dit geval zal dit niet nodig zijn, maar als je brede tellers heb op hoge frequenties dan kan dit nodig zijn.

Verder nog wat nice-to-haves. (Om punten te scoren bij je professor :P ).
* Maak een generic waarin de de klock frequentie zet, zodat je een stukje herbruikbare code krijgt.
* Als je de groote van je teller weet (afhankelijk van je clock frequentie) kan je ook de breedte van je teller automatisch bepalen.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
signal second_counter   : unsigned( 26 downto 0 );
signal enable           : std_logic;

if reset = '1' then 

  -- reset stuff
  second_counter <= ( others => '0' );
  enable         <= '0';

elsif rising_edge( clk ) then
 
  -- default value for enable is zero
  enable <= '0'; 

  if second_counter = 0 then
    -- We've counted down a second, set the the enable and reload the counter.
    second_counter <= to_unsigned( 99999999, second_counter'length );
    enable <= '1';
  else
    second_counter <= second_counter - 1;
  end if;
  
  if enable = '1' then 
    Teller_Out <=  std_logic_vector( to_unsigned( Teller_Out ) + 1 );
  end if;

end if



Pffff. Heel verhaal :O.

Een aantal statements die ik hier maak zijn ook persoonlijke meningen, en ik heb collega's die er anders over denken. Het is dus ook niet zo dat dit allemaal de enige juiste manier is.

Zou het leuk vinden als je deze opmerkingen meeneemt en een stukje code van bakt wat wel compileert, ( bovenstaande vast niet :P), en dat er wat anders tweakers commentaar op leveren. Dan leren we er allemaal wat van :D.

[ Voor 5% gewijzigd door the12be op 30-03-2014 23:42 ]


Acties:
  • 0 Henk 'm!

  • Flake
  • Registratie: Februari 2001
  • Laatst online: 01-11-2024
Tommienator schreef op zondag 30 maart 2014 @ 19:25:
Dus hij begint pas te registeren na 500ms en te tellen om de sec, dit omdat er maar 1 rising edge per seconden volgens mijn deler is.

Maar hoe kan ik nu dit naarvoor laten schuiven.. Dus ik wil (uiteraard steekt er een beetje vertraging op) dat hij op 0s begint te tellen en dan om de seconden pulsen..

Kan ik misschien met 2 rising edge's werken?
Of wat me beter lijkt is een falling edge, maar weet niet juist hoe ik dat moet implanteren?
Jouw deler heeft helemaal geen clocksignaal, terwijl die teller dat wel heeft. Waarom? Gewoon je process laten triggeren op een rising edge van de clock en dan kijk je of er wat moet gebeuren. Of je pakt evt een extra controlsignal erbij.

Je moet oppassen voor het gebruiken van rising edges en falling edges bij signalen buiten clocksignalen. In RTL werkt dat wel, maar grote kans dat je synthesizer ervan over z'n nek gaat omdat het simpelweg te vaag omschreven is.
Pagina: 1