Altifigence Academy

57 / 63 · अवधारणा

एक क्लॉक वाले FIFO के पॉइंटर और सीमा नीति

गहराई 4 के FIFO के पॉइंटर और occupancy बनाएँ तथा empty और full में एक साथ push/pop स्वीकार होने की शर्तें स्पष्ट करें।

डेटा स्थानांतरित किए बिना क्रम बनाएँ

FIFOFIFO कतार जिसमें पहले डाला गया डेटा पहले निकलता है। पूर्ण, रिक्त और एक साथ पढ़ने-लिखने की अनुमति के नियम इसके व्यवहार के अनुबंध का हिस्सा हैं। पहले डाला गया डेटा पहले निकालता है। एक क्लॉक में पढ़ना और लिखना समान उर्ध्वगामी एज पर तय होते हैं। इस पाठ में DEPTH=4 और डेटा चौड़ाई 8 बिट निश्चित है। rptr अगला निकालने का स्थान और wptr अगला डालने का स्थान बताता है। दोनों 2 बिट हैं, इसलिए 3 के बाद स्वाभाविक रूप से 0 पर लौटते हैं। occupancy को संग्रह संख्या 0–4 दर्शानी है, इसलिए 3 बिट चाहिए।

rptr=wptr, empty और full दोनों में संभव है। केवल दोनों पतों की समानता से empty तय करेंगे तो भरे FIFO का डेटा खो जाएगा। यहाँ अलग संख्या CC रखते हैं और empty=(C=0)\mathrm{empty}=(C=0) तथा full=(C=4)\mathrm{full}=(C=4) से अंतर करते हैं। गहराई D=4D=4 में पता चौड़ाई WaddrW_{\mathrm{addr}} और संख्या चौड़ाई WcountW_{\mathrm{count}} हैं:

Waddr=⌈log⁡2D⌉=2Wcount=⌈log⁡2(D+1)⌉=3\begin{aligned} W_{\mathrm{addr}}&=\lceil\log_2 D\rceil=2\\ W_{\mathrm{count}}&=\lceil\log_2(D+1)\rceil=3 \end{aligned}

सीमा पर अनुरोध और स्वीकृति अलग करें

push और pop अनुरोध हैं। p और q क्रमशः वास्तविक push और pop स्वीकृति हों, तो reset न होने वाले एज से ठीक पहले की अवस्था से:

q=pop∧(C>0)p=push∧((C<4)∨q)C+=C+p−q\begin{aligned} q&=\mathrm{pop}\land(C>0)\\ p&=\mathrm{push}\land((C<4)\lor q)\\ C^{+}&=C+p-q \end{aligned}

Empty में दोनों अनुरोध आने पर भी निकालने को पुराना डेटा नहीं है, इसलिए केवल push स्वीकार होता है। नया डेटा उसी एज पर तुरंत आउटपुट नहीं बनता। Full में दोनों अनुरोध आएँ तो पुराना सिरा निकालकर स्थान खाली कर सकते हैं, इसलिए दोनों स्वीकार होते हैं। full का अर्थ “अभी चार मदें संग्रहीत हैं” है; इस नीति में यह push पर बिना शर्त रोक नहीं है।

एज से पहले की अवस्थाकेवल pushकेवल poppush और pop
C=0एक मद रखेंअस्वीकृतकेवल push स्वीकार, C=1
0<C<4C+1C−1दोनों स्वीकार, C वही
C=4अस्वीकृतC=3दोनों स्वीकार, C=4

क्लॉक बढ़ाकर सीमा स्थितियाँ जाँचें

पहले push और pop साथ माँगें। कतार खाली है, इसलिए केवल push स्वीकार होना चाहिए। फिर pop बंद करके चारों स्थान भरें। नए इनपुट मान के साथ दोनों अनुरोध फिर सक्रिय करें। Occupancy 4 बनी रहे, आउटपुट में पुराना सिरा और भंडारण में नई अंतिम मद होनी चाहिए।

FIFO को एक-एक क्लॉक आगे बढ़ाएँ

चार-स्थान FIFO। शुरुआत में खाली; पढ़ने और लिखने के पॉइंटर 0 हैं। खाली न होने पर pop स्वीकारती है। जगह उपलब्ध हो या उसी एज पर pop स्वीकारा जाए तो push स्वीकारती है।

चित्र हर उर्ध्वगामी एजउदयी किनारा (rising edge) क्लॉक के 0 से 1 होने का क्षण। यह CLK=1 के पूरे स्तर-अंतराल से अलग है। और जानें के ठीक बाद की अवस्था दिखाने वाला शैक्षिक मॉडल है। Pop स्वीकार होने पर output valid=1 होता है। अगले एज पर pop स्वीकार न हो तो आउटपुट रजिस्टररजिस्टर कई बिटों की अवस्था संग्रहित करता है। इस पाठ्यक्रम के तुल्यकालिक रजिस्टर निर्धारित इनपुट को क्लॉक एज पर संग्रहित करते हैं। और जानें का मान बना रहता है, लेकिन valid=0 हो जाता है। खाली स्थानों के पुराने बिट छिपाए जाते हैं। “फिर से शुरू करें” पूरे अभ्यास को आरंभ करता है; यह RTL मेमोरी का resetरीसेट अवस्था को विनिर्दिष्ट प्रारंभिक मान पर लौटाने वाला नियंत्रण। उसका तुल्यकालिक या अतुल्यकालिक होना और अन्य नियंत्रणों पर प्राथमिकता साथ तय करें। और जानें व्यवहार नहीं दर्शाता।

रजिस्टर्ड आउटपुट सहित RTL

