FPGA:0003 – LEDai

Garsą jau turim, dabar biški vaizdo. Yra 3 LED ant tos plokštės sujungti per rezistorių prie Vcc. Pas mano plokštę jie pažymėti kaip D2, D4 ir D5. Aš čia prilitavau skirtingų spalvų LEDus: raudoną, žalią ir mėlyną. O kad dar krūčiau būtų, maitinimo pajungimo indikacijos LEDą D3 padariau baltos spalvos. 🙂

Su FPGA uždegti LEDą galima taip pat, kaip ir mikrokontroleryje- užtenka atitinkamą koją perjunti į žemę (nes LEDas į Vcc) ir LEDai dega. Tiesa jie dega ir dabar, nes nenaudojamos kojos užsiprogramuoja į žemę.
Jei norime, kad LEDas mirksėtu užtenka pagrindinį 50MHz clocką pasidalinti iki kelių hercų ir paduoti į LEDą. Ir jis mirksės.

kažkas tokio:

module ledmirksi(input clock, output ledas);
reg [24:0] cnt;

always @(posedge clk) cnt<=cnt+1;

assign ledas = cnt[23];
endmodule

(ta pati nesamonė kaip ir su garsu, tik lėčiau)

Ar net “grafiškai”:
LED test fpga
Čia naudojamas “megawizardiškas” 64 skaitliukas. Ši greitukinė schema buvo naudota plokštės litavimo tikrinimui. Tačiau vyriausi bitai taip lėtai junginėjasi, kad neužtektu kantrybės pastebėti pokyčius. Galima pasiskaičiuoti dažni:
50 000 000 / (2^64) = ? Hz.

Kaip gautas šitas skaitliukas? Spaudžiam “detalės” ikoną. Pasirenkam “megawizard”. Pasirenkam “Create a new custom megafunction variation”. NEXT. Sąraše išsiskleidžiam “Arithmetic” pogrupį, pasirenkam LPM_COUNTER, pasirenkam jei reikia kalbą “verilog” ir užrašom “output file name”, kad ir “counteris”. Spaudziam NEXT. Užsidega naujas langelis su paveikslėliais. Programa klausia kokio pločio skaitliukas, pasirenkam 64 bitus. “Up only” ir spaudžiam NEXT. Čia pasirinkam “plain binary”. Jokių valdymo “enable” ar būklės “carry” mums nereikia. Spaudžiam NEXT. Čia galima įvesti sinchroninius ir asinchroninius valymo, užpildymo išorine reikšme ar hardwariškai užkoduota reikšme. Nieko mums nereikia. NEXT. Čia parašo ką mums pagimdys, o kairėje jau matosi grafinis skaitliuko vaizdas. NEXT. Parodo kokius failus sukurs šis pluginas. Kai kurie pluginai net oscilogramų paveiksliukus generuoja, kad suprasti kaip veikia elementas. FINISH. O dabar galima spausti OK ir į schemą įmesti tą skaitliuką.

Kodėl naudoti šiuos megavizardus? Ogi todėl, kad softas atsižvelgdamas į naudojama hardwarę gali pritaikyti kokį integruota į mikroschemą sudėtingesnį elementą, o ne tupai konstruoti naudodamas mažiausias universalias detalytes. Taip tauposi resursai, o ir kartais galima panaudoti “krutesni” elementą.

Tačiau, tokių pluginų naudojimas turi ir neigiamą efektą- taip prisirišama prie hardwarės. Net tik prie konkrečios firmos, bet kartais ir prie konkrečios mikroschemų šeimos. Todėl naudokite su saiku.

O jei norime pareguliuoti švietimo intensyvumą, reikia naudoti PWM (impulso pločio moduliaciją). Galima PWM organizuoti labai paprastai:

module pwmas(input clk, output reg ledas);

reg [24:0] cnt;
always @(posedge clk) cnt <= cnt+1;

// Cia generuoja PWM reiksme.
wire [3:0] PWM_input = cnt[23] ? cnt[22:19] : ~cnt[22:19];    // ramp the PWM input up and down

// Cia PWM skaiciuotuvas
always @(posedge clk)
if(PWM_input > cnt[4:1]) ledas<=0; else ledas <=1;

endmodule

Čia jau skiriasi nuo FPGA4FUN puslapio. Jų softa LEDai tikrai kaitalioja savo šviesumą, tačiau oscilografas parodė, kad pas juos ten ne PWM moduliacija, bet kaitaliojamas impulsiukų kiekis per laiko tarpą. Taip, sumoje tai duoda skirtingą raiškį, bet į LEDą pumpuojamas aukštas dažnis. Mano variantas- tikras PWMas. Dažnis išlieka tas pats, o keičiasi tik impulso užpildymas. Aš tik panaudojau RAMP generatorių pagal tuos puslapius.

