vhdl ट्यूटोरियल
Vhdl के साथ शुरुआत करना
खोज…
टिप्पणियों
VHDL VHSIC (वेरी हाई स्पीड इंटीग्रेटेड सर्किट) HDL (हार्डवेयर विवरण भाषा) के लिए एक यौगिक संक्षिप्त है। एक हार्डवेयर विवरण भाषा के रूप में, यह मुख्य रूप से वर्णन या मॉडल सर्किट के लिए उपयोग किया जाता है। VHDL सर्किट का वर्णन करने के लिए एक आदर्श भाषा है क्योंकि यह भाषा निर्माण प्रदान करता है जो आसानी से समवर्ती और अनुक्रमिक व्यवहार दोनों का वर्णन करता है और साथ ही निष्पादन मॉडल के साथ होता है जो समवर्ती व्यवहार मॉडलिंग करते समय शुरू की गई अस्पष्टता को दूर करता है।
VHDL की व्याख्या आम तौर पर दो अलग-अलग संदर्भों में की जाती है: सिमुलेशन के लिए और संश्लेषण के लिए। जब संश्लेषण के लिए व्याख्या की जाती है, तो कोड को मॉडल किए गए समतुल्य हार्डवेयर तत्वों में परिवर्तित (संश्लेषित) किया जाता है। VHDL का केवल एक सबसेट आमतौर पर संश्लेषण के दौरान उपयोग के लिए उपलब्ध होता है, और समर्थित भाषा निर्माण मानकीकृत नहीं होते हैं; यह उपयोग किए गए संश्लेषण इंजन और लक्ष्य हार्डवेयर डिवाइस का एक कार्य है। जब वीएचडीएल को सिमुलेशन के लिए व्याख्या की जाती है, तो हार्डवेयर के व्यवहार के मॉडलिंग के लिए सभी भाषा निर्माण उपलब्ध हैं।
संस्करण
संस्करण | रिलीज़ की तारीख |
---|---|
IEEE 1076-1987 | 1988/03/31 |
IEEE 1076-1993 | 1994/06/06 |
IEEE 1076-2000 | 2000/01/30 |
IEEE 1076-2002 | 2002/05/17 |
IEEE 1076c-2007 | 2007-09-05 |
IEEE 1076-2008 | 2009/01/26 |
स्थापना या सेटअप
VHDL प्रोग्राम को सिम्युलेटेड या संश्लेषित किया जा सकता है। सिमुलेशन वह है जो अन्य प्रोग्रामिंग भाषाओं में अधिकांश निष्पादन जैसा दिखता है। संश्लेषण एक वीएचडीएल कार्यक्रम का अनुवाद तर्क द्वार के नेटवर्क में करता है। कई VHDL सिमुलेशन और संश्लेषण उपकरण वाणिज्यिक इलेक्ट्रॉनिक डिजाइन ऑटोमेशन (EDA) सुइट्स के हिस्से हैं। वे अक्सर अन्य हार्डवेयर विवरण भाषाओं (एचडीएल) को भी संभालते हैं, जैसे वेरिलोग, सिस्टमविरलॉग या सिस्टमसी। कुछ मुफ्त और खुले स्रोत एप्लिकेशन मौजूद हैं।
VHDL सिमुलेशन
GHDL शायद सबसे परिपक्व मुक्त और खुला स्रोत VHDL सिम्युलेटर है। : यह बैकएंड इस्तेमाल किया पर निर्भर करता है तीन अलग अलग जायके में आता है gcc
, llvm
या mcode
। निम्न उदाहरण बताते हैं कि जीएनयू / लिनक्स ऑपरेटिंग सिस्टम के तहत मेंटर ग्राफिक्स द्वारा वाणिज्यिक एचडीएल सिम्युलेटर, जीएचडीएल (कोड संस्करण) और mcode
का उपयोग कैसे किया जाता है। चीजें अन्य उपकरणों और अन्य ऑपरेटिंग सिस्टम के साथ बहुत समान होंगी।
नमस्ते दुनिया
एक फ़ाइल बनाएं hello_world.vhd
जिसमें:
-- File hello_world.vhd
entity hello_world is
end entity hello_world;
architecture arc of hello_world is
begin
assert false report "Hello world!" severity note;
end architecture arc;
VHDL संकलन इकाई एक पूर्ण VHDL कार्यक्रम है जिसे अकेले संकलित किया जा सकता है। संस्थाओं VHDL संकलन इकाइयों कि एक डिजिटल सर्किट, अर्थात, इसके इनपुट और आउटपुट बंदरगाहों में से बाहरी इंटरफ़ेस का वर्णन किया जाता है। हमारे उदाहरण में, entity
का नाम hello_world
और खाली है। जो सर्किट हम मॉडलिंग कर रहे हैं वह एक ब्लैक बॉक्स है, इसमें कोई इनपुट नहीं है और न ही कोई आउटपुट है। वास्तुकला एक अन्य प्रकार की संकलन इकाई है। वे हमेशा एक entity
से जुड़े होते हैं और उनका उपयोग डिजिटल सर्किट के व्यवहार का वर्णन करने के लिए किया जाता है। इकाई के व्यवहार का वर्णन करने के लिए एक इकाई में एक या अधिक आर्किटेक्चर हो सकते हैं। हमारे उदाहरण में इकाई केवल arc
नामक एक वास्तुकला से जुड़ी है जिसमें केवल एक VHDL कथन है:
assert false report "Hello world!" severity note;
कथन अनुकार की शुरुआत में निष्पादित किया जाएगा और Hello world!
प्रिंट करेगा Hello world!
मानक आउटपुट पर संदेश। अनुकरण तब समाप्त हो जाएगा क्योंकि कुछ और नहीं किया जाना है। VHDL स्रोत फ़ाइल हमने लिखा है कि दो संकलन इकाइयाँ हैं। हम उन्हें दो अलग-अलग फ़ाइलों में अलग कर सकते थे लेकिन हम उनमें से किसी को भी अलग-अलग फ़ाइलों में विभाजित नहीं कर सकते थे: एक संकलन इकाई पूरी तरह से एक स्रोत फ़ाइल में समाहित होनी चाहिए। ध्यान दें कि इस वास्तुकला को संश्लेषित नहीं किया जा सकता है क्योंकि यह एक फ़ंक्शन का वर्णन नहीं करता है जिसे तर्क गेट्स से सीधे अनुवाद किया जा सकता है।
GHDL के साथ कार्यक्रम का विश्लेषण करें और चलाएं:
$ mkdir gh_work
$ ghdl -a --workdir=gh_work hello_world.vhd
$ ghdl -r --workdir=gh_work hello_world
hello_world.vhd:6:8:@0ms:(assertion note): Hello world!
gh_work
निर्देशिका वह जगह है जहां GHDL उन फ़ाइलों को संग्रहीत करता है जो इसे उत्पन्न करता है। यह - --workdir=gh_work
विकल्प कहता है। विश्लेषण चरण वाक्यविन्यास शुद्धता की जांच करता है और स्रोत फ़ाइल में पाई गई संकलन इकाइयों का वर्णन करते हुए एक पाठ फ़ाइल बनाता है। रन चरण वास्तव में प्रोग्राम को संकलित, लिंक और निष्पादित करता है। ध्यान दें कि, GHDL के mcode
संस्करण में, कोई भी बाइनरी फाइलें उत्पन्न नहीं होती हैं। हर बार जब हम इसका अनुकरण करते हैं, तो कार्यक्रम को पुन: स्थापित किया जाता है। gcc
या llvm
संस्करणों अलग ढंग से व्यवहार। यह भी ध्यान दें कि ghdl -r
एक VHDL स्रोत फ़ाइल का नाम नहीं लेता है, जैसे कि ghdl -a
करता है, लेकिन एक संकलन इकाई का नाम। हमारे मामले में हम इसे entity
का नाम देते हैं। चूंकि इसमें केवल एक architecture
जुड़ा हुआ है, इसलिए यह निर्दिष्ट करने की आवश्यकता नहीं है कि किसको अनुकरण करना है।
मॉडलिम के साथ:
$ vlib ms_work
$ vmap work ms_work
$ vcom hello_world.vhd
$ vsim -c hello_world -do 'run -all; quit'
...
# ** Note: Hello world!
# Time: 0 ns Iteration: 0 Instance: /hello_world
...
vlib
, vmap
, vcom
और vsim
चार कमांड हैं जो vmap
प्रदान करता है। vlib
एक निर्देशिका ( ms_work
) बनाता है जहाँ उत्पन्न फ़ाइलों को संग्रहीत किया जाएगा। vmap
एक निर्देशिका को vlib
द्वारा तार्किक नाम ( work
) के साथ बनाया गया है। vcom
एक VHDL स्रोत फ़ाइल संकलित करता है और, डिफ़ॉल्ट रूप से, work
तार्किक नाम से संबंधित निर्देशिका में परिणाम संग्रहीत करता है। अंत में, vsim
प्रोग्राम का अनुकरण करता है और GHDL के समान उत्पादन करता है। फिर से ध्यान दें कि क्या vsim
पूछता है एक स्रोत फ़ाइल नहीं है, लेकिन पहले से संकलित संकलन इकाई का नाम है। -c
विकल्प डिफ़ॉल्ट ग्राफ़िकल यूज़र इंटरफ़ेस (GUI) मोड के बजाय कमांड लाइन मोड में चलाने के लिए सिम्युलेटर को बताता है। -do
विकल्प का उपयोग डिज़ाइन को लोड करने के बाद निष्पादित करने के लिए एक टीसीएल स्क्रिप्ट को पास करने के लिए किया जाता है। टीसीएल एक स्क्रिप्टिंग भाषा है जिसे बहुत बार ईडीए टूल्स में उपयोग किया जाता है। -do
विकल्प का मान किसी फ़ाइल का नाम हो सकता है या, जैसे हमारे उदाहरण में, TCL कमांड्स की एक स्ट्रिंग। run -all; quit
सिम्युलेटर हिदायत जब तक यह स्वाभाविक रूप से समाप्त हो जाती है सिम्युलेशन चलाने के लिए - या हमेशा के लिए अगर यह हमेशा के लिए रहता - और फिर बाहर निकलने के लिए।
समकालिक काउंटर
-- File counter.vhd
-- The entity is the interface part. It has a name and a set of input / output
-- ports. Ports have a name, a direction and a type. The bit type has only two
-- values: '0' and '1'. It is one of the standard types.
entity counter is
port(
clock: in bit; -- We are using the rising edge of CLOCK
reset: in bit; -- Synchronous and active HIGH
data: out natural -- The current value of the counter
);
end entity counter;
-- The architecture describes the internals. It is always associated
-- to an entity.
architecture sync of counter is
-- The internal signals we use to count. Natural is another standard
-- type. VHDL is not case sensitive.
signal current_value: natural;
signal NEXT_VALUE: natural;
begin
-- A process is a concurrent statement. It is an infinite loop.
process
begin
-- The wait statement is a synchronization instruction. We wait
-- until clock changes and its new value is '1' (a rising edge).
wait until clock = '1';
-- Our reset is synchronous: we consider it only at rising edges
-- of our clock.
if reset = '1' then
-- <= is the signal assignment operator.
current_value <= 0;
else
current_value <= next_value;
end if;
end process;
-- Another process. The sensitivity list is another way to express
-- synchronization constraints. It (approximately) means: wait until
-- one of the signals in the list changes and then execute the process
-- body. Sensitivity list and wait statements cannot be used together
-- in the same process.
process(current_value)
begin
next_value <= current_value + 1;
end process;
-- A concurrent signal assignment, which is just a shorthand for the
-- (trivial) equivalent process.
data <= current_value;
end architecture sync;
नमस्ते दुनिया
शास्त्रीय "हैलो वर्ल्ड!" VHDL में संदेश। सब से सरल शायद कुछ इस तरह है:
-- File hello_world.vhd
entity hello_world is
end entity hello_world;
architecture arc of hello_world is
begin
assert false report "Hello world!" severity note;
end architecture arc;
तुल्यकालिक काउंटर के लिए एक सिमुलेशन वातावरण
सिमुलेशन वातावरण
VHDL डिज़ाइन (डिज़ाइन अंडर टेस्ट या DUT) के लिए एक सिमुलेशन वातावरण एक और VHDL डिज़ाइन है, जो न्यूनतम पर है:
- DUT के इनपुट और आउटपुट पोर्ट के अनुरूप सिग्नल की घोषणा करता है।
- DUT Instantiates और इसके पोर्ट को घोषित संकेतों से जोड़ता है।
- DUT के इनपुट पोर्ट से जुड़े सिग्नल को ड्राइव करने वाली प्रक्रियाओं को तुरंत करता है।
वैकल्पिक रूप से, एक सिमुलेशन वातावरण DUT की तुलना में अन्य डिजाइनों को त्वरित कर सकता है, उदाहरण के लिए, इंटरफेस पर ट्रैफ़िक जनरेटर, संचार प्रोटोकॉल की जांच करने के लिए मॉनिटर, DUT आउटपुट के स्वचालित सत्यापनकर्ता ...
सिमुलेशन पर्यावरण का विश्लेषण, विस्तार और निष्पादन किया जाता है। अधिकांश सिमुलेटर संकेतों का एक सेट का चयन करने की संभावना प्रदान करते हैं, उनके ग्राफिकल तरंगों का निरीक्षण करने, स्रोत कोड में ब्रेकपॉइंट लगाने, स्रोत कोड में कदम ...
आदर्श रूप से, एक सिमुलेशन वातावरण को एक मजबूत गैर-प्रतिगमन परीक्षण के रूप में प्रयोग करने योग्य होना चाहिए, अर्थात, यह स्वचालित रूप से DUT विनिर्देशों के उल्लंघन का पता लगाने, उपयोगी त्रुटि संदेशों की रिपोर्ट करने और DUT कार्यक्षमताओं के उचित कवरेज की गारंटी देने चाहिए। जब इस तरह के सिमुलेशन वातावरण उपलब्ध होते हैं, तो वे यह जांचने के लिए DUT के हर बदलाव पर फिर से दौड़ सकते हैं कि यह अभी भी कार्यात्मक रूप से सही है, बिना सिमुलेशन ट्रैड के थकाऊ और त्रुटि प्रवण दृश्य निरीक्षण की आवश्यकता के बिना।
व्यवहार में, आदर्श या यहां तक कि अच्छे सिमुलेशन वातावरण को डिजाइन करना चुनौतीपूर्ण है। यह अक्सर के रूप में, या उससे भी अधिक, DUT खुद को डिजाइन करने से भी कठिन है।
इस उदाहरण में हम सिंक्रोनस काउंटर उदाहरण के लिए एक सिमुलेशन वातावरण प्रस्तुत करते हैं। हम दिखाते हैं कि इसे GHDL और मॉडलिम का उपयोग करके कैसे चलाना है और GHDL के साथ GTKWave और मॉडलिम के साथ बिल्ट-इन वेवफॉर्म दर्शक का उपयोग करके ग्राफिकल तरंगों का निरीक्षण कैसे करें। हम फिर सिमुलेशन के एक दिलचस्प पहलू पर चर्चा करते हैं: उन्हें कैसे रोकें?
सिंक्रोनस काउंटर के लिए पहला सिमुलेशन वातावरण
सिंक्रोनस काउंटर में दो इनपुट पोर्ट और एक आउटपुट पोर्ट होते हैं। एक बहुत ही सरल सिमुलेशन वातावरण हो सकता है:
-- File counter_sim.vhd
-- Entities of simulation environments are frequently black boxes without
-- ports.
entity counter_sim is
end entity counter_sim;
architecture sim of counter_sim is
-- One signal per port of the DUT. Signals can have the same name as
-- the corresponding port but they do not need to.
signal clk: bit;
signal rst: bit;
signal data: natural;
begin
-- Instantiation of the DUT
u0: entity work.counter(sync)
port map(
clock => clk,
reset => rst,
data => data
);
-- A clock generating process with a 2ns clock period. The process
-- being an infinite loop, the clock will never stop toggling.
process
begin
clk <= '0';
wait for 1 ns;
clk <= '1';
wait for 1 ns;
end process;
-- The process that handles the reset: active from beginning of
-- simulation until the 5th rising edge of the clock.
process
begin
rst <= '1';
for i in 1 to 5 loop
wait until rising_edge(clk);
end loop;
rst <= '0';
wait; -- Eternal wait. Stops the process forever.
end process;
end architecture sim;
GHDL के साथ अनुकरण
इसे GHDL के साथ संकलित करें और अनुकरण करें:
$ mkdir gh_work
$ ghdl -a --workdir=gh_work counter_sim.vhd
counter_sim.vhd:27:24: unit "counter" not found in 'library "work"'
counter_sim.vhd:50:35: no declaration for "rising_edge"
तब त्रुटि संदेश हमें दो महत्वपूर्ण बातें बताते हैं:
- GHDL विश्लेषक ने पाया कि हमारा डिज़ाइन
counter
नाम की एक इकाई को तत्काल बनाता है लेकिन यह इकाई पुस्तकालय केwork
में नहीं मिली। ऐसा इसलिए है क्योंकि हमनेcounter_sim
से पहलेcounter
संकलित नहीं किया था। जब VHDL डिजाइनिंग जो कि इंस्टीट्यूशन एंटिटीज को डिजाइन करती है, तो नीचे के लेवल को हमेशा टॉप लेवल से पहले कंपाइल किया जाना चाहिए (पदानुक्रमित डिजाइन्स को टॉप-डाउन भी कंपेयर किया जा सकता है, लेकिन केवल तब जब वेcomponent
कंप्रेस न करें)। - हमारे डिज़ाइन द्वारा उपयोग किए जाने वाले
rising_edge
फ़ंक्शन को परिभाषित नहीं किया गया है। यह इस तथ्य के कारण है कि यह फ़ंक्शन VHDL 2008 में पेश किया गया था और हमने GHDL को भाषा के इस संस्करण का उपयोग करने के लिए नहीं कहा था (डिफ़ॉल्ट रूप से यह VHDL 1993 का उपयोग VHDL 1987 सिंटैक्स की सहनशीलता के साथ करता है)।
आइए हम दो त्रुटियों को ठीक करें और सिमुलेशन लॉन्च करें:
$ ghdl -a --workdir=gh_work --std=08 counter.vhd counter_sim.vhd
$ ghdl -r --workdir=gh_work --std=08 counter_sim sim
^C
ध्यान दें कि विश्लेषण और सिमुलेशन के लिए --std=08
विकल्प की आवश्यकता है। यह भी ध्यान दें कि हमने एक स्रोत फ़ाइल पर नहीं, इकाई counter_sim
, आर्किटेक्चर sim
पर सिमुलेशन लॉन्च किया।
जैसा कि हमारे सिमुलेशन पर्यावरण में कभी न खत्म होने वाली प्रक्रिया होती है (यह प्रक्रिया जो घड़ी उत्पन्न करती है), सिमुलेशन बंद नहीं होता है और हमें इसे मैन्युअल रूप से बाधित करना होगा। इसके बजाय, हम --stop-time
विकल्प के साथ एक स्टॉप टाइम निर्दिष्ट कर सकते हैं:
$ ghdl -r --workdir=gh_work --std=08 counter_sim sim --stop-time=60ns
ghdl:info: simulation stopped by --stop-time
जैसा कि, सिमुलेशन हमें हमारे DUT के व्यवहार के बारे में ज्यादा नहीं बताता है। आइए एक फाइल में सिग्नल के मूल्य में बदलाव करें:
$ ghdl -r --workdir=gh_work --std=08 counter_sim sim --stop-time=60ns --vcd=counter_sim.vcd
Vcd.Avhpi_Error!
ghdl:info: simulation stopped by --stop-time
(त्रुटि संदेश को अनदेखा करें, यह कुछ ऐसा है जिसे GHDL में ठीक करने की आवश्यकता है और इसका कोई परिणाम नहीं है)। एक counter_sim.vcd
फ़ाइल बनाई गई है। इसमें VCD (ASCII) प्रारूप में सिमुलेशन के दौरान सभी सिग्नल परिवर्तन शामिल हैं। GTKWave हमें इसी ग्राफिकल तरंगों को दिखा सकता है:
$ gtkwave counter_sim.vcd
जहाँ हम देख सकते हैं कि काउंटर उम्मीद के मुताबिक काम करता है।
मॉडलिम के साथ अनुकरण
सिद्धांत बिल्कुल Modelim के साथ समान है:
$ vlib ms_work
...
$ vmap work ms_work
...
$ vcom -nologo -quiet -2008 counter.vhd counter_sim.vhd
$ vsim -voptargs="+acc" 'counter_sim(sim)' -do 'add wave /*; run 60ns'
नोट -voptargs="+acc"
विकल्प vsim
को दिया गया: यह सिम्युलेटर को data
सिग्नल को अनुकूलित करने से रोकता है और हमें इसे तरंगों पर देखने की अनुमति देता है।
सुंदर रूप से सिमुलेशन समाप्त हो रहा है
दोनों सिमुलेटर के साथ हमें कभी भी समाप्त होने वाले सिमुलेशन को बाधित नहीं करना था या एक समर्पित विकल्प के साथ एक स्टॉप समय निर्दिष्ट करना था। यह बहुत सुविधाजनक नहीं है। कई मामलों में एक सिमुलेशन के अंत समय का अनुमान लगाना मुश्किल है। सिमुलेशन पर्यावरण के VHDL कोड के अंदर से सिमुलेशन को रोकने के लिए बेहतर होगा, जब कोई विशेष स्थिति, उदाहरण के लिए, जब काउंटर का वर्तमान मूल्य 20 तक पहुंचता है, तो। यह एक जोर के साथ प्राप्त किया जा सकता है। वह प्रक्रिया जो रीसेट को संभालती है:
process
begin
rst <= '1';
for i in 1 to 5 loop
wait until rising_edge(clk);
end loop;
rst <= '0';
loop
wait until rising_edge(clk);
assert data /= 20 report "End of simulation" severity failure;
end loop;
end process;
जब तक data
20 से भिन्न होता है तब तक सिमुलेशन जारी रहता है। जब data
20 तक पहुंचता है, तो सिमुलेशन एक त्रुटि संदेश के साथ दुर्घटनाग्रस्त हो जाता है:
$ ghdl -a --workdir=gh_work --std=08 counter_sim.vhd
$ ghdl -r --workdir=gh_work --std=08 counter_sim sim
counter_sim.vhd:90:24:@51ns:(assertion failure): End of simulation
ghdl:error: assertion failed
from: process work.counter_sim(sim2).P1 at counter_sim.vhd:90
ghdl:error: simulation failed
ध्यान दें कि हमने केवल सिमुलेशन पर्यावरण को फिर से संकलित किया है: यह एकमात्र डिजाइन है जो बदल गया है और यह शीर्ष स्तर है। था हम केवल संशोधित counter.vhd
, हम करने के लिए फिर से संकलन दोनों पड़ता था: counter.vhd
और क्योंकि यह बदल counter_sim.vhd
क्योंकि यह इस पर निर्भर करता counter.vhd
।
त्रुटि संदेश के साथ सिमुलेशन को क्रैश करना बहुत सुरुचिपूर्ण नहीं है। यह तब भी एक समस्या हो सकती है जब स्वचालित रूप से गैर-प्रतिगमन परीक्षण पास हुआ या नहीं, यह तय करने के लिए स्वचालित रूप से सिमुलेशन संदेशों को पार्स करना। एक बेहतर और बहुत अधिक सुरुचिपूर्ण समाधान सभी प्रक्रियाओं को रोकना है जब एक स्थिति तक पहुंच जाता है। यह, उदाहरण के लिए, सिमुलेशन ( eof
) सिग्नल के boolean
एंड को जोड़कर किया जा सकता है। डिफ़ॉल्ट रूप से इसे सिमुलेशन की शुरुआत में false
माना जाता है। हमारी एक प्रक्रिया इसे true
करने के लिए तय करेगी जब अनुकरण समाप्त होने का समय आ गया है। अन्य सभी प्रक्रियाएं इस सिग्नल की निगरानी करेंगी और जब यह true
हो जाएगा तब तक एक अनन्त wait
साथ रुकेंगी:
signal eos: boolean;
...
process
begin
clk <= '0';
wait for 1 ns;
clk <= '1';
wait for 1 ns;
if eos then
report "End of simulation";
wait;
end if;
end process;
process
begin
rst <= '1';
for i in 1 to 5 loop
wait until rising_edge(clk);
end loop;
rst <= '0';
for i in 1 to 20 loop
wait until rising_edge(clk);
end loop;
eos <= true;
wait;
end process;
$ ghdl -a --workdir=gh_work --std=08 counter_sim.vhd
$ ghdl -r --workdir=gh_work --std=08 counter_sim sim
counter_sim.vhd:120:24:@50ns:(report note): End of simulation
अंतिम लेकिन कम से कम, VHDL 2008 में मानक पैकेज env
और stop
एंड finish
प्रक्रियाओं के साथ पेश किया गया एक और भी बेहतर समाधान है:
use std.env.all;
...
process
begin
rst <= '1';
for i in 1 to 5 loop
wait until rising_edge(clk);
end loop;
rst <= '0';
for i in 1 to 20 loop
wait until rising_edge(clk);
end loop;
finish;
end process;
$ ghdl -a --workdir=gh_work --std=08 counter_sim.vhd
$ ghdl -r --workdir=gh_work --std=08 counter_sim sim
simulation finished @49ns
सिग्नल बनाम चर, VHDL के सिमुलेशन शब्दार्थों का एक संक्षिप्त अवलोकन
यह उदाहरण VHDL भाषा के सबसे बुनियादी पहलुओं में से एक से संबंधित है: सिमुलेशन शब्दार्थ। यह वीएचडीएल शुरुआती के लिए अभिप्रेत है और एक सरल दृष्टिकोण प्रस्तुत करता है जहां कई विवरणों को छोड़ दिया गया है (स्थगित प्रक्रियाएं, वीएचडीएल प्रक्रियात्मक इंटरफ़ेस, साझा चर ...) वास्तविक पूर्ण शब्दार्थ में रुचि रखने वाले पाठक भाषा मैनुअल (एलआरएम) का उल्लेख करेंगे।
संकेत और चर
अधिकांश शास्त्रीय अनिवार्य प्रोग्रामिंग भाषाएं चर का उपयोग करती हैं। वे मूल्य कंटेनर हैं। एक असाइनमेंट ऑपरेटर का उपयोग किसी वैरिएबल में मान को स्टोर करने के लिए किया जाता है:
a = 15;
और एक चर में वर्तमान में संग्रहीत मूल्य को अन्य कथनों में पढ़ा और उपयोग किया जा सकता है:
if(a == 15) { print "Fifteen" }
VHDL भी चर का उपयोग करता है और उनकी अधिकांश समान भाषाओं की तरह ही भूमिका है। लेकिन वीएचडीएल दूसरे प्रकार के मूल्य कंटेनर भी प्रदान करता है: सिग्नल। सिग्नल भी मूल्यों को संग्रहीत करते हैं, उन्हें भी सौंपा और पढ़ा जा सकता है। मूल्यों का प्रकार जो संकेतों में संग्रहीत किया जा सकता है (लगभग) वैरिएबल में समान है।
तो, दो प्रकार के मूल्य वाले कंटेनर क्यों हैं? इस सवाल का जवाब आवश्यक है और भाषा के दिल में है। VHDL में कुछ भी प्रोग्राम करने की कोशिश करने से पहले चर और संकेतों के बीच अंतर को समझना सबसे पहली बात है।
आइए इस अंतर को ठोस उदाहरण पर स्पष्ट करते हैं: गमागमन।
नोट: सभी निम्नलिखित कोड स्निपेट प्रक्रियाओं के भाग हैं। हम बाद में देखेंगे कि क्या प्रक्रियाएं हैं।
tmp := a;
a := b;
b := tmp;
स्वैप वैरिएबल a
और b
। इन 3 निर्देश को क्रियान्वित करने के बाद, की नई सामग्री a
की पुरानी सामग्री है b
और इसके विपरीत। अधिकांश प्रोग्रामिंग भाषाओं की तरह, एक तीसरे अस्थायी चर ( tmp
) की आवश्यकता है। यदि, चर के बजाय, हम संकेतों को स्वैप करना चाहते थे, तो हम लिखेंगे:
r <= s;
s <= r;
या:
s <= r;
r <= s;
उसी परिणाम के साथ और तीसरे अस्थायी संकेत की आवश्यकता के बिना!
नोट: VHDL सिग्नल असाइनमेंट ऑपरेटर
<=
वेरिएबल असाइनमेंट ऑपरेटर से अलग है:=
।
आइए हम एक दूसरे उदाहरण को देखें जिसमें हम यह मानते हैं कि print
उपप्रोग्राम अपने पैरामीटर के दशमलव प्रतिनिधित्व को प्रिंट करता है। यदि a
पूर्णांक चर है और इसका वर्तमान मान 15 है, तो क्रियान्वित करना:
a := 2 * a;
a := a - 5;
a := a / 5;
print(a);
प्रिंट होगा:
5
अगर हम एक डिबगर में कदम से इस कदम पर अमल हम के मूल्य देख सकते हैं a
30, 25 और अंत में 5 के लिए प्रारंभिक 15 से बदलते।
लेकिन अगर s
एक पूर्णांक संकेत है और इसका वर्तमान मान 15 है, तो निष्पादन:
s <= 2 * s;
s <= s - 5;
s <= s / 5;
print(s);
wait on s;
print(s);
प्रिंट होगा:
15
3
यदि हम डिबगर में इस चरण को चरणबद्ध तरीके से निष्पादित करते हैं, तो हम wait
निर्देश के बाद तक s
का कोई भी मूल्य परिवर्तन नहीं देखेंगे। इसके अलावा, के अंतिम मूल्य s
15, 30, 25 या 5 लेकिन 3 नहीं होगा!
यह स्पष्ट रूप से अजीब व्यवहार डिजिटल हार्डवेयर की मौलिक समानांतर प्रकृति के कारण है, जैसा कि हम निम्नलिखित अनुभागों में देखेंगे।
समानता
वीएचडीएल एक हार्डवेयर विवरण भाषा (एचडीएल) है, यह प्रकृति द्वारा समानांतर है। VHDL प्रोग्राम अनुक्रमिक कार्यक्रमों का एक संग्रह है जो समानांतर में चलता है। इन अनुक्रमिक कार्यक्रमों को प्रक्रिया कहा जाता है:
P1: process
begin
instruction1;
instruction2;
...
instructionN;
end process P1;
P2: process
begin
...
end process P2;
प्रक्रियाएं, जैसे हार्डवेयर वे मॉडलिंग कर रहे हैं, कभी समाप्त नहीं होते हैं: वे अनंत लूप हैं। अंतिम निर्देश को निष्पादित करने के बाद, निष्पादन पहले के साथ जारी है।
किसी भी प्रोग्रामिंग भाषा के साथ जो एक रूप या समानता के किसी अन्य का समर्थन करती है, एक अनुसूचक एक वीएचडीएल सिमुलेशन के दौरान किस प्रक्रिया को निष्पादित (और कब) करने के लिए जिम्मेदार है। इसके अलावा, भाषा अंतर-प्रक्रिया संचार और सिंक्रनाइज़ेशन के लिए विशिष्ट निर्माण प्रदान करती है।
निर्धारण
शेड्यूलर सभी प्रक्रियाओं की एक सूची रखता है और उनमें से प्रत्येक के लिए, अपनी वर्तमान स्थिति को रिकॉर्ड करता है जो running
, run-able
या suspended
। running
स्थिति में अधिकांश एक प्रक्रिया में है: एक जो वर्तमान में निष्पादित है। जब तक वर्तमान में चल रही प्रक्रिया wait
निर्देश को निष्पादित नहीं करती है, तब तक यह चलती रहती है और किसी अन्य प्रक्रिया को निष्पादित होने से रोकती है। VHDL शेड्यूलर प्रीपेप्टिव नहीं है: यह प्रत्येक प्रक्रिया की जिम्मेदारी है कि वह खुद को निलंबित करे और अन्य प्रक्रियाओं को चलने दे। यह उन समस्याओं में से एक है जो वीएचडीएल शुरुआती अक्सर मुठभेड़ करते हैं: मुक्त चलने की प्रक्रिया।
P3: process
variable a: integer;
begin
a := s;
a := 2 * a;
r <= a;
end process P3;
नोट: चर
a
स्थानीय रूप से घोषित किया जाता है, जबकि संकेतs
औरr
एक उच्च स्तर पर कहीं और घोषित कर रहे हैं। वीएचडीएल चर उस प्रक्रिया के लिए स्थानीय हैं जो उन्हें घोषित करता है और अन्य प्रक्रियाओं द्वारा नहीं देखा जा सकता है। एक अन्य प्रक्रिया भी नाम के एक चर की घोषणा कर सकतीa
, यह वैसा ही चर नहीं होगा जैसा किP3
प्रक्रिया में से एक है।
जैसे ही शेड्यूलर P3
प्रक्रिया को फिर से शुरू करेगा, सिमुलेशन अटक जाएगा, सिमुलेशन वर्तमान समय अब आगे नहीं बढ़ेगा और इसे रोकने का एकमात्र तरीका सिमुलेशन को मारना या बाधित करना होगा। इसका कारण यह है कि P3
ने wait
विवरण नहीं दिया है और इस प्रकार यह हमेशा के लिए running
है, इसके 3 निर्देशों पर निर्भर रहेगा। किसी अन्य प्रक्रिया को कभी भी चलाने का मौका नहीं दिया जाएगा, भले ही वह run-able
।
यहां तक कि wait
विवरण वाली प्रक्रियाएं भी यही समस्या पैदा कर सकती हैं:
P4: process
variable a: integer;
begin
a := s;
a := 2 * a;
if a = 16 then
wait on s;
end if;
r <= a;
end process P4;
नोट: VHDL इक्विटी ऑपरेटर
=
।
यदि प्रक्रिया P4
को फिर से शुरू किया जाता है, जबकि संकेत s
का मान 3 है, तो यह हमेशा के लिए चलेगा क्योंकि a = 16
स्थिति कभी सत्य नहीं होगी।
आइए हम मान लें कि हमारे वीएचडीएल कार्यक्रम में ऐसी रोग प्रक्रियाएं नहीं हैं। जब रनिंग प्रक्रिया एक wait
निर्देश निष्पादित करती है, तो इसे तुरंत निलंबित कर दिया जाता है और शेड्यूलर इसे suspended
स्थिति में रखता है। wait
निर्देश प्रक्रिया को फिर से run-able
लिए भी शर्त रखता है। उदाहरण:
wait on s;
साधन मुझे संकेत के मूल्य तक निलंबित s
बदल जाता है। यह स्थिति अनुसूचक द्वारा दर्ज की जाती है। शेड्यूलर तब run-able
बीच एक और प्रक्रिया का चयन करता है, इसे running
स्टेट में डालता है और इसे निष्पादित करता है। और जब तक सभी run-able
प्रक्रियाओं को निष्पादित और निलंबित नहीं किया जाता है, तब तक वही दोहराता है।
महत्वपूर्ण नोट: जब कई प्रक्रियाएं
run-able
, तो VHDL मानक यह निर्दिष्ट नहीं करता है कि शेड्यूलर कैसे चुनेंगे कि कौन सा चलाना है। एक परिणाम यह है कि सिम्युलेटर के आधार पर, सिम्युलेटर का संस्करण, ऑपरेटिंग सिस्टम, या कुछ और, एक ही VHDL मॉडल के दो सिमुलेशन एक बिंदु पर, अलग-अलग विकल्प बना सकते हैं और निष्पादित करने के लिए एक अलग प्रक्रिया का चयन कर सकते हैं। यदि इस चुनाव का अनुकरण परिणामों पर प्रभाव पड़ता है, तो हम कह सकते हैं कि VHDL गैर-नियतात्मक है। जैसा कि गैर-नियतात्मकता आमतौर पर अवांछनीय है, गैर-निर्धारक स्थितियों से बचने के लिए प्रोग्रामर की जिम्मेदारी होगी। सौभाग्य से, वीएचडीएल इस बात का ध्यान रखता है और यही वह जगह है जहाँ सिग्नल तस्वीर में प्रवेश करते हैं।
सिग्नल और इंटर-प्रोसेस संचार
VHDL दो विशिष्ट विशेषताओं का उपयोग करके गैर नियतांक से बचता है:
- प्रक्रियाएं केवल संकेतों के माध्यम से सूचना का आदान-प्रदान कर सकती हैं
signal r, s: integer; -- Common to all processes
...
P5: process
variable a: integer; -- Different from variable a of process P6
begin
a := s + 1;
r <= a;
a := r + 1;
wait on s;
end process P5;
P6: process
variable a: integer; -- Different from variable a of process P5
begin
a := r + 1;
s <= a;
wait on r;
end process P6;
नोट: VHDL टिप्पणियों का विस्तार
--
लाइन के अंत तक है।
- VHDL सिग्नल का मान प्रक्रियाओं के निष्पादन के दौरान नहीं बदलता है
हर बार जब कोई संकेत सौंपा जाता है, तो निर्धारित मान को अनुसूचक द्वारा दर्ज किया जाता है लेकिन संकेत का वर्तमान मूल्य अपरिवर्तित रहता है। यह चर के साथ एक और बड़ा अंतर है जो असाइन किए जाने के तुरंत बाद अपना नया मूल्य लेते हैं।
आइए हम उपरोक्त प्रक्रिया P5
निष्पादन को देखें और मान लें कि शेड्यूलर द्वारा फिर से शुरू किए जाने पर a=5
, s=1
और r=0
। निर्देश को निष्पादित करने के बाद a := s + 1;
, चर का मान a
परिवर्तन और 2 (1 + 1) हो जाता है। अगले निर्देश को निष्पादित करते समय r <= a;
यह a
(2) का नया मान है जिसे r
को सौंपा गया है। लेकिन r
एक संकेत जा रहा है, के वर्तमान मूल्य r
अभी भी 0. तो है, जब क्रियान्वित a := r + 1;
, चर a
(तुरंत) मान 1 (0 + 1), नहीं 3 (2 + 1) लेता है अंतर्ज्ञान के रूप में कह सकते हैं कि।
सिग्नल r
वास्तव में अपना नया मूल्य कब लेगा? जब शेड्यूलर ने सभी रन-सक्षम प्रक्रियाओं को निष्पादित किया होगा और वे सभी निलंबित हो जाएंगे। यह भी कहा जाता है: एक डेल्टा चक्र के बाद। यह केवल तब है कि शेड्यूलर उन सभी मूल्यों को देखेगा जिन्हें संकेतों को सौंपा गया है और वास्तव में संकेतों के मूल्यों को अपडेट करते हैं। VHDL सिमुलेशन निष्पादन चरणों और सिग्नल अपडेट चरणों का एक विकल्प है। निष्पादन चरणों के दौरान, संकेतों का मूल्य स्थिर होता है। प्रतीकात्मक, हम कहते हैं कि एक निष्पादन चरण और निम्नलिखित संकेत अद्यतन चरण के बीच समय की एक डेल्टा गुजरे। यह वास्तविक समय नहीं है। एक डेल्टा चक्र की कोई भौतिक अवधि नहीं है।
इस देरी संकेत अद्यतन तंत्र के लिए धन्यवाद, VHDL नियतात्मक है। प्रक्रियाएं केवल संकेतों के साथ संवाद कर सकती हैं और प्रक्रियाओं के निष्पादन के दौरान संकेत नहीं बदलते हैं। इसलिए, प्रक्रियाओं के निष्पादन का क्रम मायने नहीं रखता है: निष्पादन के दौरान उनका बाहरी वातावरण (संकेत) नहीं बदलता है। हमें प्रक्रियाओं के साथ पिछले उदाहरण पर इस दिखा P5
और P6
, जहां प्रारंभिक अवस्था है P5.a=5
, P6.a=10
, s=17
, r=0
और जहां अनुसूचक भागने का फैसला P5
पहला और P6
अगले । निम्न तालिका दो चर का मान दिखाती है, प्रत्येक प्रक्रिया के प्रत्येक निर्देश को निष्पादित करने के बाद संकेतों के वर्तमान और अगले मूल्यों:
प्रक्रिया / निर्देश | P5.a | P6.a | s.current | s.next | r.current | r.next |
---|---|---|---|---|---|---|
प्रारम्भिक अवस्था | 5 | 10 | 17 | 0 | ||
P5 / a := s + 1 | 18 | 10 | 17 | 0 | ||
P5 / r <= a | 18 | 10 | 17 | 0 | 18 | |
P5 / a := r + 1 | 1 | 10 | 17 | 0 | 18 | |
P5 / wait on s | 1 | 10 | 17 | 0 | 18 | |
P6 / a := r + 1 | 1 | 1 | 17 | 0 | 18 | |
P6 / s <= a | 1 | 1 | 17 | 1 | 0 | 18 |
P6 / wait on r | 1 | 1 | 17 | 1 | 0 | 18 |
सिग्नल अपडेट के बाद | 1 | 1 | 1 | 18 |
उन्हीं प्रारंभिक स्थितियों के साथ, यदि शेड्यूलर P6
पहले और P5
को चलाने का निर्णय लेता है:
प्रक्रिया / निर्देश | P5.a | P6.a | s.current | s.next | r.current | r.next |
---|---|---|---|---|---|---|
प्रारम्भिक अवस्था | 5 | 10 | 17 | 0 | ||
P6 / a := r + 1 | 5 | 1 | 17 | 0 | ||
P6 / s <= a | 5 | 1 | 17 | 1 | 0 | |
P6 / wait on r | 5 | 1 | 17 | 1 | 0 | |
P5 / a := s + 1 | 18 | 1 | 17 | 1 | 0 | |
P5 / r <= a | 18 | 1 | 17 | 1 | 0 | 18 |
P5 / a := r + 1 | 1 | 1 | 17 | 1 | 0 | 18 |
P5 / wait on s | 1 | 1 | 17 | 1 | 0 | 18 |
सिग्नल अपडेट के बाद | 1 | 1 | 1 | 18 |
जैसा कि हम देख सकते हैं, हमारी दो प्रक्रियाओं के निष्पादन के बाद, परिणाम वही है जो निष्पादन का क्रम है।
यह काउंटर-सहज संकेत असाइनमेंट शब्दार्थ एक दूसरे प्रकार की समस्याओं का कारण है जो VHDL शुरुआती अक्सर मुठभेड़ करते हैं: असाइनमेंट जो जाहिरा तौर पर काम नहीं करता है क्योंकि यह एक डेल्टा चक्र द्वारा देरी हो रही है। जब चल रही प्रक्रिया को P5
कदम-दर-कदम एक डिबगर में, के बाद r
18 सौंपा गया है और a
सौंपा गया है r + 1
, एक की उम्मीद कर सकता है कि मूल्य a
19 है, लेकिन डिबगर हठपूर्वक कि कहते हैं r=0
और a=1
...
नोट: एक ही सिग्नल को एक ही निष्पादन चरण के दौरान कई बार सौंपा जा सकता है। इस मामले में, यह अंतिम असाइनमेंट है जो सिग्नल के अगले मूल्य को तय करता है। अन्य असाइनमेंट का कोई प्रभाव नहीं पड़ता है, जैसे कि वे कभी निष्पादित नहीं हुए थे।
हमारी समझ की जाँच करने का समय आ गया है: कृपया हमारे पहले स्वेपिंग उदाहरण पर वापस जाएँ और समझने की कोशिश करें:
process
begin
---
s <= r;
r <= s;
---
end process;
वास्तव में तीसरे अस्थायी संकेत की आवश्यकता के बिना संकेत r
और s
स्वैप करता है और क्यों:
process
begin
---
r <= s;
s <= r;
---
end process;
सख्ती से समकक्ष होगा। यह भी समझने की क्यों, अगर प्रयास करें s
एक पूर्णांक संकेत है और इसके वर्तमान मूल्य 15 है, और हम निष्पादित करें:
process
begin
---
s <= 2 * s;
s <= s - 5;
s <= s / 5;
print(s);
wait on s;
print(s);
---
end process;
सिग्नल s
के दो पहले असाइनमेंट का कोई प्रभाव नहीं पड़ता है, s
आखिरकार 3 को क्यों सौंपा गया है और दो मुद्रित मूल्य 15 और 3 क्यों हैं।
भौतिक समय
हार्डवेयर को मॉडल करने के लिए, कुछ ऑपरेशन द्वारा लिए गए भौतिक समय को मॉडल करने में सक्षम होना बहुत उपयोगी है। यहाँ एक उदाहरण है कि यह VHDL में कैसे किया जा सकता है। उदाहरण एक तुल्यकालिक काउंटर को मॉडल करता है और यह एक पूर्ण, स्व-निहित, वीएचडीएल कोड है जिसे संकलित और अनुकरण किया जा सकता है:
-- File counter.vhd
entity counter is
end entity counter;
architecture arc of counter is
signal clk: bit; -- Type bit has two values: '0' and '1'
signal c, nc: natural; -- Natural (non-negative) integers
begin
P1: process
begin
clk <= '0';
wait for 10 ns; -- Ten nano-seconds delay
clk <= '1';
wait for 10 ns; -- Ten nano-seconds delay
end process P1;
P2: process
begin
if clk = '1' and clk'event then
c <= nc;
end if;
wait on clk;
end process P2;
P3: process
begin
nc <= c + 1 after 5 ns; -- Five nano-seconds delay
wait on c;
end process P3;
end architecture arc;
प्रक्रिया P1
में wait
निर्देश का उपयोग तब तक करने के लिए नहीं किया जाता है जब तक कि सिग्नल में परिवर्तन नहीं होता है, जैसे कि हमने अभी तक देखा था, लेकिन एक निश्चित अवधि के लिए प्रतीक्षा करने के लिए। यह प्रक्रिया एक घड़ी जनरेटर मॉडल करती है। सिग्नल clk
हमारे सिस्टम की घड़ी है, यह 20 ns (50 MHz) की अवधि के साथ आवधिक है और इसमें कर्तव्य चक्र है।
प्रक्रिया P2
मॉडल एक रजिस्टर है कि, अगर की बढ़ती बढ़त clk
सिर्फ हुई, प्रदान करती है अपने इनपुट का मूल्य nc
इसके उत्पादन के लिए c
और उसके बाद के अगले मूल्य बदलाव के लिए इंतजार कर रहा है clk
।
प्रक्रिया P3
एक वृद्धिशील मॉडल है जो अपने इनपुट c
के मान को बढ़ाता है, एक के द्वारा बढ़ाता है, इसके आउटपुट nc
... 5 ns के भौतिक विलंब के साथ। यह तब तक इंतजार करता है जब तक इसके इनपुट c
का मूल्य नहीं बदल जाता। यह भी नया है। अब तक हमने हमेशा संकेत दिए हैं:
s <= value;
जो, पिछले अनुभागों में बताए गए कारणों के लिए, हम संक्षेप में अनुवाद कर सकते हैं:
s <= value; -- after delta
इस छोटे से डिजिटल हार्डवेयर सिस्टम को निम्न आकृति द्वारा दर्शाया जा सकता है:
भौतिक समय की शुरूआत के साथ, और यह जानते हुए कि हमारे पास डेल्टा में मापा जाने वाला एक प्रतीकात्मक समय भी है, हमारे पास अब एक दो आयामी समय है जिसे हम T+D
को निरूपित करेंगे जहां T
एक भौतिक समय है जिसे नैनो-सेकंड में मापा जाता है और D
एक संख्या है डेल्टास (बिना भौतिक अवधि के)।
पूरी तस्वीर
वीएचडीएल सिमुलेशन का एक महत्वपूर्ण पहलू है जिस पर हमने अभी तक चर्चा नहीं की है: एक निष्पादन चरण के बाद सभी प्रक्रियाएं suspended
स्थिति में हैं। हमने अनौपचारिक रूप से कहा कि अनुसूचक तब संकेत के मूल्यों को अद्यतन करता है जिन्हें असाइन किया गया है। लेकिन, एक समकालिक काउंटर के हमारे उदाहरण में, क्या यह एक ही समय में संकेत clk
, c
और nc
को अपडेट करेगा? भौतिक देरी के बारे में क्या? और suspended
राज्य में सभी प्रक्रियाओं के साथ आगे क्या होता है और कोई भी run-able
स्थिति में नहीं है?
पूरा (लेकिन सरलीकृत) सिमुलेशन एल्गोरिथ्म निम्नलिखित है:
- प्रारंभ
- वर्तमान समय
Tc
को 0 + 0 (0 ns, 0 डेल्टा-चक्र) पर सेट करें - सभी संकेतों को प्रारंभ करें।
- प्रत्येक प्रक्रिया को तब तक निष्पादित करें जब तक कि वह
wait
विवरण पर निलंबित न हो जाए।- सिग्नल असाइनमेंट के मूल्यों और देरी को रिकॉर्ड करें।
- प्रक्रिया को फिर से शुरू करने के लिए शर्तों को दर्ज करें (देरी या संकेत परिवर्तन)।
- अगली बार
Tn
की तुलना सबसे पहले करें:-
wait for <delay>
द्वारा निलंबित प्रक्रियाओं का फिर से शुरू समय। - अगली बार जिस समय सिग्नल का मूल्य बदल जाएगा।
-
- वर्तमान समय
- सिमुलेशन चक्र
-
Tc=Tn
। - उन संकेतों को अपडेट करें जिनकी आवश्यकता है।
-
run-able
स्थिति में रखें, सभी प्रक्रियाएं जो अपडेट किए गए संकेतों में से एक के मूल्य परिवर्तन की प्रतीक्षा कर रही थीं। -
run-able
स्थिति में रखें जो सभी प्रक्रियाओं कोwait for <delay>
विवरण केwait for <delay>
एकwait for <delay>
द्वारा निलंबित कर दिया गया था और जिसके लिए फिर से शुरू समयTc
। - सभी रन-सक्षम प्रक्रियाओं को निष्पादित करें जब तक कि वे निलंबित न हों।
- सिग्नल असाइनमेंट के मूल्यों और देरी को रिकॉर्ड करें।
- प्रक्रिया को फिर से शुरू करने के लिए शर्तों को दर्ज करें (देरी या संकेत परिवर्तन)।
- अगली बार
Tn
की तुलना सबसे पहले करें:-
wait for <delay>
द्वारा निलंबित प्रक्रियाओं का फिर से शुरू समय। - अगली बार जिस समय सिग्नल का मूल्य बदल जाएगा।
-
- यदि
Tn
अनंत है, तो अनुकरण बंद करें। और, एक नया सिमुलेशन चक्र शुरू करें।
-
मैनुअल सिमुलेशन
निष्कर्ष निकालने के लिए, अब हम मैन्युअल रूप से ऊपर प्रस्तुत सिंक्रोनस काउंटर पर सरलीकृत सिमुलेशन एल्गोरिदम का अभ्यास करें। हम मनमाना निर्णय लेते हैं कि, जब कई प्रक्रियाएं चलाने योग्य होती हैं, तो ऑर्डर P3
> P2
> P1
। निम्नलिखित तालिकाएँ आरंभीकरण और पहले सिमुलेशन चक्रों के दौरान सिस्टम की स्थिति के विकास का प्रतिनिधित्व करती हैं। प्रत्येक सिग्नल का अपना कॉलम होता है जिसमें वर्तमान मूल्य इंगित होता है। जब एक सिग्नल असाइनमेंट निष्पादित किया जाता है, तो निर्धारित मूल्य वर्तमान मूल्य से जुड़ा होता है, उदाहरण के a/b@T+D
यदि वर्तमान मान a
और अगला मूल्य समय पर b
T+D
(भौतिक समय प्लस डेल्टा चक्र) होगा । 3 अंतिम कॉलम स्थिति को निलंबित प्रक्रियाओं को फिर से शुरू करने के लिए संकेत देते हैं (संकेतों का नाम जो बदलना चाहिए या उस समय जिस पर प्रक्रिया फिर से शुरू होगी)।
प्रारंभिक चरण:
संचालन | Tc | Tn | clk | c | nc | P1 | P2 | P3 |
---|---|---|---|---|---|---|---|---|
वर्तमान समय निर्धारित करें | 0 + 0 | |||||||
सभी संकेतों को प्रारंभ करें | 0 + 0 | '0' | 0 | 0 | ||||
P3/nc<=c+1 after 5 ns | 0 + 0 | '0' | 0 | 0/1 @ 5 + 0 | ||||
P3/wait on c | 0 + 0 | '0' | 0 | 0/1 @ 5 + 0 | c | |||
P2/if clk='1'... | 0 + 0 | '0' | 0 | 0/1 @ 5 + 0 | c | |||
P2/end if | 0 + 0 | '0' | 0 | 0/1 @ 5 + 0 | c | |||
P2/wait on clk | 0 + 0 | '0' | 0 | 0/1 @ 5 + 0 | clk | c | ||
P1/clk<='0' | 0 + 0 | '0' / '0' @ 0 + 1 | 0 | 0/1 @ 5 + 0 | clk | c | ||
P1/wait for 10 ns | 0 + 0 | '0' / '0' @ 0 + 1 | 0 | 0/1 @ 5 + 0 | 10 + 0 | clk | c | |
अगली बार गणना करें | 0 + 0 | 0 + 1 | '0' / '0' @ 0 + 1 | 0 | 0/1 @ 5 + 0 | 10 + 0 | clk | c |
सिमुलेशन चक्र # 1
संचालन | Tc | Tn | clk | c | nc | P1 | P2 | P3 |
---|---|---|---|---|---|---|---|---|
वर्तमान समय निर्धारित करें | 0 + 1 | '0' / '0' @ 0 + 1 | 0 | 0/1 @ 5 + 0 | 10 + 0 | clk | c | |
सिग्नल अपडेट करें | 0 + 1 | '0' | 0 | 0/1 @ 5 + 0 | 10 + 0 | clk | c | |
अगली बार गणना करें | 0 + 1 | 5 + 0 | '0' | 0 | 0/1 @ 5 + 0 | 10 + 0 | clk | c |
नोट: पहले सिमुलेशन चक्र के दौरान कोई निष्पादन चरण नहीं है क्योंकि हमारी 3 प्रक्रियाओं में से कोई भी इसकी फिर से शुरू होने वाली स्थिति से संतुष्ट नहीं है।
P2
के एक मूल्य बदलाव के लिए इंतज़ार कर रहा हैclk
और वहाँ पर लेन-देन किया गया हैclk
, लेकिन जैसा कि पुराने और नए मूल्यों ही कर रहे हैं, यह एक मूल्य के परिवर्तन नहीं है।
सिमुलेशन चक्र # 2
संचालन | Tc | Tn | clk | c | nc | P1 | P2 | P3 |
---|---|---|---|---|---|---|---|---|
वर्तमान समय निर्धारित करें | 5 + 0 | '0' | 0 | 0/1 @ 5 + 0 | 10 + 0 | clk | c | |
सिग्नल अपडेट करें | 5 + 0 | '0' | 0 | 1 | 10 + 0 | clk | c | |
अगली बार गणना करें | 5 + 0 | 10 + 0 | '0' | 0 | 1 | 10 + 0 | clk | c |
नोट: फिर से, कोई निष्पादन चरण नहीं है।
nc
बदल लेकिन कोई प्रक्रिया पर इंतज़ार कर रहा हैnc
।
सिमुलेशन चक्र # 3
संचालन | Tc | Tn | clk | c | nc | P1 | P2 | P3 |
---|---|---|---|---|---|---|---|---|
वर्तमान समय निर्धारित करें | 10 + 0 | '0' | 0 | 1 | 10 + 0 | clk | c | |
सिग्नल अपडेट करें | 10 + 0 | '0' | 0 | 1 | 10 + 0 | clk | c | |
P1/clk<='1' | 10 + 0 | '0' / '1' @ 10 + 1 | 0 | 1 | clk | c | ||
P1/wait for 10 ns | 10 + 0 | '0' / '1' @ 10 + 1 | 0 | 1 | 20 + 0 | clk | c | |
अगली बार गणना करें | 10 + 0 | 10 + 1 | '0' / '1' @ 10 + 1 | 0 | 1 | 20 + 0 | clk | c |
सिमुलेशन चक्र # 4
संचालन | Tc | Tn | clk | c | nc | P1 | P2 | P3 |
---|---|---|---|---|---|---|---|---|
वर्तमान समय निर्धारित करें | 10 + 1 | '0' / '1' @ 10 + 1 | 0 | 1 | 20 + 0 | clk | c | |
सिग्नल अपडेट करें | 10 + 1 | '1' | 0 | 1 | 20 + 0 | clk | c | |
P2/if clk='1'... | 10 + 1 | '1' | 0 | 1 | 20 + 0 | c | ||
P2/c<=nc | 10 + 1 | '1' | 0/1 @ 10 + 2 | 1 | 20 + 0 | c | ||
P2/end if | 10 + 1 | '1' | 0/1 @ 10 + 2 | 1 | 20 + 0 | c | ||
P2/wait on clk | 10 + 1 | '1' | 0/1 @ 10 + 2 | 1 | 20 + 0 | clk | c | |
अगली बार गणना करें | 10 + 1 | 10 + 2 | '1' | 0/1 @ 10 + 2 | 1 | 20 + 0 | clk | c |
सिमुलेशन चक्र # 5
संचालन | Tc | Tn | clk | c | nc | P1 | P2 | P3 |
---|---|---|---|---|---|---|---|---|
वर्तमान समय निर्धारित करें | 10 + 2 | '1' | 0/1 @ 10 + 2 | 1 | 20 + 0 | clk | c | |
सिग्नल अपडेट करें | 10 + 2 | '1' | 1 | 1 | 20 + 0 | clk | c | |
P3/nc<=c+1 after 5 ns | 10 + 2 | '1' | 1 | 1/2 @ 15 + 0 | 20 + 0 | clk | ||
P3/wait on c | 10 + 2 | '1' | 1 | 1/2 @ 15 + 0 | 20 + 0 | clk | c | |
अगली बार गणना करें | 10 + 2 | 15 + 0 | '1' | 1 | 1/2 @ 15 + 0 | 20 + 0 | clk | c |
नोट: कोई सोच सकता है कि
nc
अपडेट15+2
पर निर्धारित किया जाएगा, जबकि हमने इसे15+0
पर शेड्यूल किया था। वर्तमान समय (10+2
) में एक शून्य-शून्य भौतिक विलंब (यहाँ5 ns
) जोड़ने पर, डेल्टा चक्र लुप्त हो जाता है। वास्तव में, डेल्टा चक्र केवल अलग-अलग सिमुलेशन समयT+0
,T+1
... को एक ही भौतिक समयT
साथ अलग करने के लिए उपयोगी हैं। जैसे ही भौतिक समय बदलता है, डेल्टा चक्र को रीसेट किया जा सकता है।
सिमुलेशन चक्र # 6
संचालन | Tc | Tn | clk | c | nc | P1 | P2 | P3 |
---|---|---|---|---|---|---|---|---|
वर्तमान समय निर्धारित करें | 15 + 0 | '1' | 1 | 1/2 @ 15 + 0 | 20 + 0 | clk | c | |
सिग्नल अपडेट करें | 15 + 0 | '1' | 1 | 2 | 20 + 0 | clk | c | |
अगली बार गणना करें | 15 + 0 | 20 + 0 | '1' | 1 | 2 | 20 + 0 | clk | c |
नोट: फिर से, कोई निष्पादन चरण नहीं है।
nc
बदल लेकिन कोई प्रक्रिया पर इंतज़ार कर रहा हैnc
।