ভিএইচডিএল: বিট গণনা করার সময় মডিউলটি এলোমেলোভাবে ব্যর্থ হয়


9

পটভূমি

এটি একটি ব্যক্তিগত প্রকল্প; এটি কোনও এনপি 64 এর সাথে একটি এফপিজিএ সংযোগ সম্পর্কিত, এফপিজিএ প্রাপ্ত বাইট মানগুলি আমার কম্পিউটারে ইউআরটির মাধ্যমে প্রেরণ করা হয়। এটি আসলে বেশ ভাল কাজ করে! দুর্ভাগ্যক্রমে এলোমেলো সময়ে, ডিভাইস ব্যর্থ হবে, তারপরে পুনরুদ্ধার করুন। ডিবাগিংয়ের মাধ্যমে, আমি সমস্যাটি সন্ধান করতে পেরেছি, তবে কীভাবে এটি ঠিক করতে হবে তা নিয়ে আমি স্তব্ধ হয়ে পড়েছি কারণ আমি ভিএইচডিএলের সাথে মোটামুটি অক্ষম।

আমি এখন কয়েকদিন ধরে ভিএইচডিএলের সাথে কথা বলছি এবং আমি এটি সমাধান করতে অক্ষম হতে পারি।

সমস্যাটি

আমার কাছে একটি এসিসিলোস্কোপ রয়েছে যাতে এফপিজিএ-তে N64 সংকেত পরিমাপ করা হয় এবং অন্য চ্যানেলটি এফপিজিএর আউটপুটটির সাথে সংযোগ স্থাপন করে। আমারও পাল্টা মান রেকর্ডিং ডিজিটাল পিন রয়েছে।

মূলত, N64 স্টপ বিট সহ 9 ডেটা বিট প্রেরণ করে। কাউন্টারটি প্রাপ্ত ডেটার বিটগুলি গণনা করে এবং যখন আমি 9 বিটে পৌঁছায়, এফপিজিএটি ইউআআআআরটির মাধ্যমে সংক্রমণ শুরু করে।

এখানে সঠিক আচরণ: এখানে চিত্র বর্ণনা লিখুন

এফপিজিএ হল নীল তরঙ্গরূপ এবং কমলা তরঙ্গরূপটি N64 এর ইনপুট। প্রাপ্তির সময়কালের জন্য, আমার এফপিজিএ ডিবাগিংয়ের উদ্দেশ্যে ইনপুটটির সংকেত "প্রতিধ্বনি" দেয়। এফপিজিএ 9 তে গণনা করার পরে, এটি ইউআআআআরটির মাধ্যমে ডেটা প্রেরণ শুরু করে। লক্ষ্য করুন যে ডিজিটাল পিনগুলি গণনা 9 এবং এফপিজিএ আউটপুট N64 শেষ হওয়ার সাথে সাথেই কম যায়।

এখানে একটি ব্যর্থতার উদাহরণ:

এখানে চিত্র বর্ণনা লিখুন

লক্ষ্য করুন যে কাউন্টারটি 2 এবং 7 টি বিট করে! এফপিজিএ শেষ দিকে পৌঁছে, N64 থেকে পরবর্তী শুরু বিটের জন্য অপেক্ষা করছে তবে কিছুই নেই। সুতরাং এফপিজিএ সময় শেষ এবং পুনরুদ্ধার।

এটি N64 প্রাপ্ত মডিউলটির জন্য ভিএইচডিএল। এতে কাউন্টার রয়েছে: এস_বিটকাউন্ট।

library IEEE;
use IEEE.STD_LOGIC_1164.all;   
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity N64RX is
     port(
         N64RXD : in STD_LOGIC;                    --Data input
         clk25 : in STD_LOGIC;
         clr : in STD_LOGIC; 
         tdre : in STD_LOGIC;                      --detects when UART is ready
         transmit : out STD_LOGIC;                 --Signal to UART to transmit  
         sel : out STD_LOGIC; 
         echoSig : out STD_LOGIC;
         bitcount : out STD_LOGIC_VECTOR(3 downto 0);
         data : out STD_LOGIC_VECTOR(3 downto 0)   --The significant nibble
         );
end N64RX;

--}} End of automatically maintained section

architecture N64RX of N64RX is 

