Kysymys:
Kuinka jakaa 50 MHz alas 2 Hz: iin VHDL: ssä Xilinx FPGA: lla
ABAYOMI STEPHEN
2013-03-19 06:04:57 UTC
view on stackexchange narkive permalink

Minulla on Xilinx FPGA -levy, jossa on 50 MHz: n kristalli. Minun on jaettava se 2 Hz: iin VHDL: ssä. Kuinka teen tämän?

Joten mitä olet itse kokeillut?
Miksi et käyttäisi Xilinx clock manager IP: tä?
Viisi vastused:
stanri
2013-03-19 11:09:48 UTC
view on stackexchange narkive permalink

Periaatteessa tähän on kaksi tapaa. Ensimmäinen on käyttää Xilinx-natiivikellosyntetisaattorin ydintä. Yksi tämän eduista on, että Xlinx-työkalut tunnistavat kellon sellaisenaan ja reitittävät sen vaadittujen reittien läpi. Työkalut käsittelevät myös kaikki aikarajoitukset (ei oikeastaan ​​sovellettavissa tässä tapauksessa, koska se on 2 Hz: n kello).

Toinen tapa on laskurin avulla laskea nopeamman kellopulssin määrä, kunnes puolet hitaammasta kellonaika on kulunut. Esimerkiksi sinun tapauksessasi nopeiden kellopulssien määrä, joka muodostaa yhden hitaan kellojakson kellojakson, on 50000000/2 = 25000000. Koska haluamme puoli kellojaksoa, se on 25000000/2 = 12500000 kutakin puolijaksoa kohti . (kunkin korkean tai matalan kesto).

VHDL: ssä se näyttää tältä:

  library IEEE; use IEEE.STD_LOGIC_1164.all; - Poista seuraava kommentti kirjastoilmoitus, jos käytetään - aritmeettisia toimintoja allekirjoitetuilla tai allekirjoittamattomilla arvoilla, käytä IEEE.NUMERIC_STD.all; entiteetti scale_clock on portti (clk_50Mhz: in std_logic; rst: in std_logic; clk_2Hz: out std_logic); end scale_clock; arkkitehtuuri Scale_clock-käyttäytyminen on signaalin esijärjestelmä : allekirjoittamaton (23 - 0); signaali clk_2Hz_i: std_logic; aloita gen_clk: prosessi (clk_50Mhz, ensimmäinen) alkaa - prosessi gen_clk, jos rst = '1', sitten clk_2Hz_i < = '0'; esijäähdytin < = (muut = > '0'); elsif rising_edge (clk_50Mhz) sitten - nouseva kellon reuna, jos escalkali = X "BEBC20", sitten - 12 500 000 heksadesimaalissa < = (muut = > '0'); clk_2Hz_i < = ei clk_2Hz_i; muut esijäähdyttimet < = esijäähdyttimet + "1"; loppu Jos; loppu Jos; end process gen_clk; clk_2Hz < = clk_2Hz_i; end Behavioral;  

Huomattavat asiat:

  • Luodun kellon arvo on nollaan nollausprosessin aikana. Tämä on ok joillekin sovelluksille, ei toisille, se riippuu vain kellosta.
  • Generoitu kello reititetään normaalina signaalina Xilinx-synteesityökaluilla.
  • 2 Hz on erittäin hidas. Sekunnin simulointi kestää jonkin aikaa. Se on pieni määrä koodia, joten sen pitäisi olla suhteellisen nopeaa simuloida jopa 1 sekunnin ajan, mutta jos aloitat koodin lisäämisen, 2 Hz: n kellosyklin simulointiin kuluva aika voi olla huomattavan pitkä.

EDIT: clk_2Hz_i käytetään lähtösignaalin puskurointiin. VHDL ei halua käyttää signaalia tehtävän oikealla puolella, kun se on myös lähtö.

