FPGA चक्रवात IV के लिए सांप का खेल (VGA और SPI जॉयस्टिक के साथ)

परिचय


क्या आपको बचपन से सांप का खेल याद है, जहां एक सांप स्क्रीन पर एक सेब खाने की कोशिश करता है? यह लेख एक FPGA 1 पर खेल के हमारे कार्यान्वयन का वर्णन करता है।


Gameplay.gif
चित्र 1. गेमप्ले


सबसे पहले, हम अपना परिचय दें और औचित्य की व्याख्या करें कि हमने परियोजना पर काम क्यों किया है। हम में से 3 हैं: तैमूर लिसेंको , डेनियल मैनाकोवस्की और सर्गेई मकरोवइन्नोपोलिस विश्वविद्यालय के प्रथम वर्ष के छात्रों के रूप में, हमारे पास "कंप्यूटर आर्किटेक्चर" में एक कोर्स था, जो पेशेवर रूप से पढ़ाया जाता है और सीखने वाले को कंप्यूटर के निम्न-स्तरीय ढांचे को समझने में सक्षम बनाता है। पाठ्यक्रम के दौरान कुछ बिंदु पर, प्रशिक्षकों ने हमें पाठ्यक्रम में अतिरिक्त बिंदुओं के लिए एक एफपीजीए के लिए एक परियोजना विकसित करने का अवसर प्रदान किया। हमारी प्रेरणा केवल ग्रेड नहीं रही है, बल्कि हार्डवेयर डिज़ाइन में अधिक अनुभव प्राप्त करने, परिणामों को साझा करने और आखिरकार, एक सुखद खेल होने के लिए हमारी रुचि है।


अब, हम गहरे गहरे विवरण में जाते हैं।


परियोजना का अवलोकन


हमारी परियोजना के लिए, हमने "स्नेक" अर्थात् एक आसानी से कार्यान्वित और मजेदार गेम का चयन किया। कार्यान्वयन की संरचना निम्नानुसार है: सबसे पहले, एक इनपुट एक एसपीआई जॉयस्टिक से लिया जाता है, फिर संसाधित किया जाता है, और अंत में, एक तस्वीर वीजीए मॉनिटर के लिए आउटपुट होती है और एक स्कोर 7-खंड प्रदर्शन (हेक्स में) पर दिखाया जाता है। यद्यपि खेल तर्क सहज और सरल है, वीजीए और जॉयस्टिक दिलचस्प चुनौतियां हैं और उनके कार्यान्वयन से एक अच्छा गेमिंग अनुभव प्राप्त हुआ है।


खेल के निम्नलिखित नियम हैं। एक खिलाड़ी एकल साँप के सिर से शुरू होता है। लक्ष्य सेब खाने के लिए है, जो पिछले एक खाने के बाद स्क्रीन पर बेतरतीब ढंग से उत्पन्न होते हैं। इसके अलावा, भूख को संतुष्ट करने के बाद सांप को 1 पूंछ से बढ़ाया जा रहा है। सिर के पीछे पूंछ एक के बाद एक चलती है। सांप हमेशा हिलता रहता है। यदि स्क्रीन की सीमाएँ पहुँच जाती हैं, तो साँप को स्क्रीन के दूसरी तरफ स्थानांतरित किया जा रहा है। यदि सिर पूंछ से टकराता है, तो खेल खत्म हो गया है।


उपकरण का इस्तेमाल किया


  • Altera Cyclone IV (EP4CE6E22C8N) 6272 तार्किक तत्वों के साथ, 50 MHz घड़ी, 3-बिट रंग VGA, 8 अंक 7-खंड प्रदर्शन के साथ। FPGA अपने पिंस में एनालॉग इनपुट नहीं ले सकता है।
  • SPI जॉयस्टिक (KY-023)
  • एक वीजीए मॉनिटर जो 60 हर्ट्ज ताज़ा दर का समर्थन करता है
  • क्वार्टस प्राइम लाइट संस्करण 18.0.0 614 बनाएँ
  • वेरिलोग एचडीएल IEEE 1364-2001
  • breadboard
  • विद्युत तत्व:
    • 8 पुरुष-महिला कनेक्टर
    • 1 महिला-महिला कनेक्टर
    • 1 पुरुष-पुरुष संबंधक
    • 4 प्रतिरोध (4.7 KΩ)

