Saat menulis VHDL, saya sangat merekomendasikan menggunakan std_logic_vector (slv) daripada integer (int) untuk SIGNALS . (Di sisi lain, menggunakan int untuk generik, beberapa konstanta, dan beberapa variabel bisa sangat berguna.) Sederhananya, jika Anda mendeklarasikan sinyal tipe int, atau harus menentukan rentang untuk integer maka Anda mungkin melakukan sesuatu yang salah.
Masalah dengan int adalah bahwa programmer VHDL tidak tahu apa representasi logika internal dari int, sehingga kami tidak dapat memanfaatkannya. Sebagai contoh, jika saya mendefinisikan int kisaran 1 hingga 10, saya tidak tahu bagaimana kompiler mengkodekan nilai-nilai itu. Semoga itu akan dikodekan sebagai 4 bit, tetapi kita tidak tahu banyak tentang itu. Jika Anda dapat menyelidiki sinyal di dalam FPGA itu mungkin dikodekan sebagai "0001" menjadi "1010", atau dikodekan sebagai "0000" menjadi "1001". Mungkin juga dikodekan dengan cara yang sama sekali tidak masuk akal bagi kita manusia.
Sebaliknya, kita hanya harus menggunakan slv daripada int, karena dengan demikian kita memiliki kontrol atas pengkodean dan juga memiliki akses langsung ke bit individu. Memiliki akses langsung itu penting, seperti yang akan Anda lihat nanti.
Kita bisa memberikan int ke slv kapan pun kita membutuhkan akses ke bit individual, tetapi itu menjadi sangat berantakan, sangat cepat. Itu seperti mendapatkan yang terburuk dari kedua dunia alih-alih yang terbaik dari kedua dunia. Kode Anda akan sulit untuk dioptimalkan oleh kompiler, dan hampir mustahil untuk Anda baca. Saya tidak merekomendasikan ini.
Jadi, seperti yang saya katakan, dengan slv Anda memiliki kontrol atas penyandian bit dan akses langsung ke bit. Jadi apa yang dapat Anda lakukan dengan ini? Saya akan menunjukkan beberapa contoh. Katakanlah Anda perlu mengeluarkan pulsa setiap 4.294.000.000 jam. Inilah cara Anda melakukan ini dengan int:
signal count :integer range 0 to 4293999999; -- a 32 bit integer
process (clk)
begin
if rising_edge(clk) then
if count = 4293999999 then -- The important line!
count <= 0;
pulse <= '1';
else
count <= count + 1;
pulse <= '0';
end if;
end if;
end process;
Dan kode yang sama menggunakan slv:
use ieee.numeric_std.all;
signal count :std_logic_vector (32 downto 0); -- a 33 bit integer, one extra bit!
process (clk)
begin
if rising_edge(clk) then
if count(count'high)='1' then -- The important line!
count <= std_logic_vector(4293999999-1,count'length);
pulse <= '1';
else
count <= count - 1;
pulse <= '0';
end if;
end if;
end process;
Sebagian besar kode ini identik antara int dan slv, setidaknya dalam arti ukuran dan kecepatan logika yang dihasilkan. Tentu saja satu menghitung mundur dan yang lainnya menghitung mundur, tetapi itu tidak penting untuk contoh ini.
Perbedaannya ada pada "garis penting".
Dengan contoh int, ini akan menghasilkan komparator 32-input. Dengan 4-Input LUT yang digunakan Xilinx Spartan-3, ini akan membutuhkan 11 LUT dan 3 level logika. Beberapa kompiler mungkin mengubahnya menjadi pengurangan yang akan menggunakan rantai carry dan span setara dengan 32 LUT tetapi mungkin berjalan lebih cepat dari 3 level logika.
Dengan contoh slv, tidak ada perbandingan 32-bit sehingga "nol LUT, nol tingkat logika". Satu-satunya penalti adalah bahwa counter kami adalah satu bit ekstra. Karena waktu tambahan untuk penghitung ekstra ini semuanya ada dalam rantai penampung, ada penundaan waktu tambahan "hampir nol".
Tentu saja ini adalah contoh ekstrem, karena kebanyakan orang tidak akan menggunakan penghitung 32-bit dengan cara ini. Itu berlaku untuk penghitung yang lebih kecil, tetapi perbedaannya akan kurang dramatis meskipun masih signifikan.
Ini hanya satu contoh bagaimana memanfaatkan slv over int untuk mendapatkan pengaturan waktu yang lebih cepat. Ada banyak cara lain untuk memanfaatkan slv - hanya dibutuhkan beberapa imajinasi.
Pembaruan: Menambahkan hal-hal untuk menanggapi komentar Martin Thompson tentang penggunaan int dengan "if (count-1) <0"
(Catatan: Saya berasumsi Anda bermaksud "jika menghitung <0", karena itu akan membuatnya lebih setara dengan versi slv saya dan menghapus kebutuhan untuk pengurangan tambahan itu.)
Dalam beberapa keadaan ini mungkin menghasilkan implementasi logika yang dimaksud tetapi tidak dijamin berfungsi sepanjang waktu. Itu akan tergantung pada kode Anda dan bagaimana kompiler Anda mengkodekan nilai int.
Bergantung pada kompiler Anda, dan bagaimana Anda menentukan rentang int Anda, sangat mungkin bahwa nilai int nol tidak menyandikan ke vektor bit "0000 ... 0000" ketika membuatnya menjadi logika FPGA. Agar variasi Anda berfungsi, itu harus disandikan ke "0000 ... 0000".
Misalnya, katakanlah Anda menetapkan int untuk memiliki rentang -5 hingga +5. Anda mengharapkan nilai 0 dikodekan menjadi 4 bit seperti "0000", dan +5 sebagai "0101" dan -5 sebagai "1011". Ini adalah skema pengkodean dua-pelengkap khas.
Tetapi jangan berasumsi bahwa kompiler akan menggunakan dua-pelengkap. Meskipun tidak biasa, komplemen satu dapat menghasilkan logika "lebih baik". Atau, kompiler dapat menggunakan semacam pengkodean "bias" di mana -5 dikodekan sebagai "0000", 0 sebagai "0101", dan +5 sebagai "1010".
Jika pengkodean int adalah "benar" maka kompiler kemungkinan akan menyimpulkan apa yang harus dilakukan dengan carry bit. Tetapi jika itu salah maka logika yang dihasilkan akan mengerikan.
Mungkin saja menggunakan int dengan cara ini bisa menghasilkan ukuran dan kecepatan logika yang masuk akal, tetapi itu bukan jaminan. Beralih ke kompiler yang berbeda (XST ke Sinopsis misalnya), atau pergi ke arsitektur FPGA yang berbeda dapat menyebabkan hal yang salah terjadi.
Belum ditandatangani / ditandatangani vs slv adalah debat lain. Anda dapat berterima kasih kepada komite Pemerintah AS karena telah memberi kami begitu banyak pilihan dalam VHDL. :) Saya menggunakan slv karena itu adalah standar untuk antarmuka antara modul dan inti. Selain itu, dan beberapa kasus lain dalam simulasi, saya tidak berpikir ada manfaat besar untuk menggunakan slv lebih dari yang ditandatangani / tidak ditandatangani. Saya juga tidak yakin apakah sinyal tri-menyatakan dukungan yang ditandatangani / tidak ditandatangani.