Apakah sulit untuk menulis program VHDL pertama Anda?

Apakah sulit untuk menulis program VHDL pertama Anda? Sulit dikatakan, tetapi hal utama di sini adalah motivasi ...


Mungkin saya bisa menunda momen ini, tetapi seorang tetangga meminta saya untuk membuat generator pulsa persegi panjang sehingga bisa ditampilkan dengan jelas dan mungkin untuk mengontrol frekuensi dan durasi pulsa.

Dan dengan akurasi 0,1 mikrodetik ...

Dan pendapat saya jatuh pada syal dengan CPLD (200 rubel, semacam) di mana ada indikator dan tombol. Begitu Anda harus mulai bekerja dengan hal seperti itu, saya pikir, dan ...

Pilihan tentang apa yang harus ditulis VHDL atau Verilog tidak - walaupun saya menulis semuanya dalam C, tapi saya masih suka Ada - jadi VHDL unik. Selain itu, setelah membaca pengantar FPGA, saya menyadari bahwa tidak ada yang rumit (well, setidaknya untuk tugas yang sederhana).

Jadi, pada mulanya adalah kata mari kita menjadikan diri kita generator. Frekuensi rusak asli adalah 50 MHz, yaitu, kami akan menguranginya menjadi 10, sehingga beralih dari garis jam akan berada di tengah dan akhir. Inilah yang terjadi.

-- 100 ns signal generator process(clk) variable t:integer range 0 to 5 := 0; begin if rising_edge(clk) then t := t + 1; if t = 5 then t := 0; tact <= not tact; end if; if t = 2 then tact <= not tact; end if; end if; end process; 

Maka Anda perlu entah bagaimana menampilkan dan mengelola. Kami memiliki dua nilai - panjang periode dan panjang impuls, sehingga untuk panjang periode kami menetapkan 3 keakraban (dengan mempertimbangkan persepuluh), dan untuk panjang periode - 3.

 shared variable period : integer range 0 to 1000 := 500; shared variable duty : integer range 0 to 1000 := 250; shared variable dig1:std_logic_vector(3 downto 0):="0000"; shared variable dig2:std_logic_vector(3 downto 0):="0101"; shared variable dig3:std_logic_vector(3 downto 0):="0010"; shared variable di1:std_logic_vector(3 downto 0):="0000"; shared variable di2:std_logic_vector(3 downto 0):="0000"; shared variable di3:std_logic_vector(3 downto 0):="0101"; 

Nah, untuk kontrol, sinyal dari tombol cocok, yang terlihat di bagian bawah papan - hanya ada 4,
jadi biarkan dua mengontrol perubahan dalam periode dan momentum, masing-masing, satu menetapkan tanda perubahan, dan satu lagi menghidupkan dan mematikan generator ...

Ini manajemennya
 process(key1) begin if rising_edge(key1) then ready <= not ready; end if; end process; process(key3) begin if rising_edge(key3) then if key4 = '1' then inc_duty; else dec_duty; end if; end if; end process; process(key2) begin if rising_edge(key2) then if key4 = '1' then inc_period; else dec_period; end if; end if; end process; 


Dalam manajemen ada prosedur inc / dec, di sini mereka
 procedure inc_duty is begin if duty < period then duty := duty + 1; if dig1 = "1001" then dig1 := "0000"; if dig2 = "1001" then dig2 := "0000"; if dig3 = "1001" then dig3 := "0000"; else dig3 := dig3 + 1; end if; else dig2 := dig2 + 1; end if; else dig1 := dig1 + 1; end if; end if; end procedure; procedure dec_duty is begin if duty > 1 then duty := duty - 1; if dig1 = "0000" then dig1 := "1001"; if dig2 = "0000" then dig2 := "1001"; dig3 := dig3 - 1; else dig2 := dig2 - 1; end if; else dig1 := dig1 - 1; end if; end if; end procedure; procedure inc_period is begin if period < 1000 then period := period + 1; if di1 = "1001" then di1 := "0000"; if di2 = "1001" then di2 := "0000"; if di3 = "1001" then di3 := "0000"; else di3 := di3 + 1; end if; else di2 := di2 + 1; end if; else di1 := di1 + 1; end if; end if; end procedure; procedure dec_period is begin if period > 1 then period := period - 1; if di1 = "0000" then di1 := "1001"; if di2 = "0000" then di2 := "1001"; if di3 = "0000" then di3 := "1001"; else di3 := di3 - 1; end if; else di2 := di2 - 1; end if; else di1 := di1 - 1; end if; end if; end procedure; 


Agak panjang dan rumit (itu sebabnya diminimalkan), tapi cukup dimengerti.

Yah, kita perlu entah bagaimana menampilkannya - kita memiliki indikator tujuh segmen, dan ada 6 di antaranya (sebenarnya 8). Kami akan menampilkan waktu dan, agar tidak menderita dengan sebuah poin, dalam sepersepuluh mikrodetik.