वास्तुकला अवलोकन


परियोजना की वास्तुकला पर विचार करने के लिए एक महत्वपूर्ण कारक है। चित्र 2 शीर्ष स्तर के दृष्टिकोण से इस वास्तुकला को दर्शाता है:


Design.png
चित्रा 2. डिजाइन का शीर्ष-स्तरीय दृश्य ( पीडीएफ )


जैसा कि आप देख सकते हैं, कई इनपुट, आउटपुट और कुछ मॉड्यूल हैं। यह खंड वर्णन करेगा कि प्रत्येक तत्व का क्या अर्थ है और निर्दिष्ट करें कि पोर्ट के लिए कौन से पिन बोर्ड पर उपयोग किए जाते हैं।


मुख्य इनपुट्स


कार्यान्वयन के लिए आवश्यक मुख्य इनपुट res_x_one , res_x_two , res_y_one , res_y_two हैं , जिनका उपयोग जॉयस्टिक की वर्तमान दिशा प्राप्त करने के लिए किया जाता है। चित्र 3 उनके मूल्यों और दिशाओं के बीच मानचित्रण दिखाता है।


इनपुटवामसहीऊपरनीचेदिशा में कोई बदलाव नहीं
res_x_one (PIN_30)10एक्सएक्स1
res_x_two (PIN_52)10एक्सएक्स0
res_y_one (PIN_39)एक्सएक्स101
res_y_two (PIN_44)एक्सएक्स100

चित्रा 3. जॉयस्टिक इनपुट और दिशाओं का मानचित्रण


अन्य जानकारी


  • clk - बोर्ड घड़ी (PIN_23)
  • रीसेट - गेम को रीसेट करने और प्रिंटिंग बंद करने का संकेत (PIN_58)
  • रंग - जब 1, सभी संभावित रंग स्क्रीन पर आउटपुट होते हैं और केवल प्रदर्शन उद्देश्यों के लिए उपयोग किए जाते हैं (PIN_68)

मुख्य मॉड्यूल


joystick_input


जॉयस्टिक_इनपुट का उपयोग जॉयस्टिक के इनपुट के आधार पर एक दिशा कोड बनाने के लिए किया जाता है।


game_logic


game_logic में गेम खेलने के लिए आवश्यक सभी तर्क सम्‍मिलित हैं। मॉड्यूल दिए गए दिशा में एक सांप ले जाता है। इसके अतिरिक्त, यह एक सेब खाने और टक्कर का पता लगाने के लिए जिम्मेदार है। इसके अलावा, यह स्क्रीन पर एक पिक्सेल का वर्तमान x और y निर्देशांक प्राप्त करता है और स्थिति पर रखी गई इकाई को लौटाता है।


VGA_Draw


दराज वर्तमान स्थिति ( iVGA_X, iVGA_Y ) और वर्तमान इकाई ( प्रवेश ) के आधार पर एक पिक्सेल का एक विशेष मूल्य निर्धारित करता है


VGA_Ctrl


VGA आउटपुट ( V_Sync, H_Sync, R, G, B ) पर एक नियंत्रण बिटस्ट्रीम बनाता है


SSEG_Display 2


SSEG_Display 7-सेगमेंट डिस्प्ले पर वर्तमान स्कोर को आउटपुट करने के लिए एक ड्राइवर है।


VGA_clk


VGA_clk 50MHz घड़ी प्राप्त करता है और इसे घटाकर 25.175 MHz करता है।


game_upd_clk


game_upd_clk एक मॉड्यूल है जो एक विशेष घड़ी उत्पन्न करता है जो गेम स्टेट के अपडेट को ट्रिगर करता है।