type state_type is (start, delay2us, sigSample, waitForStop, waitForStart, timeout, count9bits, sendToUART);

signal state: state_type;
signal s_sel, s_echoSig, s_timeoutDetect : STD_LOGIC;
signal s_baudCount : STD_LOGIC_VECTOR(6 downto 0);  --Counting variable for baud rate in delay
signal s_bitCount : STD_LOGIC_VECTOR(3 downto 0);  --Counting variable for number of bits recieved 
signal s_data : STD_LOGIC_VECTOR(8 downto 0);   --Signal for data

constant delay : STD_LOGIC_VECTOR(6 downto 0) := "0110010";  --Provided 25MHz, 50 cycles is 2us 
constant delayLong : STD_LOGIC_VECTOR(6 downto 0) := "1100100";

begin 

n64RX: process(clk25, N64RXD, clr, tdre)
begin
    if clr = '1' then
        s_timeoutDetect <= '0';
        s_echoSig <= '1';
        s_sel <= '0';
        state <= start;
        s_data <= "000000000";
        transmit <= '0'; 
        s_bitCount <= "0000";
        s_baudCount <= "0000000";  
    elsif (clk25'event and clk25 = '1') then    --on rising edge of clock input
        case state is
            when start =>   
                --s_timeoutDetect <= '0';
                s_sel <= '0';
                transmit <= '0';        --Don't request UART to transfer   
                s_data <= "000000000";
                s_bitCount <= X"0";   
                if N64RXD = '1' then
                    state <= start;
                elsif N64RXD = '0' then     --if Start bit detected
                    state <= delay2us;
                end if;    

            when delay2us =>                 --wait two microseconds to sample
                --s_timeoutDetect <= '0';
                s_sel <= '1';
                s_echoSig <= '0';
                if s_baudCount >= delay then    
                    state <= sigSample;
                else
                    s_baudCount <= s_baudCount + 1;
                    state <= delay2us;
                end if;  

            when sigSample => 
                --s_timeoutDetect <= '1';
                s_echoSig <= N64RXD;
                s_bitCount <= s_bitCount + 1;
                s_baudcount <= "0000000";
                s_data <= s_data(7 downto 0) & N64RXD;      
                state <= waitForStop;   

            when waitForStop => 
                s_echoSig <= N64RXD;
                if N64RXD = '0' then
                    state <= waitForStop;
                elsif N64RXD = '1' then
                    state <= waitForStart;
                end if;   

            when waitForStart => 
                s_echoSig <= '1';
                s_baudCount <= s_baudCount + 1; 
                if N64RXD = '0' then 
                    s_baudCount <= "0000000";
                    state <= delay2us;
                elsif N64RXD = '1' then 
                    if s_baudCount >= delayLong then
                        state <= timeout;
                    elsif s_bitCount >= X"9" then
                        state <= count9bits;
                    else
                        state <= waitForStart;
                    end if;
                end if;     

            when count9bits =>  
                s_sel <= '0';
                if tdre = '0' then
                    state <= count9bits;
                elsif tdre = '1' then
                    state <= sendToUART;
                end if;   

            when sendToUART =>
                transmit <= '1';
                if tdre = '0' then
                    state <= start;
                else
                    state <= sendToUART;
                end if;

            when timeout =>
                --s_timeoutDetect <= '1';
                state <= start;

        end case;   
    end if;
end process n64RX;  
--timeoutDetect <= s_timeoutDetect;
bitcount <= s_bitCount;
echoSig <= s_echoSig;
sel <= s_sel;
data <= s_data(4 downto 1);

end N64RX;

সুতরাং, কোন ধারণা? ডিবাগিং টিপস? সসীম স্টেট মেশিনগুলি কোডিংয়ের টিপস?

এরই মধ্যে, আমি এটি নিয়ে ঘুরে বেড়াতে যাব (অবশেষে আমার তা হবে)! আমাকে স্ট্যাক এক্সচেঞ্জ সাহায্য করুন, আপনি আমার একমাত্র আশা!

সম্পাদন করা

আমার ডিবাগিংয়ের আরও একটি আবিষ্কার, রাজ্যগুলি ওয়েটারফর্ট থেকে লাফিয়ে লাফিয়ে স্টোরটিতে ফিরে যাবে। আমি প্রতিটি রাজ্যকে অপেক্ষা ফোরস্টার্ট সমান '5' এবং 'অপেক্ষা' স্টোর সমান '4' দিয়ে একটি মান দিয়েছি। নীচের চিত্রটি দেখুন: এখানে চিত্র বর্ণনা লিখুন


1
আপনার প্রথম কেস ব্লকে, "s_bitCount <= এক্স" 0 "লাইনটি রয়েছে;" এটা কি এক্স টাইপো?
ট্র্যাভিসবার্টলি

@ ট্র্যাভ 1 এস না, "এক্স" হেক্সাডেসিমালকে বোঝায়। সুতরাং এক্স "0" আসলে বাইনারিতে "0000"।
নিক উইলিয়ামস

1
একটি ল্যাটারের মাধ্যমে কোডটি চালাতে আমি বেশ কয়েকটি ত্রুটি পেয়েছি। সিগন্যাল N64RXD এবং tdre অনুক্রমিক প্রক্রিয়া সংবেদনশীলতা তালিকায় ব্যবহার করা উচিত নয়, লাইন 36.
ট্র্যাভিসবার্টলি

1
@ trav1s পয়েন্টারের জন্য ধন্যবাদ, আমি সেই পরামিতিগুলি সরিয়েছি; তুমি ঠিক বলেছ, এগুলি দরকার নেই দুর্ভাগ্যক্রমে আমার এখনও সমস্যাটি আছে। সুযোগ নিয়ে, আমি কোন রাজ্যে আছি তা সনাক্ত করার জন্য আমি সংকেতগুলি যুক্ত করেছি some কিছু কারণে, এফপিজিএ "ওয়েটফোর্ড স্টার্ট" থেকে কোনও রাজ্য ছাড়াই ফিরে "ওয়েটফর্সটপ" তে ঝাঁপিয়ে পড়ে! এ কারণেই এটি গণনা হচ্ছে না কারণ এফপিজিএ যেখানে রাজ্যটিকে বিট হিসাবে গণনা করে সেখানে পৌঁছায় না। "জাম্প ব্যাক" বিষয়টি মনে হচ্ছে।
নিক উইলিয়ামস

1
তবে "অপেক্ষাফর্ট স্টার্ট" -> "অপেক্ষাফর্টসপ" ট্রানজিশনটি অবৈধ। একক চক্রে এই লাফানোর কোনও উপায় নেই। এর মধ্যে খুব সংক্ষিপ্ত অবস্থা না রয়েছে তা নিশ্চিত করতে খুব ঘনিষ্ঠভাবে পরীক্ষা করুন। অন্যথায়, একটি হার্ডওয়্যার / সময়সংশ্লিষ্ট ত্রুটি থাকতে হবে।
ট্র্যাভিসবার্টলি

উত্তর:


9

আমি আরএক্স ডেটা লাইনে একটি সিঙ্ক্রোনাইজারটি দেখতে পাচ্ছি না।

সমস্ত অ্যাসিনক্রোনাস ইনপুটগুলি স্যাম্পলিং ঘড়ির সাথে সিঙ্ক্রোনাইজ করতে হবে। এর বেশ কয়েকটি কারণ রয়েছে: মেটাস্টেবিলিটি এবং রাউটিং। এগুলি বিভিন্ন সমস্যা তবে আন্তঃসম্পর্কিত।

এফপিজিএ ফ্যাব্রিকের মাধ্যমে সংকেত প্রচার করতে সময় লাগে। এফপিজিএর অভ্যন্তরীণ ক্লক নেটওয়ার্কটি এই "ভ্রমণ" বিলম্বের জন্য ক্ষতিপূরণ দেওয়ার জন্য ডিজাইন করা হয়েছে যাতে FPGA এর মধ্যে থাকা সমস্ত ফ্লিপ ফ্লপটি একই মুহূর্তে ঘড়িটি দেখতে পায়। সাধারণ রাউটিং নেটওয়ার্কটিতে এটি নেই এবং পরিবর্তে এই নিয়মটির উপর নির্ভর করে যে সমস্ত সংকেত অবশ্যই কিছু সময়ের জন্য ঘড়ির পরিবর্তনের আগে স্থিতিশীল থাকতে হবে এবং ঘড়ির পরিবর্তনের পরে কিছুটা সময় স্থিতিশীল থাকতে হবে। এই সামান্য বিটস সেটআপ হিসাবে পরিচিত এবং প্রদত্ত ফ্লিপ ফ্লপের সময় ধরে রাখে। সরঞ্জামচেইনের স্থান এবং রুটের উপাদানটি নির্দিষ্ট ডিভাইসের জন্য রাউটিং বিলম্ব সম্পর্কে খুব ভাল বোঝা পেয়েছে এবং একটি প্রাথমিক ধারণাটি তৈরি করে যে কোনও সিগন্যাল সেটআপ লঙ্ঘন করে না এবং এফপিজিএতে ফ্লিপ ফ্লপের সময় ধরে না।

যখন আপনার সিগন্যালগুলি স্যাম্পলিং ঘড়ির সাথে সিঙ্ক্রোনাইজ করা হয়নি তখন আপনি এমন পরিস্থিতিতে শেষ করতে পারেন যেখানে কোনও ফ্লিপ ফ্লপ সিগন্যালের "পুরানো" মানটি দেখায় যেহেতু নতুন মানটি প্রচার করার সময় হয়নি। এখন আপনি অবাঞ্ছিত পরিস্থিতিতে রয়েছেন যেখানে একই সংকেতের দিকে যুক্তি দেখানো দুটি পৃথক মান দেখে। এটি ভুল ক্রিয়াকলাপ, ক্র্যাশড স্টেট মেশিন এবং সমস্ত ধরণের কঠোর রোগ নির্ণয় করতে পারে।

আপনার সমস্ত ইনপুট সিগন্যালগুলি আপনাকে কেন সিঙ্ক্রোনাইজ করতে হবে তার অন্য কারণটি হ'ল মেটাস্টেবিলিটি। এই বিষয়ে খণ্ডগুলি লেখা আছে তবে সংক্ষেপে ডিজিটাল লজিক সার্কিটরিটি এটির প্রাথমিক স্তরে একটি এনালগ সার্কিট। যখন আপনার ঘড়ির লাইনটি বৃদ্ধি পায় ইনপুট লাইনের স্থিতিটি ক্যাপচার হয়ে যায় এবং সেই ইনপুট যদি সেই সময়ে স্থিতিশীল উচ্চ বা নিম্ন স্তরের না হয়, তবে একটি অজানা "ইন-বিউন্ড" মান স্যাম্পলিং ফ্লিপ ফ্লপ দ্বারা ক্যাপচার করা যেতে পারে।

আপনি জানেন যে, এফপিজিএগুলি হ'ল ডিজিটাল জন্তু এবং এটি এমন সিগন্যালের সাথে ভাল প্রতিক্রিয়া জানায় না যা উচ্চ বা কম নয়। সবচেয়ে খারাপ বিষয়, যদি সেই অনির্দিষ্ট মানটি স্যাম্পলিং ফ্লিপ ফ্লপের অতীত হয়ে যায় এবং এফপিজিএতে চলে যায় এটি যুক্তির বড় অংশগুলি এখন একটি অনির্দিষ্ট মান দেখতে পায় এবং এটি বোঝার চেষ্টা করার কারণে এটি সমস্ত ধরণের অদ্ভুততার কারণ হতে পারে।

সমাধানটি সিগন্যাল সিঙ্ক্রোনাইজ করা। একেবারে বেসিক স্তরে এর অর্থ আপনি ইনপুট ক্যাপচার করতে ফ্ল্যাপ ফ্লপের একটি চেইন ব্যবহার করেন। যে কোনও মেটাস্টেবল লেভেল যা সম্ভবত প্রথম ফ্লিপ ফ্লপ দ্বারা ক্যাপচার করা হয়েছে এবং এটির ব্যবস্থাপন করতে সক্ষম হয়েছে তা আপনার জটিল যুক্তিকে হিট করার আগে সমাধানের আর একটি সুযোগ পেয়ে যায়। দুটি ফ্লিপ ফ্লপ সাধারণত ইনপুট সিঙ্ক্রোনাইজ করার জন্য পর্যাপ্ত পরিমাণের চেয়ে বেশি।

একটি বেসিক সিঙ্ক্রোনাইজার এর মতো দেখাচ্ছে:

entity sync_2ff is
port (
    async_in : in std_logic;
    clk : in std_logic;
    rst : in std_logic;
    sync_out : out std_logic
);
end;

architecture a of sync_2ff is
begin

signal ff1, ff2: std_logic;

-- It's nice to let the synthesizer know what you're doing. Altera's way of doing it as follows:
ATTRIBUTE altera_attribute : string;
ATTRIBUTE altera_attribute OF ff1 : signal is "-name SYNCHRONIZER_IDENTIFICATION ""FORCED IF ASYNCHRONOUS""";
ATTRIBUTE altera_attribute OF a : architecture is "-name SDC_STATEMENT ""set_false_path -to *|sync_2ff:*|ff1 """;

-- also set the 'preserve' attribute to ff1 and ff2 so the synthesis tool doesn't optimize them away
ATTRIBUTE preserve: boolean;
ATTRIBUTE preserve OF ff1: signal IS true;
ATTRIBUTE preserve OF ff2: signal IS true;

synchronizer: process(clk, rst)
begin
if rst = '1' then
    ff1 <= '0';
    ff2 <= '0';
else if rising_edge(clk) then
    ff1 <= async_in;
    ff2 <= ff1;
    sync_out <= ff2;
end if;
end process synchronizer;
end sync_2ff;

সিঙ্ক্রোনাইজারের async_in ইনপুটটিতে N64 নিয়ন্ত্রকের আরএক্স ডেটা লাইনের জন্য ফিজিকাল পিনটি সংযুক্ত করুন এবং আপনার ইউআরটির আরএক্সডি ইনপুটটিতে সিঙ্ক_আউট সংকেতটি সংযুক্ত করুন।

আনসক্রোনাইজড সংকেতগুলি অদ্ভুত সমস্যা সৃষ্টি করতে পারে । নিশ্চিত করুন যে কোনও এফপিজিএ উপাদানটির সাথে সংযুক্ত কোনও ইনপুট যা সংকেত পড়ার প্রক্রিয়ার ঘড়ির সাথে সিঙ্ক্রোনাইজ করা হয়নি। এর মধ্যে পুশব্যাটন, ইউআরটি 'আরএক্স' এবং 'সিটিএস' সিগন্যাল অন্তর্ভুক্ত রয়েছে ... যে কোনও কিছু যা এফপিজিএ সিগন্যালের নমুনা ব্যবহার করার জন্য ঘড়ির সাথে সুসংগত হয় না।

(একপাশে: আমি পৃষ্ঠাটি বেশ কয়েক বছর আগে www.mixdown.ca/n64devলিখেছি just আমি ঠিক বুঝতে পেরেছিলাম যে সাইটটি শেষবার আপডেট করার সময় আমি এই লিঙ্কটি ভেঙে দিয়েছিলাম এবং সকালে যখন আমি একটি কম্পিউটারে ফিরে আসি তখন এটি ঠিক করব। আমার কোনও ধারণা ছিল না যে এত লোকেরা পৃষ্ঠাটি ব্যবহার করেছিল!)


দুর্দান্ত এবং ব্যাপক উত্তরের জন্য ধন্যবাদ! আমি এটি চেষ্টা করে যাচ্ছি এবং আমার মেশিনটিকে আরও শক্তিশালী করে তুলছি।
নিক উইলিয়ামস

2
এটি মেটাস্টাবিলিটির সাথে আসলে খুব সামান্যই (যদিও এটি একটি উদ্বেগও), এবং অ্যাসিনক্রোনাস ইনপুট থেকে বিভিন্ন এফএফগুলিতে পৃথক পাথের বিলম্বের সাথে সমস্ত কিছু যা রাষ্ট্রের পরিবর্তনশীলগুলির বিটগুলিকে ধরে রাখে।
ডেভ টুইট করেছেন

আপনি ঠিক বলেছেন, @ ডেভিটওয়েড; আমি দু'জনকে একসাথে পিছু পিছু নিয়ে যাওয়ার চেষ্টা করি এবং এটি ভুল-মাথাচিন্তা।
akohlsmith

আমি @ ডেভিটউইডের মন্তব্যগুলিকে অ্যাকাউন্টে নেওয়ার জন্য আমার উত্তরটি সম্পাদনা করেছি।
অ্যাকোহলস্মিথ

1
@akohlsmith আশ্চর্যজনক! আমি সিঙ্ক্রোনাইজার যুক্ত করেছি এবং এটিই ছিল সমাধান। এছাড়াও, এটি একটি অবিশ্বাস্য কাকতালীয় ঘটনা যা আপনি মিক্সডাউন পৃষ্ঠাটি লিখেছিলেন; আমি N64 প্রোটোকলে এমন একাধিক সংস্থান খুঁজে পেয়েছি যা সেই নিবন্ধটি রেফারেন্স করেছে এবং আমি হতাশ হয়েছি লিঙ্কটি ভেঙে গেছে। এটি ঠিক করার জন্য ধন্যবাদ।
নিক উইলিয়ামস

6

আপনার সমস্যাটি হ'ল আপনি নিজের রাজ্য মেশিনে সিদ্ধান্ত নিতে আনইনক্রোনাইজড সংকেত ব্যবহার করছেন। স্টেট মেশিনে ডাবল-এফএফ সিঙ্ক্রোনাইজারগুলির মাধ্যমে আপনার সমস্ত বাহ্যিক সংকেতকে খাওয়ানো উচিত।

রাষ্ট্রীয় মেশিনগুলির সাথে এটি একটি সূক্ষ্ম সমস্যা যা কোনও রাজ্যের উত্তরণে উত্থিত হতে পারে যা রাষ্ট্রের পরিবর্তনশীলে দুটি বা ততোধিক বিট পরিবর্তন করতে পারে। আপনি যদি একটি সিঙ্ক-ইনক্রোনাইজড ইনপুট ব্যবহার করেন, বিটগুলির মধ্যে একটিতে অন্যটি পরিবর্তন করতে ব্যর্থ হতে পারে। এটি আপনাকে উদ্দেশ্যপ্রাপ্ত একের থেকে আলাদা অবস্থায় নিয়ে যায় এবং এটি আইনী রাষ্ট্র হতেও পারে এবং নাও পারে।

এই শেষ বিবৃতিটি হ'ল কেন when others => ...আপনার রাজ্য মেশিন কেস স্টেটমেন্টে আপনার সর্বদা একটি ডিফল্ট কেস (ভিএইচডিএল ) থাকা উচিত যা আপনাকে কোনও অবৈধ অবস্থা থেকে আইনী হিসাবে নিয়ে যায়।


হ্যাঁ, এই উপসংহারটি আমি আলাদা করতে যাচ্ছিলাম, তবে পর্যাপ্ত তথ্য পাওয়ার আগে আমি এটিতে লাফিয়ে
উঠতে চাইনি

1
অভিশাপ, আপনি আমাকে এটি মারধর। আমি এটি ট্যাবলেটে আমার সমস্ত টাইপ করার জন্য দোষ দিই। :-)
অ্যাকোহলস্মিথ