SystemVerilog
module fifo4 (
  input  logic       clk, rst, push, pop,
  input  logic [7:0] din,
  output logic [7:0] dout,
  output logic       dout_valid, full, empty,
  output logic [2:0] occupancy
);
  timeunit 1ns;
  timeprecision 1ps;
  logic [7:0] mem [0:3];
  logic [1:0] rptr, wptr;
  logic take_push, take_pop;

  assign empty = (occupancy == 3'd0);
  assign full  = (occupancy == 3'd4);
  assign take_pop  = !rst && pop && !empty;
  assign take_push = !rst && push && (!full || take_pop);

  always_ff @(posedge clk) begin
    if (rst) begin
      rptr <= 2'd0;
      wptr <= 2'd0;
      occupancy <= 3'd0;
      dout_valid <= 1'b0;
    end else begin
      dout_valid <= take_pop;
      if (take_push) begin
        mem[wptr] <= din;
        wptr <= wptr + 2'd1;
      end
      if (take_pop) begin
        dout <= mem[rptr];
        rptr <= rptr + 2'd1;
      end
      case ({take_push, take_pop})
        2'b10: occupancy <= occupancy + 3'd1;
        2'b01: occupancy <= occupancy - 3'd1;
        default: occupancy <= occupancy;
      endcase
    end
  end
endmodule

occupancy को बढ़ाने और घटाने के लिए दो स्वतंत्र if से असाइन नहीं किया गया। एक साथ स्वीकृति होने पर एक ही रजिस्टर पर दो nonblockingnonblocking अनुक्रमिक RTL में <= द्वारा असाइनमेंट। दाईं ओर का मूल्यांकन कर अद्यतन निर्धारित करता है, जिससे उसी एज के रजिस्टर पुरानी अवस्था के आधार पर गणना करते हैं। और जानें असाइनमेंट में केवल अंतिम लागू होती है। दोनों पॉइंटर अपनी-अपनी स्वीकृति पर बढ़ते हैं, जबकि संख्या चारों मामलों से एक बार तय होती है। स्वीकृति की शर्तें 0 से घटने और 4 से बढ़ने को भी रोकती हैं।

Full में एक ही पता पढ़ना और लिखना

A,B,C,D क्रम से डालने पर rptr=wptr=0 और occupancy=4 है। अब pop=push=1,din=E हो तो एज के बाद dout=A,dout_valid=1 और तार्किक कतार [B,C,D,E] है। दोनों पॉइंटर 1 होते हैं, संख्या 4 रहती है। mem[0] E हो जाता है, लेकिन dout की nonblocking असाइनमेंट का दायाँ पक्ष पुराना A पढ़ता है। Full पर बदलने की नीति के लिए यह read-first टकराव व्यवहार आवश्यक है।

इसके बाद push=0,pop=1 हो तो B निकलता है और संख्या 3 होती है। इसके विपरीत, empty में din=Z के साथ दोनों अनुरोध देने पर केवल संख्या 1 होती है और dout_valid=0 रहता है। Z निकालने के लिए अगले एज पर pop माँगना होगा। Empty में तुरंत आगे भेजना और full में बदलना अलग डिजाइन विकल्प हैं।

rst active-high तुल्यकालिक reset है, जो पॉइंटर, संख्या और dout_valid आरंभ करता है। यह मेमोरी या dout नहीं मिटाता। Reset के बाद पुराने बिट बचे हों तो भी empty pop रोकता है और बाद में केवल नए push द्वारा लिखे स्थान पढ़े जाते हैं। इसलिए सामान्य संचालन के लिए पूरी सरणी reset करना आवश्यक नहीं है। dout_valid=0 वाला मान उपयोग न करें। valid=1 वाला आउटपुट स्वीकार किए pop का उत्तर है; आउटपुट पर अलग ready नहीं है, इसलिए उपभोक्ता को वह उत्तर लेना चाहिए।

DEPTH, 2 की घात न हो तो वही सरल 2-बिट overflow दोबारा उपयोग नहीं कर सकते। उदाहरण के लिए, गहराई 3 में पता 2 के बाद स्पष्ट रूप से 0 लौटना चाहिए। यदि संश्लेषण में RAM मिले तो जाँचें कि उसी पते पर वह old-data व्यवहार समर्थित करता है। यह कोड एक क्लॉक के लिए है; अलग क्लॉक वाले FIFO के पॉइंटर समन्वय पर सीधे लागू नहीं होता।

खुद आज़माएँ

Reset के ठीक बाद हर एज पर ये अनुरोध दें: (1) push A और pop साथ, (2) केवल push B, (3) केवल push C, (4) केवल push D, (5) push E और pop साथ, (6) केवल pop। हर चरण के बाद कतार, occupancy,dout_valid और मान्य आउटपुट लिखें। पाँचवें चरण में read-first क्यों आवश्यक है?

व्याख्या पढ़ें

(1) [A],1,valid=0। (2) [A,B],2,valid=0। (3) [A,B,C],3,valid=0। (4) [A,B,C,D],4,valid=0। (5) [B,C,D,E],4,valid=1,dout=A। (6) [C,D,E],3,valid=1,dout=B। पहले चरण में पुरानी मद नहीं है, इसलिए pop अस्वीकार होता है। पाँचवें चरण में rptr=wptr=0 है और एक ही स्थान पर पढ़ना-लिखना होता है, इसलिए पुराना सिरा A पढ़ना चाहिए। Write-first से E लौटाने पर FIFO का क्रम और सामग्री गलत हो जाएँगे। valid=0 वाले आउटपुट मान का मूल्यांकन नहीं किया जाता।

आपका चयन इस ब्राउज़र पर लागू होता है। फ़ुटर से कभी भी बदलें।