आउटपुट


  • VGA_B - VGA ब्लू पिन (PIN_144)
  • VGA_G - VGA ग्रीन पिन (PIN_1)
  • VGA_R - VGA लाल पिन (PIN_2)
  • VGA_HS - VGA क्षैतिज सिंक्रनाइज़ेशन (PIN_142)
  • VGA_VS - VGA वर्टिकल सिंक्रोनाइज़ेशन (PIN_143)
  • sseg_a_to_dp - यह निर्दिष्ट करता है कि 8 खंडों में से कौन सा प्रकाश (PIN_115, PIN_119, PIN_120, PIN_121, PIN_124, PIN_125, PIN_126, PIN_127)
  • sseg_an - निर्दिष्ट करता है कि 4 में से कौन सा 7-खंड प्रदर्शित करता है (PIN_128, PIN_129, PIN_132, PIN_133)

कार्यान्वयन


एसपीआई जॉयस्टिक के साथ इनपुट


stick.jpg


चित्रा 4. एसपीआई जॉयस्टिक (KY-023)


इनपुट मॉड्यूल को लागू करते समय, हमें पता चला कि छड़ी एक एनालॉग सिग्नल का उत्पादन करती है। जॉयस्टिक में प्रत्येक अक्ष के लिए 3 स्थान हैं:


  • शीर्ष - ~ 5V आउटपुट
  • मध्य - ~ 2.5V आउटपुट
  • कम - ~ 0V आउटपुट

इनपुट, टर्नरी सिस्टम के समान है: एक्स-एक्सिस के लिए, हमारे पास true (बाएं), false (दाएं) और एक undetermined स्थिति है, जहां जॉयस्टिक न तो बाईं तरफ है और न ही दाईं ओर। समस्या यह है कि FPGA बोर्ड केवल एक डिजिटल इनपुट की प्रक्रिया कर सकता है। इसलिए हम केवल कुछ कोड लिखकर इस टर्नरी लॉजिक को बाइनरी में नहीं बदल सकते। पहला सुझाया गया समाधान एक एनालॉग-डिजिटल कनवर्टर खोजना था, लेकिन फिर हमने भौतिकी के अपने स्कूल के ज्ञान का उपयोग करने और वोल्टेज विभक्त 3 को लागू करने का निर्णय लिया। तीन राज्यों को परिभाषित करने के लिए, हमें दो बिट्स की आवश्यकता होगी: 00 false , 01 undefined और 11 true । कुछ मापों के बाद, हमें पता चला कि हमारे बोर्ड पर, शून्य और एक के बीच की सीमा लगभग 1.7 वी है। इस प्रकार, हमने निम्नलिखित योजना बनाई (सर्किटलैब 4 का उपयोग करके बनाई गई छवि):


Stick_connection.png


चित्रा 5. जॉयस्टिक के लिए एडीसी के लिए सर्किट


भौतिक कार्यान्वयन Arduino किट आइटम का उपयोग करके बनाया गया है, और निम्नानुसार दिखता है:


stick_imp


चित्रा 6. एडीसी कार्यान्वयन


हमारा सर्किट प्रत्येक अक्ष के लिए एक इनपुट लेता है और दो आउटपुट उत्पन्न करता है: पहला छड़ी से सीधे आता है और केवल शून्य हो जाता है यदि जॉयस्टिक आउटपुट zero । दूसरा undetermined स्थिति में 0 है, लेकिन अभी भी 1 true । यह सटीक परिणाम है जिसकी हमें उम्मीद थी।


इनपुट मॉड्यूल का तर्क है:


  1. हम प्रत्येक दिशा के लिए सरल द्विआधारी तारों के लिए अपने त्रिगुट तर्क का अनुवाद करते हैं;
  2. प्रत्येक घड़ी चक्र में, हम जांचते हैं कि क्या केवल एक दिशा true (सांप तिरछे होकर नहीं जा सकता);
  3. हम अपनी नई दिशा की तुलना पिछले एक के साथ करते हैं ताकि सांप को खाने से रोका जा सके और खिलाड़ी को विपरीत दिशा में बदलने की अनुमति नहीं दी।