Ei paha, mutta voit lisätä / verrata allekirjoittamatonta kokonaislukuun, joten: "jos esikalkkikone = 50_000_000 / 4 sitten ..." ja "esikalkkikone <= esikalkkikone + 1;" olisi hieman yksinkertaisempi.
@StaceyAnne Yritettäessä tätä, saan "Ei voi lukea" out "-objektista clk_o; käytä" puskuria "tai" inout "" unohtuiko jotain?
@evading, puskuria lähtöön tarvitaan. VHDL ei pidä siitä, että "clk_2Hz" on lähtö, mutta silti sen arvoa luetaan tällä rivillä "clk_2Hz <= ei clk_2Hz;". Olen muokannut korjausta.
+1 Hyvä esimerkki.Mutta tässä tietämättömyyteni näkyy (uusi VHDL: lle).Mitä eroa on `esijäähdyttimellä <= (muut => '0');` ja `esijäähdyttimellä <= '0';`?
NVM!Kaipasin täysin sitä, mihin `muita 'käytettiin lukiessani VHDL-kirjaa.Se on vain pikakuvake kaikkien muiden "bittien" julistamiseksi yhteiseksi arvoksi sen sijaan, että käytettäisiin jotain "00000000000000000000 ...." jne.
MLM
2013-03-19 07:49:41 UTC
view on stackexchange narkive permalink

Käytä kellon esiasteikkoa.

Esikalkkeri-arvon arvo on (kellonopeus / haluttu kellonopeuden nopeus) / 2 joten (50Mhz (50,000,000) / 2hz (2)) / 2 = 12,500,000, joka binaarisesti olisi 101111101011110000100000 .

Yksinkertaisemmin: (50 000 000) / 2) / 2 = 12 500 000 muunna binaariseksi -> 101111101011110000100000

Tässä on jotkut koodit tekemisistä: Käytä newClock-toimintoa mihin tahansa 2 Hz: n tarvitsemaan ...

  kirjasto IEEE; käytä IEEE.STD_LOGIC_1164.ALL; käytä IEEE.STD_LOGIC_UNSIGNED.ALL; entiteetti ClockPrescaler on portti ( kello: STD_LOGIC-tilassa; - 50 MHz Led: ulos STD_LOGIC); loppu ClockPrescaler; arkkitehtuuri ClockPrescaler-käyttäytyminen on - esijäähdyttimen tulisi olla (kellonopeus / haluttu_kellonopeus) / 2, koska haluat nousevan reunan jokaisen jakson esiskalaattorille: STD_LOGIC_VECTOR (23 alaspäin) 0): = "101111101011110000100000"; - 12 500 000 binaarisignaalin esilaskurin_laskuri: STD_LOGIC_VECTOR (23 alas 0): = (muut = > '0'); signaali newClock: std_logic: = '0'; alkaa Led < = newClock; countClock: prosessi (kello, newClock) alkaa, jos nouseva_reuna (kello) sitten prescaler_counter < = prescaler_counter + 1; if (prescaler_counter > -esikalkkuri) sitten - Iterate newClock < = not newClock; prescaler_counter < = (muut = > '0'); loppu Jos; loppu Jos; lopeta prosessi; lopeta käyttäytyminen;  
Näyttää siltä, ​​että luot kaksi kelloa, yhden 0,5 Hz: n ja yhden 1 Hz: n? (koska kellojaksosi on esikalkkisi * 2?). Lisäksi "+" antaa virheen, koska lisäät slv-tiedostoja, enkä ole niin varma lisäyksen ylivuoto-ominaisuuden käytöstä tällä tavalla. miksi ei vain mennä `` newClock: std_logic: = '' 0 '', lasketaan prescaler / 2: een ja määritetään `newClk <= not newClk`?
Kiitos, logiikkani oli vähän poissa. Päivitin alkuperäisen viestini testatulla koodilla nyt ja muutama ehdotuksesi :)
Uh - kaikki nuo ja nollat ​​sekä kommentti, mikä se todella on! Miksi et käytä kääntäjää tekemään se puolestasi ??? Ja miksi ei vain käyttää kokonaislukuja?
Olen väärässä, mutta luulen, että oletusarvojen käyttöä määritettäessä signaaleja arkkitehtuurissa kuten kohdassa ": = (others => '0')" ei voida syntetisoida.
Se on syntetisoitavissa, mutta toimii periaatteessa vain SRAM-pohjaisilla FPGA-levyillä, kuten useimmat Xilinx, Altera tai Lattice.
Martin Thompson
2013-03-20 17:03:14 UTC
view on stackexchange narkive permalink

Et yleensä halua kelloa mitään hidasta, luo vain käyttöönotto oikealla nopeudella ja käytä sitä logiikassa:

  if rising_edge (50MHz_clk) and enable = ' 1 'sitten  

voit luoda käyttöönoton näin:

  prosessimuuttujien määrä: luonnollinen; aloita, jos nouseva reuna (50MHz_clk) otetaan sitten käyttöön < =' 0 ' ; määrä: = laskenta + 1; jos count = clock_freq / haluttu_freq ota < = '1' käyttöön; määrä: = 0; loppu Jos; end if; lopeta prosessi;  

luo pari vakiota kellotaajuudellasi ja haluamallasi aktivointitaajuudella ja poissa. Käynnistä itse dokumentoiva koodi.

Arturs Vancans
2013-03-20 18:50:32 UTC
view on stackexchange narkive permalink

Ehdotan mieluummin Xilinx primitice -digitaalikellon hallintaohjelman IP-osoitteen käyttämistä.

Siinä on graafinen asetusrajapinta, jossa voit määrittää haluamasi taajuuden. Se luo komponentin, jonka taajuus on haluamasi lähtö.

Se löytyy ohjatusta IP-toiminnosta;

enter image description here

Ja sitten voit määritä haluamasi taajuus: enter image description here

Roger Garzon Nieto
2014-05-11 12:25:26 UTC
view on stackexchange narkive permalink

Faktori = tulosignaalin frecuency / output-prescaler-frecuency.

CE = Clock Enable. Sen pitäisi olla yhden kellon (clk) leveä pulssi tai korkea, jos sitä ei käytetä.

Q = Yhden kellon leveän pulssin lähtösignaali halutulla frukiteetilla.

  kirjasto IEEE ; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; entiteetin esijärjestelmä on yleinen (FACTOR: kokonaisluku); portti (clk: in std_logic; rst: in std_logic; CE: in std_logic; Q: out std_logic); end preskaler; prescalerin_esimerkin_arkkitehtuuri on signaalin counter_reg, counter_next: kokonaislukualue 0 - FACTOR-1; signaali Q_seuraava: std_logic; Aloita - for_prescaler -prosessi (clk, rst) alkaa - prosessi, jos rst = '1', sitten - asynkroninen nollaus (aktiivinen matala) counter_reg < = 0; elsif clk'event ja clk = '1' sitten - nouseva kellon reuna counter_reg < = counter_next; loppu Jos; lopeta prosessi; prosessi (counter_reg, CE) alkaa - prosessi Q_seuraava < = '0'; counter_next < = laskuri_reg; jos CE = '1', niin jos counter_reg = FACTOR-1, sitten counter_next < = 0; Q_seuraava < = '1'; else counter_next < = counter_reg + 1; loppu Jos; loppu Jos; lopeta prosessi; prosessi (clk, rst) alkaa - prosessi, jos rst = '1', sitten - asynkroninen nollaus (aktiivinen matala) Q < = '0'; elsif clk'event ja clk = '1' sitten - nouseva kellonreuna Q < = Q_seuraava; loppu Jos; lopeta prosessi; end for_prescaler;  


Tämä Q & A käännettiin automaattisesti englanniksi.Alkuperäinen sisältö on saatavilla stackexchange-palvelussa, jota kiitämme cc by-sa 3.0-lisenssistä, jolla sitä jaetaan.
Loading...