Biarkan mereka berputar dan menampilkan angka saat ini:

 process(tactX) begin case tactX is when"000"=> en_xhdl<="11111110"; when"001"=> en_xhdl<="11111101"; when"010"=> en_xhdl<="11111011"; when"011"=> en_xhdl<="11110111"; when"100"=> en_xhdl<="11101111"; when"101"=> en_xhdl<="11011111"; when"110"=> en_xhdl<="10111111"; when"111"=> en_xhdl<="01111111"; when others => en_xhdl<="01111111"; end case; end process; process(en_xhdl) begin case en_xhdl is when "11111110"=> data4<=dig1; when "11111101"=> data4<=dig2; when "11111011"=> data4<=dig3; when "11110111"=> data4<="1111"; when "11101111"=> data4<=di1; when "11011111"=> data4<=di2; when "10111111"=> data4<=di3; when "01111111"=> data4<="0000"; when others => data4<="1111"; end case; end process; process(data4) begin case data4 is WHEN "0000" => dataout_xhdl1 <= "11000000"; WHEN "0001" => dataout_xhdl1 <= "11111001"; WHEN "0010" => dataout_xhdl1 <= "10100100"; WHEN "0011" => dataout_xhdl1 <= "10110000"; WHEN "0100" => dataout_xhdl1 <= "10011001"; WHEN "0101" => dataout_xhdl1 <= "10010010"; WHEN "0110" => dataout_xhdl1 <= "10000010"; WHEN "0111" => dataout_xhdl1 <= "11111000"; WHEN "1000" => dataout_xhdl1 <= "10000000"; WHEN "1001" => dataout_xhdl1 <= "10010000"; WHEN OTHERS => dataout_xhdl1 <= "11111111"; END CASE; END PROCESS; 

Jujur saya akui saya menyeret bagian dari kode dari sumber yang datang dengan syal - itu sangat keren dan ditulis dengan jelas! en_xhdl - sinyal ini akan mengontrol indikator yang aktif dalam siklus switching, dataout_xhdl1 - sinyal ini menyala pada LED, well, data4 adalah register sementara dan menyimpan angka.

Tetap menulis hati yang menganggap segalanya - generator itu sendiri. Di sini tactX adalah generator tampilan, dan cnt adalah penghitung posisi pulsa. Nah, lin adalah sinyal dari generator itu sendiri.

 process(tact) variable cntX : integer range 0 to 1000 := 0; variable cnt : integer range 0 to 1000 := 0; begin if rising_edge(tact) then if cntX = 0 then tactX <= tactX + 1; end if; cntX := cntX + 1; if cnt > period then cnt := 0; else cnt := cnt + 1; end if; if cnt = 0 then lin <= '0'; elsif cnt = duty then lin <= '1'; end if; end if; end process; 

Yah, tetap untuk menampilkan data - ini dilakukan terus-menerus, jadi harus ditempatkan di blok eksekusi paralel.

  cat_led <= dataout_xhdl1; en_led <= en_xhdl; led1 <= not ready; out1 <= lin when ready = '1' else '0'; out2 <= not lin when ready = '1' else '0'; 

Pada akhirnya, tutup semua proses secara bersamaan - file Quarus Prime yang dihasilkan diterima, dikompilasi, dan dilaporkan

 Top-level Entity Name v12 Family MAX II Device EPM240T100C5 Timing Models Final Total logic elements 229 / 240 ( 95 % ) Total pins 29 / 80 ( 36 % ) Total virtual pins 0 UFM blocks 0 / 1 ( 0 % ) 

Tahap yang paling membosankan tetap, meskipun sepenuhnya grafis - untuk menetapkan pin tertentu ke sinyal. Dan itu saja - tetap mengisi semuanya ke dalam perangkat dan memeriksa! Menariknya, kami berhasil mempertahankan 229 sel, jadi sudah ada 11 sel yang tersisa - tetapi dalam kenyataannya, hampir semuanya melahap antarmuka - tombol dan tampilan. Sebenarnya generator dapat ditumpuk dalam beberapa sel - Intel memiliki dokumen tempat mereka menjelaskan cara menumpuk dalam 1 LUT - yah, tentu saja, tanpa kontrol ...

Jadi, menjawab pertanyaan tentang tajuk utama - tidak, tidak sulit jika Anda tahu C atau Ada dan Anda memahami cara kerja elektronik digital, dan ya, sulit jika Anda tidak memiliki gagasan tentang hal-hal dasar ... Setidaknya saya membutuhkan waktu sehari untuk menulis dan saya Saya mendapat banyak kesenangan baik dari proses pengembangan, dan dari perangkat yang berfungsi! Dan tetangga itu senang :)

Source: https://habr.com/ru/post/id461621/


All Articles