55 / 63 · अवधारणा
तुल्यकालिक मेमोरी और पढ़ने-लिखने के टकराव का अनुबंध
रजिस्टर्ड पढ़ने के उत्तर का समय और read-first, write-first, no-change अलग पहचानें तथा valid और पते के आरंभीकरण की अलग जिम्मेदारियाँ तय करें।
पाठ पढ़ना मुफ़्त है। प्रगति सेव करने के लिए नामांकन करें।
पते से पहले उत्तर का समय तय करें
मेमोरी जोड़ते समय क्षमता के साथ पढ़ने का विलंब और टकराव का व्यवहार भी तय करना होता है। यहाँ 16 पते हैं, हर पते पर 8 बिट संग्रहीत होते हैं और एक उर्ध्वगामी एज पर एक पढ़ना तथा एक लिखना स्वीकार हो सकता है। दोनों अनुरोध समान क्लॉक का उपयोग करते हैं, लेकिन उनके पते स्वतंत्र हैं। क्षमता 16×8=128 बिट और पता चौड़ाई बिट है।
पढ़ने का पता और rd_en उर्ध्वगामी एज से पहले स्थिर रखने पर, एज के बाद रजिस्टर्ड rd_data और rd_valid मिलते हैं। यह रजिस्टर्ड पढ़ने के एक चरण का विलंब है। कोई अन्य always_ff उसी एज पर इन आउटपुटों को पढ़े तो अपडेट से पहले का मान देखता है; इसलिए उत्तर लेने वाला रजिस्टररजिस्टर कई बिटों की अवस्था संग्रहित करता है। इस पाठ्यक्रम के तुल्यकालिक रजिस्टर निर्धारित इनपुट को क्लॉक एज पर संग्रहित करते हैं। और जानें उसे अगले उर्ध्वगामी एज पर ग्रहण करता है। अनुरोध का समय और उत्तर देखने का समय तरंग पर अलग चिह्नित करें। हर क्लॉक नया अनुरोध लिया जा सकता है, इसलिए एक चरण के विलंब का अर्थ 1/2 थ्रूपुटथ्रूपुट प्रति इकाई समय स्वीकार या पूर्ण किए जाने वाले कार्यों की संख्या। पाइपलाइन किसी एक कार्य का विलंब घटाए बिना भी थ्रूपुट बढ़ा सकती है। और जानें नहीं है।
एक ही पते को पढ़ें और लिखें तो
मान लें एज से ठीक पहले M[3]=8'h25 है और पता 3 पढ़ते समय उस पर 8'h9A लिखते हैं। Read-first उत्तर में 25 देता है और भंडारण को 9A करता है। Write-first नया मान 9A देता है। No-change आउटपुट रजिस्टर को बनाए रखता है, इसलिए उस आउटपुट में पता 3 का पिछला मान होने की गारंटी नहीं है। ये सामान्य व्यवहार के तीन अलग अनुबंध हैं। AMD का RAM समन्वय मोड दस्तावेज भी इन तीनों को अलग करता है।
इस उदाहरण में read-first है। एज से पहले और एज के बाद की सरणी हो, तो reset न होने वाले एज पर हर पते के लिए:
टकराव पर भी पढ़ना नहीं, का उपयोग करता है। पढ़ने का अनुरोध न होने पर rd_data बना रहता है।
module sync_mem16x8 (
input logic clk, rst,
input logic wr_en, rd_en,
input logic [3:0] wr_addr, rd_addr,
input logic [7:0] wr_data,
output logic [7:0] rd_data,
output logic rd_valid
);
timeunit 1ns;
timeprecision 1ps;
logic [7:0] mem [0:15];
always_ff @(posedge clk) begin
if (rst) begin
rd_valid <= 1'b0;
end else begin
rd_valid <= rd_en;
if (wr_en)
mem[wr_addr] <= wr_data;
if (rd_en)
rd_data <= mem[rd_addr];
end
end
endmoduleदोनों असाइनमेंट के दाएँ पक्ष पुराने मान पढ़ते हैं और nonblockingnonblocking अनुक्रमिक RTL में <= द्वारा असाइनमेंट। दाईं ओर का मूल्यांकन कर अद्यतन निर्धारित करता है, जिससे उसी एज के रजिस्टर पुरानी अवस्था के आधार पर गणना करते हैं। और जानें अपडेट उसके बाद लागू होते हैं। इसलिए लिखने का कथन पढ़ने के कथन से पहले रखने पर नया मान पढ़ने का व्यवहार नहीं बन जाता। Write-first चाहिए तो पढ़ने का व्यंजक स्पष्ट रूप से (wr_en && wr_addr==rd_addr) ? wr_data : mem[rd_addr] करें। इस बाइपास में भी पढ़ने वाला आउटपुट रजिस्टर बना रहता है।
Valid और आरंभीकरण अलग वादे हैं
rst active-high तुल्यकालिक reset है। उर्ध्वगामी एज पर rst=1 हो तो दोनों अनुरोध अनदेखे होते हैं और केवल rd_valid को 0 किया जाता है। सरणी और rd_data को शून्य से नहीं भरते। बिजली चालू होने के बाद कभी न लिखे गए पते की सामग्री इस अनुबंध में परिभाषित नहीं है। सिम्युलेटर में X दिख सकता है और वास्तविक हार्डवेयर में भी किसी निश्चित संख्या की धारणा नहीं कर सकते।
rd_valid=1 का अर्थ “पढ़ने के अनुरोध का उत्तर चक्र” है, “पता पहले ही आरंभ हो चुका है और मान ज्ञात है” नहीं। उपयोगकर्ता केवल पहले लिखे पते पढ़े या हर पते की अलग आरंभीकरण तालिका रखे। पहली बार लिखने वाले उसी एज पर read-first से पढ़ने पर भी पुरानी सामग्री अपरिभाषित रहती है। valid=0 होने पर rd_data को गणना में न लेने वाला valid guard भी चाहिए। केवल आरंभ किए पते पढ़ने की शर्त और valid guard एक-दूसरे का स्थान नहीं लेते।
Reset भंडारण नहीं मिटाता, इसलिए पहले लिखे मान RTL में रहते हैं। लेकिन यदि सिस्टम reset के बाद पुरानी सामग्री त्यागता है, तो बाहरी आरंभीकरण तालिका भी उसी अनुसार सँभालनी होगी। संवेदनशील जानकारी मिटाना, नियंत्रण reset से अलग डिजाइन आवश्यकता है।
हर स्तंभ एक उर्ध्वगामी एजउदयी किनारा (rising edge) क्लॉक के 0 से 1 होने का क्षण। यह CLK=1 के पूरे स्तर-अंतराल से अलग है। और जानें का अवलोकन है। इनपुट एज से ठीक पहले के हैं; नाम में “एज के बाद” वाली अवस्थाएँ अपडेट के ठीक बाद की हैं। स्तंभों का संरेखण नमूनों का क्रम दिखाता है, भौतिक प्रसार विलंबप्रसार विलंब इनपुट बदलने के बाद आउटपुट सही मान पर स्थिर होने तक का समय। तार्किक समतुल्यता और समय-संबंधी गुण अलग हैं। और जानें नहीं। पढ़ने और लिखने के सभी पते 3 हैं। E0 पहली बार 25 लिखता है और E1 पर पढ़ते हुए 9A से बदलता है। Data का डैश अपरिभाषित मान दर्शाता है; valid=0 वाला बस उत्तर नहीं गिना जाता। डेटा हेक्साडेसिमल में है।
तरंगरूप डेटा देखें
| संकेत | तरंगरूप | बस मान |
|---|---|---|
| एज | 2345 | E0 → E1 → E2 → E3 |
| wr_en | 1.0. | |
| wr_data | 23.. | 25 → 9A |
| rd_en | 01.0 | |
| एज के बाद M[3] | 23.. | 25 → 9A |
| एज के बाद rd_data | 234. | - → 25 → 9A |
| एज के बाद rd_valid | 01.0 |
चार एज हाथ से देखें
E0 पर पता 3 में 25 लिखें और rd_en=0 रखें। E1 पर उसी पते को पढ़ते हुए 9A लिखें: E1 के बाद valid=1,data=25 है। E2 पर बिना लिखे पता 3 फिर पढ़ें तो data=9A है। E3 पर rd_en=0 हो तो valid=0 और data=9A रहता है। E3 के आउटपुट बस पर 9A होने मात्र से नया उत्तर गिनेंगे तो वही डेटा दो बार संसाधित होगा।
पते अलग हों तो पढ़ना और लिखना स्वतंत्र हैं। उदाहरण के लिए, पता 7 पढ़ते समय पता 3 लिखने पर उत्तर में पता 7 का पुराना मान मिलता है। वास्तविक FPGA में यह RTL किस RAM संसाधन से बनेगा और वह संसाधन एक ही पते की टक्कर कैसे सँभालेगा, इसे संश्लेषण रिपोर्ट और उपकरण के दस्तावेज से जाँचें। RTL का अर्थ निर्धारित करना और किसी विशेष उपकरण पर उसका कार्यान्वयन सत्यापित करना अलग चरण हैं।
खुद आज़माएँ
M[6]=8'h10 पहले से संग्रहीत है। E0 पर पता 6 पढ़ते हुए 8'h20 लिखें, E1 पर बिना लिखे फिर पढ़ें और E2 पर rd_en=0 रखें। Read-first में हर एज के बाद data/valid निकालें। Write-first करने पर क्या बदलेगा? जिस पते पर कभी लिखा न गया हो, वहाँ पहली read-first टक्कर क्या परिभाषित मान देती है?
व्याख्या पढ़ें
E0 के बाद data=10,valid=1 है और सरणी 20 से अपडेट होती है। E1 के बाद data=20,valid=1 है। E2 पर data=20 रहता है, लेकिन valid=0 होने से उसे उत्तर नहीं गिनते। Write-first में केवल E0 का data बदलकर 20 होगा। पहली बार लिखने के साथ read-first पढ़ना, लिखने से पहले का अनारंभित मान देता है; कोई निश्चित मान सही उत्तर नहीं हो सकता। valid=1 भी आरंभीकरण की गारंटी नहीं है।