58 / 63 · अवधारणा
FIFO और मेमोरी की सत्यापन योजना तथा स्वतंत्र स्कोरबोर्ड
कार्यान्वयन के पॉइंटरों से स्वतंत्र queue स्कोरबोर्ड बनाएँ और सीमा, reset, valid तथा अनारंभित पढ़ने को सत्यापन योजना से जोड़ें।
पाठ पढ़ना मुफ़्त है। प्रगति सेव करने के लिए नामांकन करें।
संदर्भ मॉडल को DUT से अलग बनाएँ
सत्यापक, अनुबंध से निकले अपेक्षित मान को DUT से मिलाता है। FIFOFIFO कतार जिसमें पहले डाला गया डेटा पहले निकलता है। पूर्ण, रिक्त और एक साथ पढ़ने-लिखने की अनुमति के नियम इसके व्यवहार के अनुबंध का हिस्सा हैं। और जानें के अंदर के rptr,wptr की नकल करके अपेक्षित मान निकालने पर वही पॉइंटर गलती मॉडल में भी आ सकती है। स्वतंत्र स्कोरबोर्डस्कोरबोर्ड सत्यापन में अपेक्षित डेटा और वास्तविक आउटपुट का क्रम से मिलान करने वाली संदर्भ अवस्था। इसकी गणना स्वतंत्र होती है; यह कार्यान्वयन की आंतरिक अवस्था की नकल नहीं करती। केवल तार्किक क्रम SystemVerilog queue में रखता है। Push स्वीकार हो तो पीछे जोड़ें; pop स्वीकार हो तो आगे से निकालें।
सत्यापन योजना में अवस्था और अनुरोधों के संयुक्त मामले लिखें। Empty, आंशिक रूप से भरी और full—हर अवस्था में कोई अनुरोध नहीं, केवल push, केवल pop और दोनों अनुरोध जाँचें। बार-बार wrap-around, लगातार pop और डेटा रहते हुए reset भी जोड़ें। हर मामला देखा गया या नहीं, यह दर्ज करें; पुनरुत्पादन के लिए random seed और असफल इनपुट रखें।
अपेक्षित स्वीकृति DUT के full या occupancy से नहीं, queue की पिछली संख्या से निकालें।
पुराना सिरा निकालने के बाद नया डेटा पीछे जोड़ें, ताकि full पर दोनों अनुरोध आने से पुराना सिरा सुरक्षित रहे। अपेक्षित होने पर ही dout मिलाएँ।
पूरा टेस्टबेंच
यह पिछले पाठ के fifo4 के साथ संकलित होने वाला पूरा टेस्टबेंच है। यह विलंब और queue वाला सत्यापन कोड है। इनपुट अधोगामी एज पर बदलते हैं और उर्ध्वगामी एज के 1 ps बाद DUT के nonblockingnonblocking अनुक्रमिक RTL में <= द्वारा असाइनमेंट। दाईं ओर का मूल्यांकन कर अद्यतन निर्धारित करता है, जिससे उसी एज के रजिस्टर पुरानी अवस्था के आधार पर गणना करते हैं। और जानें अपडेट का परिणाम मिलाया जाता है।
module tb_fifo4;
timeunit 1ns;
timeprecision 1ps;
typedef logic [7:0] word_t;
logic clk=0, rst=1, push=0, pop=0;
word_t din=0, dout;
logic dout_valid, full, empty;
logic [2:0] occupancy;
word_t model[$], expected;
bit expect_pop, expect_push;
fifo4 dut (.*);
always #5ns clk = ~clk;
always @(posedge clk) begin
if (rst) begin
model.delete();
expect_pop = 0;
end else begin
expect_pop = pop && (model.size() != 0);
expect_push = push && ((model.size() < 4) || expect_pop);
if (expect_pop) expected = model.pop_front();
if (expect_push) model.push_back(din);
end
#1ps;
assert (dout_valid === expect_pop)
else $fatal(1, "valid mismatch");
if (expect_pop)
assert (dout === expected)
else $fatal(1, "data mismatch");
assert (int'(occupancy) === model.size())
else $fatal(1, "count mismatch");
assert (empty === (model.size() == 0))
else $fatal(1, "empty mismatch");
assert (full === (model.size() == 4))
else $fatal(1, "full mismatch");
end
task automatic step(input bit r, p, o, input word_t d);
@(negedge clk);
rst=r; push=p; pop=o; din=d;
endtask
initial begin
step(0,0,1,0);
step(0,1,1,8'hA0);
for (int i=1; i<4; i++)
step(0,1,0,word_t'(160+i));
step(0,1,0,8'hEE);
step(0,1,1,8'hB0);
repeat (5) step(0,0,1,0);
repeat (3) begin
for (int i=0; i<4; i++) step(0,1,0,word_t'(i));
repeat (4) step(0,0,1,0);
end
step(0,1,0,8'h5A);
step(1,1,1,8'hFF);
step(0,0,1,0);
repeat (100)
step(0,bit'($urandom_range(1,0)),bit'($urandom_range(1,0)),
word_t'($urandom));
repeat (4) step(0,0,1,0);
@(negedge clk);
$display("PASS");
$finish;
end
endmoduleपहले उर्ध्वगामी एज पर rst=1 है, इसलिए DUT और मॉडल दोनों खाली होते हैं। ===, X सहित कठोर तुलना करता है। Valid=0 पर अनारंभित dout नहीं मिलाते, लेकिन valid स्वयं X हो तो जाँच असफल होती है। अंतिम चार pop शेष सारा डेटा जाँचते हैं। PASS वह संदेश है जो वास्तव में यह टेस्ट चलने और सभी assertion पार होने पर मिलता है; यहाँ कोड देना मात्र उसके निष्पादित होने का प्रमाण नहीं है।
लेखन डेटा B0 डालने से पहले पुराना सिरा A0 अपेक्षित आउटपुट के रूप में अलग रखें। यह पॉइंटर या भौतिक स्थानों के बजाय डेटा के तार्किक क्रम की तुलना है।
- पिछली कतार: [A0, A1, A2, A3]
- अपेक्षित pop मान: पुराना सिरा A0 सहेजें
- push लागू करें: [A1, A2, A3, B0]
- उत्तर मिलाएँ: valid=1 पर dout=A0
सीमा उदाहरणों से स्कोरबोर्ड जाँचें
Queue [A0,A1,A2,A3] हो और केवल push आए, तो संख्या 4 होने से EE त्यागा जाता है। अगले संयुक्त अनुरोध में पहले expected=A0 सहेजें और B0 पीछे जोड़कर [A1,A2,A3,B0] बनाएँ। DUT नया B0 तुरंत निकाले तो डेटा assertion असफल होगी। इसके विपरीत, empty पर संयुक्त अनुरोध expect_pop=0,expect_push=1 देता है; आउटपुट तुलना के बिना एक मद रखी जाती है। Reset में दोनों अनुरोध अनदेखे होते हैं, queue खाली होती है और valid=0 जाँचा जाता है।
मेमोरी सत्यापन में भी यही सिद्धांत उपयोग करें। हर पते की संदर्भ सरणी और initialized तालिका रखें। Read-first में संदर्भ लेखन अपडेट से पहले पढ़ने का अपेक्षित मान सहेजें। रजिस्टररजिस्टर कई बिटों की अवस्था संग्रहित करता है। इस पाठ्यक्रम के तुल्यकालिक रजिस्टर निर्धारित इनपुट को क्लॉक एज पर संग्रहित करते हैं। और जानें फाइल के बाइपास में टक्कर होने पर wr_data चुनें, फिर संदर्भ सरणी में लेखन लागू करें। अनारंभित पते पढ़ने को मना करना है या अपरिभाषित उत्तर स्वीकार करने हैं, इसे टेस्ट की धारणा में लिखें; मनमाने ढंग से 0 को सही उत्तर न बनाएँ। पते से चलने वाली मेमोरी को अलग सत्यापक चाहिए।
एक-एक करके गलतियाँ डालें: full पर साथ आए pop को नया मान लौटाना, दोनों स्वीकृतियों पर संख्या बढ़ाना, या empty pop पर valid सक्रिय करना। संबंधित जाँच अवश्य असफल होनी चाहिए। ऐसी समीक्षा और हर सीमा की coverage से टेस्ट में छूटे मामले मिलते हैं। RAM संसाधन में मैपिंग और टाइमिंग अलग संश्लेषण तथा टाइमिंग सत्यापन से जाँचें।
खुद आज़माएँ
गलत स्कोरबोर्ड पहले push अनुरोध queue में डालता है, फिर अपडेट हुई संख्या से pop की अनुमति तय करता है। Empty में push और pop साथ आने पर क्या गलत निर्णय होगा? Full में दोनों अनुरोध हों तो अपेक्षित डेटा कब सहेजना चाहिए? Reset के बाद हमेशा dout=0 जाँचने के नियम का भी मूल्यांकन करें।
व्याख्या पढ़ें
Empty में नई मद तुरंत pop की जा सकती है, ऐसा गलत मानकर expect_pop=1 बनेगा। अनुबंध में स्वीकृति एज से पहले की संख्या पर निर्भर है, इसलिए केवल push स्वीकार होगा और आउटपुट valid=0 होना चाहिए। Full में पहले पुराना सिरा expected में सहेजकर निकालें, फिर नया डेटा पीछे डालें। Reset, dout को 0 नहीं करता, इसलिए valid=0 और queue व occupancy का खाली होना ही जाँचें। डेटा तुलना expect_pop=1 पर करें और DUT valid को अलग भी जाँचें; अन्यथा हमेशा valid=0 देने की गलती छूट सकती है।