Pada pandangan pertama Anda akan mengharapkan kode sumber VHDL di bawah ini berperilaku sebagai register geser. Dalam q itu, seiring waktu akan menjadi
"UUUU0", "UUU00", "UU000", "U0000", "00000", ....
tetapi sebaliknya selalu U
setelah lima (atau lebih) siklus jam berturut-turut.
Kenapa ini?
Kode ini sebenarnya adalah versi yang jauh dari simulasi yang jauh lebih rumit. Tapi itu menunjukkan gejala yang saya lihat.
Ini menunjukkan hasil yang menarik dan tidak terduga ini selama simulasi di bawah ModelSim dan ActiveHDL, saya belum mencoba simulator lain dan akan (kedua untuk penjelasan penyebabnya) ingin tahu apakah orang lain bertindak dengan cara yang sama.
Untuk menjawab pertanyaan ini dengan benar, Anda harus memahami bahwa:
- Saya tahu ini bukan cara terbaik untuk mengimplementasikan register geser
- Saya tahu untuk sintesis RTL ini harus memiliki reset.
- Saya tahu array std_logic adalah std_logic_vector.
- Saya tahu operator agregasi
&
,.
Apa yang saya juga temukan:
- Jika tugas
temp(0)<='0';
dipindahkan dalam proses, itu berfungsi. - Jika loop tidak dibuka (lihat kode komentar), itu berhasil.
Saya akan menegaskan kembali bahwa ini adalah versi yang sangat disederhanakan dari desain yang jauh lebih rumit (untuk CPU pipelined), dikonfigurasi untuk murni menunjukkan hasil simulasi yang tidak terduga. Jenis sinyal yang sebenarnya hanyalah penyederhanaan. Untuk alasan ini, Anda harus mempertimbangkan jawaban Anda dengan kode dalam bentuk apa adanya.
Dugaan saya adalah bahwa pengoptimal mesin simulasi VHDL keliru (atau mungkin sesuai spesifikasi) tidak repot untuk menjalankan ekspresi di dalam loop karena tidak ada sinyal di luar perubahan, meskipun saya dapat membuktikan hal ini dengan menempatkan loop terbuka dalam satu lingkaran.
Jadi saya berharap bahwa jawaban untuk pertanyaan ini lebih berkaitan dengan standar untuk simulasi VHDL dari sintaks VHDL tidak eksplisit dan bagaimana mesin simulasi VHDL melakukan optimisasi mereka, daripada jika diberikan kode contoh adalah cara terbaik untuk melakukan sesuatu atau tidak.
Dan sekarang ke kode saya mensimulasikan:
library ieee;
use ieee.std_logic_1164.all;
entity test_simple is
port (
clk : in std_logic;
q : out std_logic
);
end entity;
architecture example of test_simple is
type t_temp is array(4 downto 0) of std_logic;
signal temp : t_temp;
begin
temp(0) <= '0';
p : process (clk)
begin
if rising_edge(clk) then
for i in 1 to 4 loop
temp(i) <= temp(i - 1);
end loop;
--temp(1) <= temp(0);
--temp(2) <= temp(1);
--temp(3) <= temp(2);
--temp(4) <= temp(3);
end if;
end process p;
q <= temp(4);
end architecture;
Dan bangku tes:
library ieee;
use ieee.std_logic_1164.all;
entity Bench is
end entity;
architecture tb of bench is
component test_simple is
port (
clk : in std_logic;
q : out std_logic
);
end component;
signal clk:std_logic:='0';
signal q:std_logic;
signal rst:std_logic;
constant freq:real:=100.0e3;
begin
clk<=not clk after 0.5 sec / freq;
TB:process
begin
rst<='1';
wait for 10 us;
rst<='0';
wait for 100 us;
wait;
end process;
--Note: rst is not connected
UUT:test_simple port map (clk=>clk,q=>q) ;
end architecture;
sumber
temp(0)
karena tidak ada "peristiwa" yang terkait dengan konstanta literal. Menempatkan tugas di dalamprocess
menciptakan hubungan dengan peristiwa jam yang membuatnya bekerja. Saya ingin tahu apakah menambahkanafter
klausa ke tugas akan menjadi solusi potensial.Jawaban:
Ini ada hubungannya dengan apa yang dapat dengan mudah dievaluasi pada waktu elaborasi, secara formal, apa yang disebut "ekspresi statis lokal". Ini adalah aturan yang terlihat tidak jelas, tetapi perlu beberapa pemikiran - pada akhirnya itu masuk akal, dan simulator Anda cukup benar dalam mengingatkan Anda dengan menghasilkan hasil yang tidak jelas.
Sekarang,
temp(1)
dapat dievaluasi pada waktu kompilasi (bahkan lebih awal dari waktu elaborasi) dan dapat menghasilkan driver pada bit 1 dari "temp".Namun,
temp(i)
melibatkan sedikit lebih banyak pekerjaan untuk alat. Mengingat sifat sepele dari loop terikat di sini (1 hingga 4) jelas bagi kita manusia bahwa suhu (0) tidak dapat didorong dan apa yang Anda lakukan aman. Tapi bayangkan batas-batasnya adalah fungsi-fungsilower(foo) to upper(bar)
dalam sebuah paket yang dideklarasikan di tempat lain ... sekarang yang paling bisa Anda katakan dengan pasti adalah yangtemp
didorong - sehingga ekspresi "lokal statis"temp
.Dan itu berarti bahwa proses dibatasi oleh aturan-aturan ini untuk mendorong semua
temp
, di mana Anda memiliki beberapa drivertemp(0)
- proses mengemudi (tidak ada nilai awal, yaitu 'u') dan eksternaltemp(0) <= '0';
. Jadi secara alami kedua pembalap memutuskan untuk 'U'.Alternatifnya adalah "aturan kecil yang macet" (pendapat) bahwa jika loop bounds adalah konstanta, lakukan satu hal, tetapi jika mereka dinyatakan sebagai sesuatu yang lain, lakukan sesuatu yang lain, dan seterusnya ... aturan kecil yang lebih aneh seperti itu ada, semakin kompleks bahasa menjadi ... menurut saya, bukan solusi yang lebih baik.
sumber