इनपुट मॉड्यूल कोड का एक हिस्सा
 reg left, right, up, down; initial begin direction = `TOP_DIR; end always @(posedge clk) begin //1 left = two_resistors_x; right = ~one_resistor_x; up = two_resistors_y; down = ~one_resistor_y; if (left + right + up + down == 3'b001) //2 begin if (left && (direction != `RIGHT_DIR)) //3 begin direction = `LEFT_DIR; end //same code for other directions end end 

वीजीए को आउटपुट


हमने 60 एफपीएस पर चलने वाली 60 हर्ट्ज की स्क्रीन पर संकल्प 640x480 के साथ आउटपुट बनाने का फैसला किया।


वीजीए मॉड्यूल में 2 मुख्य भाग होते हैं: एक चालक और एक दराज । ड्राइवर वर्टिकल, हॉरिजॉन्टल सिंक्रोनाइज़ेशन सिग्नल्स और बिटा वीजीए आउटपुट को दिए गए कलर से मिलकर एक बिटस्ट्रीम बनाता है। @SlavikMIPT द्वारा लिखा गया एक लेख 5 वीजीए के साथ काम करने के बुनियादी सिद्धांतों का वर्णन करता है। हमने ड्राइवर को लेख से हमारे बोर्ड में अनुकूलित किया है।


हमने स्क्रीन को 40x30 एलिमेंट ग्रिड में तोड़ने का फैसला किया, जिसमें 16x16 पिक्सल्स शामिल हैं। प्रत्येक तत्व 1 खेल इकाई के लिए खड़ा है: या तो एक सेब, एक सांप का सिर, एक पूंछ या कुछ भी नहीं।


हमारे कार्यान्वयन में अगला कदम संस्थाओं के लिए स्प्राइट बनाना था।


चक्रवात IV में वीजीए (लाल के लिए 1, हरे रंग के लिए 1, और नीले रंग के लिए 1) पर एक रंग का प्रतिनिधित्व करने के लिए केवल 3 बिट्स हैं। इस तरह की सीमा के कारण, हमें छवियों में रंगों को फिट करने के लिए एक कनवर्टर को लागू करने की आवश्यकता थी। उस उद्देश्य के लिए, हमने एक अजगर लिपि बनाई, जो हर पिक्सेल के RGB मान को 128 से विभाजित करती है।


