Dalam kursus Desain Logika kita semua belajar bahwa adalah mungkin untuk meminimalkan fungsi logika, misalnya dengan menggunakan peta Karnaugh atau algoritma Quine-McCluskey . Kami juga belajar bahwa nilai "Tidak Peduli" meningkatkan potensi minimalisasi.
Misalnya mengambil file register. The write_address
dan write_data
sinyal tidak terlalu penting ketika write_enable
sinyal '0'
. Dengan demikian, mereka harus diberi nilai "Jangan Peduli" untuk memungkinkan lebih banyak optimasi dalam logika yang menggerakkan sinyal-sinyal ini (yaitu tidak dalam file register itu sendiri).
Apa cara yang benar untuk menentukan nilai "Tidak Peduli" dalam VHDL untuk memungkinkan alat sintesis lebih banyak ruang untuk kemungkinan optimasi?
Sejauh ini saya telah menemukan hal-hal berikut yang mungkin cocok. Tapi saya tidak begitu yakin apa pro dan kontra dari setiap pendekatan:
- Sama sekali tidak menetapkan sinyal. Sepertinya ini bisa berhasil. Namun saya menemukan bahwa itu tidak berfungsi ketika Anda ingin mendefinisikan "melakukan apa-apa yang konstan" dari beberapa
record
jenis, karena catatan konstanta harus sepenuhnya ditentukan (setidaknya Modelsim mengatakan demikian). - The
std_logic_1164
paket mendefinisikan nilai'-' -- Don't care
untukstd_ulogic
. Sepertinya ini adalah pilihan semantik yang benar untuk "tidak peduli" yang eksplisit, tetapi saya belum pernah melihatnya digunakan di mana pun (kecuali dalamcase?
konstruksi VHDL-2008 yang tidak terkait ). - Modelsim menggunakan nilai
'X'
untuk menampilkan sinyal yang tidak ditentukan. Namun saya tidak yakin apakah alat sintesis memahami'X'
penugasan eksplisit sebagai "tidak peduli".
Berikut cuplikan kode yang disederhanakan untuk klarifikasi, tempat saya menginisialisasi sinyal tidak peduli '-'
.
Seperti yang Anda lihat, sinyal control.reg_write_address
dapat memiliki 3 nilai yang berbeda: "----"
, instruction(11 downto 8);
dan instruction(3 downto 0);
. Sekarang saya berharap ini akan disintesis menjadi multiplexer 2-input jika '-'
ditafsirkan sebagai "tidak peduli". Seandainya saya menginisialisasi sinyal dengan (others => '0')
bukannya '-'
, alat harus menghasilkan multiplexer 3-input sebagai gantinya.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package mytypes is
type control_signals_t is record
write_enable : std_logic;
write_address : std_ulogic_vector(3 downto 0);
read_address : std_ulogic_vector(3 downto 0);
end record;
-- All members of this constant must be fully specified.
-- So it's not possible to simply not assign a value.
constant CONTROL_NOP : control_signals_t := (
write_enable => '0',
write_address => (others => '-'),
read_address => (others => '-')
);
end package;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library cfx;
use cfx.mytypes.all;
entity control_unit is
port(
instruction : in std_ulogic_vector(15 downto 0);
write_data : out std_ulogic_vector(15 downto 0);
ctrl : out control_signals_t
);
end entity;
architecture rtl of control_unit is
begin
decode_instruction : process(instruction) is
begin
-- Set sensible default values that do nothing.
-- Especially all "write_enable" signals should be '0'.
-- Everything else is mostly irrelevant (don't care).
ctrl <= CONTROL_NOP;
write_data <= (others => '-');
if instruction(15 downto 12) = "1100" then
-- Load 8 bit of data into the register file
ctrl.write_enable <= '1';
write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 0)), 16));
ctrl.write_address <= instruction(11 downto 8);
elsif instruction(15 downto 8) = "11111001" then
-- Load 4 bit of data into the register file
write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 4)), 16));
ctrl.write_address <= instruction(3 downto 0);
elsif instruction(15 downto 8) = "10110101" then
-- Read from the register file. Don't use the write signals at all.
ctrl.read_address <= instruction(3 downto 0);
end if;
end process;
end architecture;
sumber
write_address
danwrite_data
? Optimalisasi apa yang Anda harapkan terjadi?Jawaban:
Saya akan menyerahkannya kepada ahli LRM untuk memberikan jawaban yang lebih rinci, tetapi singkatnya, pendekatan Anda harus valid - saya menjalankan tes cepat dengan versi terbaru Quartus, dan menangani
'-'
seperti yang seharusnya - logika yang dihasilkan dikurangi seperti yang diharapkan ketika output default'-'
('X'
berfungsi juga, by the way). Lebih lanjut tentang pendekatan yang Anda cantumkan:Tidak menetapkan sinyal bukan pilihan untuk contoh Anda, tentu saja, jika Anda tidak ingin kait. Jika ini adalah proses yang sudah berjalan, Anda sedikit lebih baik, tetapi Anda masih bisa mengaktifkannya di tempat yang mungkin tidak Anda perlukan. Mungkin aku kehilangan niatmu di sini.
'-'
, seperti yang disebutkan sebelumnya, mungkin merupakan pilihan terbaik, karena alasan semantik dan praktis.Tergantung pada apa yang Anda maksud dengan "undefined".
'X'
secara teknis "tidak dikenal".'U'
untuk sinyal yang tidak diinisialisasi, yang ditampilkan ModelSim"X"
untuk representasi hex.'X'
tampaknya bekerja, seperti yang saya sebutkan di atas.Alternatif lain adalah melakukan optimasi sendiri dan menghapus satu kasus agar tidak diuji secara eksplisit:
Ini memiliki kelemahan yang signifikan (sebagian besar terkait dengan kejelasan kode), dan saya mungkin akan memilih solusi yang lebih ideal.
Secara kebetulan,
'-'
ini juga biasa digunakan denganstd_match()
, yang saya akan pertimbangkan untuk menggunakan decoding Anda, misalnya:Meskipun pada titik itu, Anda mungkin lebih baik hanya menggunakan
case?
.sumber
Singkatnya: Ini VHDL legal dan biasanya didukung oleh alat sintesis.
Namun agak jarang melihatnya digunakan. Saya tidak tahu kenapa. Menurut saya, kode Anda adalah contoh yang baik untuk menggunakannya.
Namun ada satu kelemahan yang harus diperhatikan: pada sintesis, fungsi-fungsi yang mendorong output di mana tidak peduli yang terlibat bisa berbeda antara proses sintesis. Ini membuat sintesis kurang deterministik. Jika output yang telah didefinisikan sebagai tidak peduli digunakan (karena kesalahan), ini dapat membuat kesalahan lebih sulit ditemukan.
Dukungan alat
Setidaknya alat berikut akan menerima tidak peduli dan memanfaatkan kemungkinan optimasi:
Xilinx dan Altera akan memperlakukan
'-'
dan'X'
sebagai tidak peduli, Synplify akan memperlakukan mereka dan lebih jauh'U'
dan'W'
(lemah) tidak peduli.sumber
if signal = '1' then a; else b; end if;
. Sayangnyasignal
tidak1
atau0
tapi-
. Jadi dalam simulasi,else
cabang dieksekusi, tetapi dalam perangkat keras-
ternyata menjadi1
, jadi cabang yang sebenarnya dieksekusi ...'U'
s, umum di awal simulasi, yang telah digunakan mengarah ke beberapaelse
blok kode yang dieksekusi. Akan luar biasa jika kondisional entah bagaimana bisa dibuat untuk diperbanyak'U'
, mirip dengan perilaku ekspresi boolean bersamaan.if signal = '1' then output <= '1'; elsif signal='0' then output <= '0'; else output <= '-'; end if;
. Dan saya menambahkan yang berikut ini ke semua register dan memori:assert not is_X(write_enable) report "we=" & str(A_write_enable) severity ERROR;
danif write_enable = '1' then assert not is_X(write_addr) report "write_addr=str(write_addr) severity ERROR; end if;
. Ditambah sama untukwrite_data
. Bersama-sama, itu seharusnya menangkap hampir semua kesalahan ini.