komanda: wire atsakymas = loginis_tikrinimas ? reikšmė_prie_taip : reikšmė_prie_ne;
tai jau nauja verilog komanda. Toks supaprastintas if-then-else analogas. Galimas ir toks variantas:
assign qr = (kodel) ? x : r ;
tikrai jau nesuprantama :). Subtilų skirtumą tarp “wire” ir “assign” kol kas praleisime, nes dar nesuformulavau tiksliais lietuviškai. Tačiau antra komanda reiškia tą patį: Jei “kodel” buna TRUE, tai qr priskiriama x reikšmė, o kitu atveju r. Tik prašom atkreipti dėmesį, kad ši eilutė yra už always@ bloko ribu. Ji nėra sinchronizuota su sistemos clk. Tai paprasčiausias logikos sujungimas. Todėl nebėra komandos “< =" kuri reiškia "priskirti, nukopijuoti reikšmę į registrą", o paprasta lygybė "=" kuri reikškia labiau "sujungti". T.y. ši komanda priklausomai nuo sąlygos paprasčiausiai sujugia laideliais vieną dalį su kita. Toks kaiptai ir multiplexeris gaunasi. Biški paaiškinsiu kaip čia reikšmė keičiasi, nes pats irgi iškarto nesupratau. Skaitliukas sukasi VISADA. Jo dalis, atskirta taip cnt[8:10] tai dalis veikiančio skaitliuko. Tik jis veikia “lėčiau” nes prasideda nuo 9 bito. Komanda sulygina vieną lėtesnę skaitliuko dalį cnt[23] ir priklausomai nuo reikšmės kaip PWM reikšme naudoja skaitliuko greitesnę dalį cnt[22:19] arba invertuota tą pačią cnt[22:19] reikšmę. Taigi vienu metu skaitliukas didėja, o kitu atveju, invertuotas, mažėja. Taip elegantiškai, be jokių papildomų registrų gaunami gražiai kintama reikšmė.

Beja, “blokų” seka programos listinge neturi jokios svarbos. Čia vėl primenu, kad visi blokai veikia lygiagrečiai. Todėl jei bloką perkelsim į kita listingo vietą niekas nepasikeis.

PWM fpga glow led
Čia “grafinė” schema. LEDai tikrai nėra “aukštadažnis elektronikos elementas” ir jam tikrai nereikia 50MHz. Netgi jei bus per didelis dažnis, LEDas greičiau atrodys elektrotechniškai kaip kondensatorius… Todėl šioje schemoje stovi skaitliukas kuris dalina dažnį. O ir pats modulis taip pajungtas, kad naudotusi mažesnį dažnį. Taip bent jau osciloskopas gražiai parodo PWM. O dažnis man gavosi 195kHz.

3 replies on “FPGA:0003 – LEDai”

  1. Visu pirma Aciu uz sitas pamokeles!
    Antra – uzduosiu klausimus. I viena specifini prietaisa man reikia streaminti duomenis trimis laidais su 2MHz clock’u (panasus protokolas i I2S deja daugiau kanalu). Is situ pamokeliu matau, kad tam labai labai tiktu FPGA. Tik klausimas kaip man is PC i tam tikra FPGA registra paduoti duomenis, kuriuos reikia streaminti (galeciau naudot USBuart konverteri). Ar yra galimybe su Altera softu paprastai ideti i FPGA standartinius duomenu perdavimo interfeisus (uart, spi). Turiu galvoje – paciam neprogramuojant standartiniu protokolu “blokeliu” – kaip pvz Jusu minetas 64bit couteris. Jei taip, tai reiketu aprasyt kaip apdorot priimtus is PC duomenis. O tam gal reiketu naudoti NIOS (kartu su jo uart)? Ar NIOS gali “padeti” duomenis i lygir “isorinius” nios’ui FPGA registrus, is kuriu vyksta streaminimas 2MHz bitreitu? Ar i EP2C5 arba EP2C8 telpa nios mikrokontroleris ir ar lieka dar kam nors vietos? Trecia, tai duomenu streaminimas turetu buti diferencialinis. Kaip suprantu, naudojant fpga net nereiketu statyti single ended-> differential draiveriuku. Diferencini siustuveli atitiktu vietoj vienos isejimo kojos paimant dvi, tik invertuotas vienas kitos atzvilgiu? Jei kas noretu parduoti USB blaster ir fpga eval kit’a, nupirkciau, rasykit 🙂 Dekui uz atsakymus ir pamokeles!

  2. UART draiverių tai pilna pavyzdžių, kad ir tame pačiame fpga4fun.com, neatrodo per daug sudėtingi.

    Beje, užsisakiau Cikloną iš kinų, šitas pamokas pamatęs, ačiū:).

Leave a Reply

Your email address will not be published. Required fields are marked *