अजगर की पटकथा
 from PIL import Image, ImageDraw filename = "snake_head" index = 1 im = Image.open(filename + ".png") n = Image.new('RGB', (16, 16)) d = ImageDraw.Draw(n) pix = im.load() size = im.size data = [] code = "sp[" + str(index) + "][{i}][{j}] = 3'b{RGB};\\\n" with open("code_" + filename + ".txt", 'w') as f: for i in range(size[0]): tmp = [] for j in range(size[1]): clr = im.getpixel((i, j)) vg = "{0}{1}{2}".format(int(clr[0] / 128), # an array representation for pixel int(clr[1] / 128), # since clr[*] in range [0, 255], int(clr[2] / 128)) # clr[*]/128 is either 0 or 1 tmp.append(vg) f.write(code.format(i=i, j=j, RGB=vg)) # Verilog code to initialization d.point((i, j), tuple([int(vg[0]) * 255, int(vg[1]) * 255, int(vg[2]) * 255])) # Visualize final image data.append(tmp) n.save(filename + "_3bit.png") for el in data: print(" ".join(el)) 

मूलस्क्रिप्ट के बाद



चित्रा 7. इनपुट और आउटपुट के बीच तुलना


दराज का मुख्य उद्देश्य वर्तमान स्थिति ( iVGA_X, iVGA_Y ) और वर्तमान इकाई ( प्रवेश ) के आधार पर वीजीए के लिए पिक्सेल का एक रंग भेजना है। सभी स्प्राइट हार्ड-कोडेड हैं, लेकिन ऊपर स्क्रिप्ट का उपयोग करके एक नया कोड उत्पन्न करके आसानी से बदला जा सकता है।


दराज का तर्क
 always @(posedge iVGA_CLK or posedge reset) begin if(reset) begin oRed <= 0; oGreen <= 0; oBlue <= 0; end else begin // DRAW CURRENT STATE if (ent == `ENT_NOTHING) begin oRed <= 1; oGreen <= 1; oBlue <= 1; end else begin // Drawing a particular pixel from sprite oRed <= sp[ent][iVGA_X % `H_SQUARE][iVGA_Y % `V_SQUARE][0]; oGreen <= sp[ent][iVGA_X % `H_SQUARE][iVGA_Y % `V_SQUARE][1]; oBlue <= sp[ent][iVGA_X % `H_SQUARE][iVGA_Y % `V_SQUARE][2]; end end end 

7-सेगमेंट डिस्प्ले में आउटपुट


खिलाड़ी को अपना स्कोर देखने में सक्षम बनाने के उद्देश्य से, हमने 7-सेगमेंट डिस्प्ले में गेम स्कोर को आउटपुट करने का निर्णय लिया। समय की कमी के कारण, हमने EP4CE6 स्टार्टर बोर्ड डॉक्यूमेंटेशन 2 से कोड का उपयोग किया। यह मॉड्यूल प्रदर्शन के लिए एक हेक्साडेसिमल संख्या को आउटपुट करता है।


खेल तर्क


विकास के दौरान, हमने कई दृष्टिकोणों की कोशिश की, हालांकि, हमने उस के साथ समाप्त कर दिया जिसमें न्यूनतम मात्रा में मेमोरी की आवश्यकता होती है, हार्डवेयर में लागू करना आसान है, और समानांतर संगणना से लाभ उठा सकते हैं।


मॉड्यूल कई कार्य करता है। जैसा कि वीजीए प्रत्येक घड़ी चक्र पर एक पिक्सेल खींचता है, जो ऊपरी बाएँ से शुरू होकर निचले दाएं की ओर बढ़ता है, वीजीए_ड्राव मॉड्यूल, जो पिक्सेल के लिए एक रंग का उत्पादन करने के लिए जिम्मेदार है, को पहचानने की जरूरत है कि वर्तमान निर्देशांक के लिए किस रंग का उपयोग करना है। यही कारण है कि गेम लॉजिक मॉड्यूल को आउटपुट देना चाहिए - दिए गए निर्देशांक के लिए एक इकाई कोड।
इसके अलावा, इसे फुल स्क्रीन ड्रा होने के बाद ही गेम स्टेट को अपडेट करना होगा। Game_upd_clk मॉड्यूल द्वारा निर्मित एक सिग्नल का उपयोग यह निर्धारित करने के लिए किया जाता है कि अपडेट कब करना है।


खेल राज्य


खेल राज्य में निम्न शामिल हैं:


  • सांप के सिर का निर्देशन
  • साँप की पूंछ के निर्देशांक की एक सरणी। सरणी हमारे कार्यान्वयन में 128 तत्वों द्वारा सीमित है
  • पूंछ की संख्या
  • एक सेब के निर्देशांक
  • झंडे पर खेल
  • खेल ने झंडा फहराया

खेल राज्य के अद्यतन में कई चरण शामिल हैं:


  1. दिए गए निर्देश के आधार पर सांप के सिर को नए निर्देशांक में ले जाएं। यदि यह पता चलता है कि एक समन्वय इसके किनारे पर है और इसे आगे बदलना होगा, तो सिर को स्क्रीन के दूसरे किनारे पर कूदना होगा। उदाहरण के लिए, एक दिशा बाईं ओर स्थित है, और वर्तमान X निर्देशांक 0. है। इसलिए, नए X निर्देशांक अंतिम क्षैतिज पते के बराबर हो जाना चाहिए।
  2. सेब के निर्देशांक के खिलाफ सांप के सिर के नए निर्देशांक का परीक्षण किया जाता है:
    2.1। यदि वे समान हैं और सरणी पूर्ण नहीं है, तो सरणी में एक नई पूंछ जोड़ें और पूंछ काउंटर को बढ़ाएं। जब काउंटर अपने उच्चतम मूल्य (हमारे मामले में 128) तक पहुंचता है, तो गेम जीता हुआ झंडा स्थापित किया जा रहा है और इसका मतलब है, कि सांप अब और नहीं बढ़ सकता है, और खेल अभी भी जारी है। नई पूंछ को सांप के सिर के पिछले निर्देशांक पर रखा गया है। एक्स और वाई के लिए यादृच्छिक निर्देशांक एक सेब को वहां ले जाना चाहिए।
    2.2। मामले में वे समान नहीं हैं, आसन्न पूंछ के क्रमिक रूप से स्वैप निर्देशांक। (n + 1) -थ टेल को n-th के निर्देशांक प्राप्त होने चाहिए, अगर n-th पूंछ को पहले जोड़ा गया था (n + 1) -th। पहली पूंछ सिर के पुराने निर्देशांक प्राप्त करती है।
  3. चेक करें, अगर सांप के सिर के नए निर्देशांक किसी भी पूंछ के निर्देशांक के साथ मेल खाते हैं। अगर ऐसा है, तो गेम ओवर फ्लैग उठाया जाता है और खेल रुक जाता है।

यादृच्छिक समन्वय पीढ़ी


6-बिट रैखिक-प्रतिक्रिया पारी शिफ्ट रजिस्टरों (LFSR) 6 द्वारा उत्पन्न यादृच्छिक बिट्स द्वारा उत्पादित यादृच्छिक संख्या। एक स्क्रीन में संख्याओं को फिट करने के लिए उन्हें खेल ग्रिड के आयामों द्वारा विभाजित किया जा रहा है और शेष लिया गया है।


निष्कर्ष


8 सप्ताह के काम के बाद, परियोजना को सफलतापूर्वक लागू किया गया था। हमें खेल के विकास में कुछ अनुभव हुआ है और एक FPGA के लिए "स्नेक" गेम का एक सुखद संस्करण है। खेल खेलने योग्य है, और प्रोग्रामिंग में हमारे कौशल, एक वास्तुकला और सॉफ्ट-कौशल को डिजाइन करने में सुधार हुआ है।


स्वीकृत खंड


हम अपने प्रोफेसरों मुहम्मद फहीम और अलेक्जेंडर टोरामासोव के प्रति विशेष धन्यवाद और आभार व्यक्त करना चाहते हैं ताकि हमें गहन ज्ञान और इसे व्यवहार में लाने का अवसर मिले। हम डिबगिंग में मदद करने के लिए प्रोजेक्ट में इस्तेमाल किए गए आवश्यक हार्डवेयर और तैमूर खोलमटोव के साथ हमें प्रदान करने के लिए व्लादिस्लाव ओस्तनकोविच को दिल से धन्यवाद देते हैं। हम अनास्तासिया बोइको को खेल के लिए खूबसूरत स्प्राइट्स याद करना नहीं भूलेंगे । इसके अलावा, हम इस लेख को प्रूफ़रीडिंग और एडिट करने के लिए रब मारौफ़ के लिए अपने ईमानदार मुहिम का विस्तार करना चाहते हैं।


उन सभी के लिए धन्यवाद जिन्होंने हमें खेल का परीक्षण करने में मदद की और एक रिकॉर्ड स्थापित करने की कोशिश की। आशा है कि आप इसे खेलने का आनंद लेंगे!


संदर्भ


[१]: गीथूब पर परियोजना
[२]: [FPGA] EP4CE6 स्टार्टर बोर्ड डॉक्यूमेंटेशन
[३]: वोल्टेज विभक्त
[४]: मॉडलिंग सर्किट के लिए उपकरण
[५]: FPGA Altera चक्रवात III के लिए VGA एडाप्टर
[६]: विकिपीडिया पर रैखिक-प्रतिक्रिया पारी रजिस्टर (LFSR)
एक FPGA में LFSR - VHDL और वेरिलॉग कोड
एक सेब बनावट
यादृच्छिक संख्या उत्पन्न करने के लिए विचार
पलनीतकर, एस। (2003)। वेरिलॉग एचडीएल: ए गाइड टू डिजिटल डिज़ाइन एंड सिंथेसिस, दूसरा संस्करण।

Source: https://habr.com/ru/post/hi431226/


All Articles