Eerst en vooral: Ik ben een absolute beginner met VHDL. Ik beschik over een Spartan3E Starter Kit om wat op te experimenteren.
Ik probeer een klokdeler te maken waarvan de uitgangssnelheid ingesteld kan worden: 100Hz, 500Hz, 900Hz en 1800Hz. Dit vertrekkende van het kristal van 50MHz op het bordje.
Echter doet Xilinx ISE "raar" bij mij... Ik ben al enkele uren gewoon de waardes in m'n case statement aan het aanpassen, en vaak geeft hij dan een "gated clock" warning, maar soms ook niet. Terwijl ik niks anders aanpas aan de hele code. Als hij echter die "gated clock" warning geeft, werkt het niet als ik het in de FPGA laad.
WARNING:Route:455 - CLK Net:KlokIntern may have excessive skew because
WARNING:PhysDesignRules:372 - Gated clock. Clock net KlokIntern is sourced by a
combinatorial pin. This is not good design practice. Use the CE pin to
control the loading of data into the flip-flop.
Code:
[code=VHDL]
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
entity FreqDeler is
Port ( ClkIn : in STD_LOGIC;
Speed : in STD_LOGIC_VECTOR(1 downto 0);
ClkOut : out STD_LOGIC);
end FreqDeler;
architecture Behavioral of FreqDeler is
signal KlokIntern : STD_LOGIC;
begin
process (ClkIn, Speed)
variable teller : std_logic_vector(20 downto 0);
variable vergelijkwaarde : std_logic_vector(20 downto 0);
begin
if ClkIn'event and ClkIn = '1' then
teller := teller + 1;
end if;
case Speed is
when "00" => vergelijkwaarde := "000111011111011111111"; --100Hz
when "01" => vergelijkwaarde := "000001110111110111111"; --500Hz
when "10" => vergelijkwaarde := "011010111100001000000"; --900Hz
when "11" => vergelijkwaarde := "111010111100001000000"; --1800Hz
when others => null;
end case;
if teller = vergelijkwaarde then
KlokIntern <= '1';
teller := "000000000000000000000";
else
KlokIntern <= '0';
end if;
end process;
process (KlokIntern)
variable klokuit : STD_LOGIC;
begin
if rising_edge(KlokIntern) then
klokuit := not klokuit;
ClkOut <= klokuit;
end if;
end process;
end Behavioral;
[/code]
(De waardes voor 900 en 1800Hz kloppen nog niet, deze moet ik nog correct uitrekenen)
Ik test deze code door ClkOut naar en IOpin te sturen waar mijn logic analyser op bevestigd is.
Iemand enig idee wat ik fout doe? Ik heb deze warning door google gedraaid, maar de oplossingen die daar aangeboden worden snap ik niet helemaal...
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
probeer dit eens :
Code:
[code=VHDL]
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
entity FreqDeler is
Port ( ClkIn : in STD_LOGIC;
Speed : in STD_LOGIC_VECTOR(1 downto 0);
ClkOut : out STD_LOGIC);
end FreqDeler;
architecture Behavioral of FreqDeler is
variable klokuit: STD_LOGIC;
begin
process (ClkIn, Speed)
variable teller : std_logic_vector(20 downto 0);
variable vergelijkwaarde : std_logic_vector(20 downto 0);
begin
if ClkIn'event and ClkIn = '1' then
if teller = vergelijkwaarde then
teller := "000000000000000000000";
klokuit := not klokuit;
else
teller := teller + 1;
end if;
clkout <= klokuit;
end if;
case Speed is
when "00" => vergelijkwaarde := "000111011111011111111"; --100Hz
when "01" => vergelijkwaarde := "000001110111110111111"; --500Hz
when "10" => vergelijkwaarde := "011010111100001000000"; --900Hz
when "11" => vergelijkwaarde := "111010111100001000000"; --1800Hz
when others => null;
end case;
end process;
end Behavioral;
[/code]
maar er is nog vanalles mis met je sensitivity lijsten. ik ben geen vhdl expert ( en geen zin om het te worden )
in ieder geval is de 'logische' fout eruit in mijn voorbeeld.
jouw code gebruikt de uitgang van een flipflop om een andere te clocken en dat is fout.
mijn tweak flipt het klokuit signaal op cadans van de hoofdklok.
en op die zelfde kadans van de hoofdklok wordt klokuit aan clkout toegekend. ( nog zo een eigenaardigheid van vhdl... je kan geen output pin direct bewerken en moet altijd via een tussenvariabele gaan.. )
Bedankt voor even mee te denken.
In jouw code moest de variabele klokuit terug gedefinieerd worden. Nadat ik dat gedaan heb werkt de code spijtig genoeg nog niet.
WARNING:Route:455 - CLK Net:Mcompar_teller_cmp_eq0000_cy<10> may have excessive skew because
WARNING:PhysDesignRules:372 - Gated clock. Clock net
Mcompar_teller_cmp_eq0000_cy<10> is sourced by a combinatorial pin. This is
not good design practice. Use the CE pin to control the loading of data into
the flip-flop.
Zelfde warning, andere netname...
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
probeer je logica ook anders te formatteren. nu draai je allerhande spul door elkaar wat tot een kliederboel leidt in de opgebouwde logica.
1) het is niet nodig die 'vergelijkwaarde te processen in je hoofdblok.
dat is een puur combinatorisch gebeuren en je hoeft dat niet vast te knopen aan je clocked process.
wire vergelijkwaarde
always_comb begin
case speed
0: vergelijkwaarde <= ....
1: vergelijk ....
2: ...
3: ...
end
end
always_ff(@posedge clkin) begin
teller <= teller -1;
if ~|(teller) begin
teller <= vergelijkwaarde
clkout <= ~clkout
end
end
2) aftellers synthetiseren kleiner dan optellers.
3) ik smijt die comparator eruit. comparatoren worden exor trees en die glitchen gelijk zot. je krijgt je enorme delay in je tree waardoor je veel snelheid verliest.
bovenstaand is 'scheduled code' ( kan in vhdl ook )
stap 1 : de default opdracht is : teller = teller -1
stap 2: ik maak een NOR poort (~!) waarmee ik kjk of de teller op nul staat ( | teller ) maakt ene bitwise or tussen al de flipflops in 'teller' zolang er een bit '1' is is de teller niet nul. door dat te inverteren (~) krijg ik een signaal wat me vertelt dat alle flipflops op 0 gevallen zijn. de teller is nu leeg.
als ik dat detecteer : ik herlaad de teller met 'vergelijkwaarde' en ik toggle de clkout pin.
bij de volgende clock is de teller niet meer leeg dus deze thread slaapt.
gevolg : ik heb alleen een register met een preset komende vanaf 'vergelijkwaarde' , een downcounter en een grote NOR poort.
de FPGA zal wel een wide-or hebben waardoor dit ding vol gas vooruit gaat.
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
ik heb mijn eerste oplossing aangepast. (signal klokint vervangen door clockuit )
en je output generator in het clocked event geplaatst. je krijgt die warning omdat je vergelijker 'buiten' het clocked event loopt en je daarmee een flipflop aanstuurt. dat mag niet.
je 'clocked event' is dit:
if ClkIn'event and ClkIn = '1' then
if teller = vergelijkwaarde then
teller := "000000000000000000000";
klokuit := not klokuit;
else
teller := teller + 1;
end if;
clkout <= klokuit;
end if;
alles wat tussen ClkIn'event and ClkIn = '1' en de end-if staat.
alles wat daar in gebeurt is op de cadans van de klok. het is dus daar dat je 'klokuit' moet aanpassen en ook daar dat je klokuit moet overkopieren naar 'clkout'.
ik heb het clkout <= klokuit; ook verplaatst zodat het altijd afvuurt ( onafhankelijk van de tellerstand )
[Bericht gewijzigd door free_electron op (71%)]
@ TS
Je weet toch dat je met constantes end moet werken? Ifnot, dan gaat dien flauwe plezante punte aftrekke op uw exame... (stijn zit bij mij in de klas)
Hieronder is een voorbeeld dat (ongeveer) is zoals hij het wilt, alleen weet ik niet of het werkt (les was net gedaan toen ik kon gaan synthesisen, en ik heb geen spartan bordje)
De klok 'generator' is wel nog niet aangepast zoals F_E het zegt, t'is gewoon als voorbeeld bedoelt voor hoe de leerkracht een state machine wilt opgebouwd zien.
[code=VHDL]
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity p140_stepper is
Port ( SW_SELECT : in STD_LOGIC_VECTOR (1 downto 0);
MAIN_CLK : in STD_LOGIC;
RESET : in STD_LOGIC;
CLK : out STD_LOGIC);
end p140_stepper;
architecture Behavioral of p140_stepper is
begin
process(SW_SELECT, MAIN_CLK, RESET)
variable CLK_COUNT: STD_LOGIC_VECTOR(19 downto 0);
variable CLK_SPEED: STD_LOGIC_VECTOR(19 downto 0);
variable int_CLK: STD_LOGIC;
constant SELECT1 : STD_LOGIC_VECTOR(1 downto 0) := "00";
constant SELECT2 : STD_LOGIC_VECTOR(1 downto 0) := "01";
constant SELECT3 : STD_LOGIC_VECTOR(1 downto 0) := "10";
constant SELECT4 : STD_LOGIC_VECTOR(1 downto 0) := "11";
constant SPEED1 : STD_LOGIC_VECTOR(19 downto 0) := "01111010000100100000"; -- 100 Hz
constant SPEED2 : STD_LOGIC_VECTOR(19 downto 0) := "00011000011010100000"; -- 500 Hz
constant SPEED3 : STD_LOGIC_VECTOR(19 downto 0) := "00001101100100000100"; -- 900 HZ
constant SPEED4 : STD_LOGIC_VECTOR(19 downto 0) := "00000110110010000010"; -- 1800 HZ
begin
if rising_edge(MAIN_CLK) then
if (RESET = '1') then
int_CLK := '0';
else
CLK_COUNT := CLK_COUNT +1;
end if;
end if;
case SW_SELECT is
when SELECT1 => CLK_SPEED := SPEED1;
when SELECT2 => CLK_SPEED := SPEED2;
when SELECT3 => CLK_SPEED := SPEED3;
when SELECT4 => CLK_SPEED := SPEED4;
when others => null;
end case;
if (CLK_COUNT = CLK_SPEED) then
if (int_CLK = '0') then
int_CLK := '1';
else
int_CLK := '0';
end if;
CLK_COUNT := "00000000000000000000";
end if;
CLK <= int_CLK;
end process;
end Behavioral;[/code]
Je uitleg ziet er erg aannemelijk uit... Ik redeneer soms nog te veel als een software developer...
Echter werkt de code die je aangepast hebt niet.
ERROR:HDLParsers:409 - "//vmware-host/shared folders/Gedeeld met WinXP/Xilinx Projects/StappenmotorP142/FreqDeler.vhd" Line 22. Signal 'klokuit' klokuit is at left hand side of variable assignment statement.
Regel 22 is "klokuit := not klokuit;".
Misschien moet er van klokuit terug een variabele gemaakt worden in het proces in plaats van een signal?
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
kan zijn. zoals gezegd ik ben geen expert in vhdl.
@watchout : geef die leraar dan maar een lel rond zijn oren.. boekskes verslijter ... en al die code voor zoiet simpel. in verilog is dat 10 lijnen....
eh godver ! dit is blijkbaar een schoolvraag.. we zijn hier weer bezig zijn diploma te verdienen ...
[Bericht gewijzigd door free_electron op (12%)]
Misschien ook een goed idee is om geen test te doen met de vergelijkwaarde (test dan op zijn minst groter of gelijk aan ipv gelijk aan) maar gewoon de counter te laten roll-overen en dan ipv er 1 bij te tellen een zekere decrement.
Bijvoorbeeld:
library ieee ;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
----------------------------------------------------
entity baudGen is
generic(number_of_bits: natural := 16;
clk_frequency: natural := 20000000;
output_frequency: natural := 1000);
port( clk: in std_logic;
output: out std_logic
);
end baudGen;
----------------------------------------------------
architecture behv of baudGen is
constant decValue : integer := (output_frequency)/(clk_frequency/(2**number_of_bits));
signal baudReg: std_logic_vector(number_of_bits-1 downto 0) := (others=>'0');
begin
process(clk)
begin
if(rising_edge(clk)) then
baudReg<=baudReg-decValue;
end if;
end process;
output<=baudReg(number_of_bits-1);
end behv;
Hierbij maak je decValue ipv een constante dan afhangkelijk van de ingang. Als het goed is zou dit minder logica moeten gebruiken.
En nog een goede tip: maak (of download) macro's voor je editor zodat je eenvoudig alle vhdl boilerplate kunt aanmaken, anders verlies je echt massa's tijd.
Op 2 juni 2011 17:59:37 schreef free_electron:
@watchout : geef die leraar dan maar een lel rond zijn oren.. boekskes verslijter ...
Die eer is aan U voorbehouden, den deze wilt eerst ze diplommeke hebben.
Maareuh, wat is er mis met constantes defineren?
In dit geval vind ik het ook nogal nutteloos, maar bij complexere state machines kan het toch nuttig zijn of niet?
e/:
eh godver ! dit is blijkbaar een schoolvraag.. we zijn hier weer bezig zijn diploma te verdienen ...
Hebt gij dien 'cursus' al is bezien??? Dan snapte direct waarom we naar CO komen om dit 'probleem' op te lossen...
Ik heb men code wat overhoop gegooid, en rekening gehouden met F_E z'n opmerkingen. Daarnaast heb ik de logic_vector's vervangen door integers en nu werkt m'n code.
Mooi, kan ik beginnen aan de volgende stap van wat ik wil maken.
eh godver ! dit is blijkbaar een schoolvraag.. we zijn hier weer bezig zijn diploma te verdienen ...
Neen, daar zijn we niet mee bezig.
We moeten weliswaar voor school kunnen werken met deze FPGA, maar ik probeer dit mij aan te leren door zelf problemen te verzinnen die ik wil oplossen.
Wat Watchout3 post over die "cursus" kan ik beamen. Steek me een language reference van VHDL in m'n handen en ik trek prima m'n plan. Maar met een cursus die met haken en ogen aan mekaar hangt en stukken zoals ik ze in m'n oorspronkelijke code had als voorbeeld gebruikt kun je niet zo veel aanvangen om te beginnen... 
Bedankt voor je uitleg!
Op 2 juni 2011 18:03:21 schreef watchout3:
[...]
Hebt gij dien 'cursus' al is bezien??? Dan snapte direct waarom we naar CO komen om dit 'probleem' op te lossen...
Ge hebt er ten minste 1. Bij de kuleuven gebruiken ze matlab voor FPGA's, dat is veel minder leuk, en maakt alle simpele dingen heel veel werk. (en de FPGA is heel snel vol)
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
matlab voor FPGA's,
/\_
bovenstaande smiley is 'huilen met de pet op'
de onderstaande is dan de 'propeller-beany' versie ervan.
__
/\_
beide zijn (c) free_electron heavy industries
flipflop
"We cannot solve our problems with the same thinking we used when we created them" - Albert Einstein
Het is al min of meer gezegd, maar TS, heb je gesnapt wat de essentie is?
Wat je in een FPGA nooit moet doen is een uitgang van een FF weer als clk voor een andere gebruiken. Dat deed jij wel omdat je uit een teller waarmee je afdeelt vanaf 50MHz een clk genereert. Dat is weer een clk in je systeem. Dit is ook totaal niet nodig zo, want wat is er mis met:
Genereer een pulsje uit je counter die bv elke 1ms 1 cycle actief is. Een ander pulsje is elke 10ms actief, etc. Net wat je nodig hebt. Die puls wordt nu een enable daar waar je een bepaalde actie elke 1ms wilt doen. Dat proces loopt gewoon op de 50MHz, ofwel je systeem clk. Daar loopt ALLES op. 1 clk, niet meer.
Dus dit:
process (clk_50MHz)
if rising_edge(clk) then
if (pulse_1ms) then
--doe iets dat je elke 1ms wilt doen.
end if
end if
end
In een asic wil je wel eens langzame clocken hebben om stroom te besparen, maar in een FPGA speelt dat nauwelijks een rol. De nadelen zijn dan 1000x groter dan de voordelen.