@ কোহলস্মিথ, পূর্বের দ্রুততম বন্দুক হওয়া কেবল উত্তর দেওয়ার ক্ষেত্রে গুরুত্বপূর্ণ নয়। আপনার উত্তরটি দরকারী, এবং সম্ভবত আপনি এর জবাবদিহি করার পরে প্রতারণা করেননি।
ট্র্যাভিসবার্টলি

আমি ভাবছিলাম যে when others =>এটি সহায়তা করছে, তবে এটি প্রমাণিত হয়েছে যে আপনি কী দাবি করেছেন (যা আমি ব্যবহার করেছি কোনও সিন্থেসাইজারের অধীনে) যদি আপনি কোনও বৈশিষ্ট্য যুক্ত না করেন তবে সিন্থ বুঝতে পারে যে আপনি কোনও "নিরাপদ" রাষ্ট্রীয় মেশিন চান synt স্বাভাবিক আচরণটি হ'ল এক-উষ্ণ উপস্থাপনের জন্য অনুকূলিত করা এবং পুনরুদ্ধারের যুক্তি সরবরাহ না করা। উদাহরণস্বরূপ xilinx.com/support/answers/40093.html এবং synopsys.com/Company/Publications/SynopsysInsight/Pages/… দেখুন ।
মার্টিন থম্পসন

কি দারুন! এটি দুর্দান্ত টিপ এবং এটি একটি কবজির মতো কাজ করেছে।
নিক উইলিয়ামস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.