ساخت شمارنده باینری با استفاده از برد FPGA Mojo V3

فهرست مطالب

ویژگی های برد FPGA Mojo V3

برد Mojo مبتنی بر FPGA از سری اسپارتان 6 بوده که شما را قادر می‌سازد تا لذت پیکربندی مدار دیجیتالی را بر Mojo v3 با مشخصات دلخواهتان تجربه کنید. آنچه این برد را از سایر بردها متمایز می‌کند، استفاده آسان از آن است. در واقع هدف Mojo V3 این است که کاربر بتواند FPGA را به راحتی اجرا کند.

Mojo V3 از اسپارتان 6 و میکروکنترلر ATmega32U4 با عملکرد بالا بهره می‌برد. این برد از قدرت پردازش بالایی برخوردار است. ATmega32U4 همراه با یک بوت لودر USB (DFU) است که به شما این امکان را می‌دهد بدون نیاز به پروگرامر، نسخه جدید سیستم عامل را نصب کنید. به محض روشن شدن برد، ATmega ،FPGA را از حافظه فلش پیکربندی می‌کند. پس از پیکربندی موفقیت آمیز FPGA ، طرح‌های FPGA با میکروکنترلر ارتباط برقرار می‌کنند. همچنین به شما امکان دسترسی به پورت سریال و ورودی‌های آنالوگ را می‌دهد.

جهت دریافت دیتاشیت  FPGA SPARTAN 6 اینجا کلیک کنید.

جهت دریافت دیتاشیت  ATMega32U4 اینجا کلیک کنید.

جهت دریافت دیتاشیت  Schematic اینجا کلیک کنید.

 

معرفی پایه ها (Pinout) ماژول FPGA Mojo V3

ماژول FPGA Mojo V3 دارای 110 پایه به شرح زیر است:

  • 3V: تغذیه ماژول
  • GND: زمین
  • RAW: تغذیه ورودی رگورلاتور 3V
  • P1~P144: پایه‌های دیجیتال ورودی و خروجی ماژول
  • A0~A9: پایه‌های انالوگ ماژول
  • AREF: ولتاژ مرجع پایه های انالوگ ماژول
  • RES: ریست کردن ماژول – تنظیم به عنوان کلید
  • DONE: کنترل نور پس زمینه ماژول
  • SUSPEND: تنظیم جهت ورود و خروج به حالت کم مصرف جهت اطلاعات بیشتر بر روی لینک کلیک کنید
  • TDO: خط دیتا ورودی برای ارتباط JTAG
  • TMS: پایه تعیین ترتیب حالت ها برای ارتباط JTAG
  • TCK: خط تست کلاک JTAG
  • TDI: خط دیتا خروجی برای ارتباط JTAG
  • DONE: کنترل نور پس زمینه ماژول
  • LED1~LED7: نمایشگر LED

برای اطلاعات بیشتر در مورد JTAG بر روی لینک کلیک کنید.

لوازمی که به آن احتیاج دارید

قطعات مورد نیاز

برد MOJO V3 - FPGA SPARTAN 6 × 1
میکرو سوئیچ 6x6x9.5 × 2
سون سگمنت چهار رقمی 0.56 اینچی × 1
مقاومت 330 اهم 1/4W 5% × 7

راه‌اندازی شمارنده با استفاده از برد FPGA Mojo V3

گام اول: سیم بندی

مطابق مدار زیر، ماژول را به Mojo V3 وصل کنید.

نکته

پیشنهاد می‌شود سگمنت را به همراه مقاومت‌ها بر روی برد سوراخ‌دار هویه کنید و با استفاده از پین هدر به ماژول متصل کنید.

توجه

اگر نیاز به راهنمایی بیشتر برای نصب نرم‌افزار Mojo IDE دارید، می‌توانید به آموزش در اینجا مراجعه کنید.

گام دوم: کد

در ابتدای کار مشابه آردوینو باید پایه‌های مورد استفاده را تعریف کنیم. برای انجام این کار از منوی File نرم‌افزار Mojo IDE بر روی گزینه New Project کلیک کرده و قسمت‌های خالی را مشابه تصویر زیر پر کنید.

از منوی سمت چپ بر روی گزینه Constraints راست کلیک کرده و گزینه New Constraints را انتخاب کنید.

در صفحه باز شده File name را هر مقداری که می‌خواهید وارد کنید و گزینه User Constraints را انتخاب کنید و بر روی گزینه Create File کلیک کنید.

از منو Constraints، فایلی که ساخته‌اید را باز کرده و کد زیر را وارد کنید.

NET "seg<7>" LOC = P12  | IOSTANDARD = LVTTL;//A
NET "seg<6>" LOC = P2   | IOSTANDARD = LVTTL;//B
NET "seg<5>" LOC = P134 | IOSTANDARD = LVTTL;//C
NET "seg<4>" LOC = P24  | IOSTANDARD = LVTTL;//D
NET "seg<3>" LOC = P22  | IOSTANDARD = LVTTL;//E
NET "seg<2>" LOC = P10  | IOSTANDARD = LVTTL;//F
NET "seg<1>" LOC = P138 | IOSTANDARD = LVTTL;//G
NET "seg<0>" LOC = P27  | IOSTANDARD = LVTTL;//DP

NET "sel<0>" LOC = P144 | IOSTANDARD = LVTTL;//segment1
NET "sel<1>" LOC = P6   | IOSTANDARD = LVTTL;//segment2
NET "sel<2>" LOC = P8   | IOSTANDARD = LVTTL;//segment3
NET "sel<3>" LOC = P15  | IOSTANDARD = LVTTL;//segment4

NET "button<0>" LOC = P140  | IOSTANDARD = LVTTL|PULLUP;//io_button 1
NET "button<1>" LOC = P142  | IOSTANDARD = LVTTL|PULLUP;//io_button 2
نکته

در صورتی که می‌خواهید از پایه‌های دیگر استفاده کنید در این بخش می‌توانید پایه‌ها را تغییر دهید.

بر روی منو Source راست کلیک کرده و گزینه New Source را انتخاب کنید.

در صفحه باز شده، نام فایل را 7seg قرار دهید و گزینه Lucid Source را انتخاب کرده و فایل را بسازید.

از منو Source فایلی که ساخته اید را باز کنید و کد زیر را وارد کنید.

module segment (
    input clk,  // clock
    input rst,  // reset
    input button[2],
    
     output segment1,
    output segment2,
    output segment3,
    output data1,
    output data2,
    output data3,
    output data4,
    output data5,
    output data6,
    output data7,
    output data8,
    output data9,
    output data10,
    output data11,
    output data12,
    output data13,
    output data14,
    output data15,
    output data16
    
  )
  {
  
  dff counter2[20](.clk(clk));
  
  dff counter1[33](.clk(counter2.q[19]));
  
  
  always {
    //blinker = counter1.q[24];?
    if(button[1]==0&amp;&amp;button[0]==1){
      
      counter1.d = counter1.q+1;
    }
    
    
    else if(button[0]==0&amp;&amp;button[1]==1){
      
      counter1.d = counter1.q-1;
    }
    
    data1 = counter1.q[0];
    data2 = counter1.q[1];
    data3 = counter1.q[2];
    data4 = counter1.q[3];
    data5 = counter1.q[4];
    data6 = counter1.q[5];
    data7 = counter1.q[6];
    data8 = counter1.q[7];
    data9 = counter1.q[8];
    data10 = counter1.q[9];
    data11 = counter1.q[10];
    data12 = counter1.q[11];
    data13 = counter1.q[12];
    data14 = counter1.q[13];
    data15 = counter1.q[15];
    data16 = counter1.q[16];
    
    
    counter2.d = counter2.q+1;
    segment1 = counter2.q[16];
    segment2 = counter2.q[17];
    segment3 = counter2.q[18];
    
  }
  
}

در مدار‌های منطقی برای ساخت شمارنده باینری، از D-FlipFlop های پشت سر هم استفاده می‌شود. در FPGA نیز از این روش استفاده می شود.

dff name[Number of D-FlipFlop](.clk(Connect clk first D-DlipFlop),.rst(Connect rst All D-FlipFlop));

با دستور dff یک عدد D-FlipFlop ساخته می‌شود. سپس یک نام برای D-FlipFlop انتخاب می‌کنید، سپس تعداد D-FlipFlop هایی که به یکدیگر متصل شده اند مشخص می شود. سپس مشخص می کنید که پایه کلاک اولین D-FlipFlop به کجا متصل شده باشد. در ادامه پایه ریست تمامی D-FlipFlop ها تعیین می شود. این کار اختیاری است و میتوانید آن را انجام ندهید.

counter1.d = counter1.q+1;

از این دستور برای اضافه کردن یک مقدار به مقدار قبلی سری D-FlipFlop ها استفاده می‌شود.

سپس از منوی Source، فایل mojo_top.luc را باز کرده و کد زیر را وارد کنید.

module mojo_top (
    
    //output led [8],         // 8 user controllable LEDs
    
    output seg [8],
    output sel [4],
    input button[2],


    
    input clk,              // 100MHz clock
    input rst_n            // reset button (active low)
  ) {
  
  sig rst;                 // reset signal
  sig my_array[16][8];
  sig value[4][4];

  .clk(clk) {
    // The reset conditioner is used to synchronize the reset signal to the FPGA
    // clock. This ensures the entire FPGA comes out of reset at the same time.
    reset_conditioner reset_cond;

    .rst(rst){
      segment myseg;
    }
    
  }
  
  always {
    myseg.button[0]=button[0];  
    myseg.button[1]=button[1];  
  
    
    reset_cond.in = ~rst_n; // input raw inverted reset signal
    rst = reset_cond.out;   // conditioned reset
    //value = 1234;

    value[0][0]=myseg.data1;
    value[0][1]=myseg.data2;
    value[0][2]=myseg.data3;
    value[0][3]=myseg.data4;
    
    value[1][0]=myseg.data5;
    value[1][1]=myseg.data6;
    value[1][2]=myseg.data7;
    value[1][3]=myseg.data8;
    
    value[2][0]=myseg.data9;
    value[2][1]=myseg.data10;
    value[2][2]=myseg.data11;
    value[2][3]=myseg.data11;
    
    
    value[3][0]=myseg.data12;
    value[3][1]=myseg.data13;
    value[3][2]=myseg.data14;
    value[3][3]=myseg.data15;
    
    //A,B,C,D,E,F,G,DP
    my_array[0]  = c{1,1,1,1,1,1,0,0};
    my_array[1]  = c{0,1,1,0,0,0,0,0};
    my_array[2]  = c{1,1,0,1,1,0,1,0};
    my_array[3]  = c{1,1,1,1,0,0,1,0};
    my_array[4]  = c{0,1,1,0,0,1,1,0};
    my_array[5]  = c{1,0,1,1,0,1,1,0};
    my_array[6]  = c{0,0,1,1,1,1,1,0};
    my_array[7]  = c{1,1,1,0,0,0,0,0};
    my_array[8]  = c{1,1,1,1,1,1,1,0};
    my_array[9]  = c{1,1,1,0,0,1,1,0};
    my_array[10] = c{1,1,1,0,1,1,1,0};
    my_array[11] = c{0,0,1,1,1,1,1,0};
    my_array[12] = c{0,0,0,1,1,0,1,0};
    my_array[13] = c{0,1,1,1,1,0,1,0};
    my_array[14] = c{1,0,0,1,1,1,1,0};
    my_array[15] = c{1,0,0,0,1,1,1,0};
    
    
    
    sel = ~c{0,0,0,0};
    //led=  c{0,0,0,0,0,0,0,0};
    seg=  my_array[15] ;
    
    
    if (myseg.segment1 == 1&&myseg.segment2 != 1&&myseg.segment3 != 1){
      
      //  led=  c{0,0,0,0,0,0,0,1};
      sel = ~c{0,0,0,1};
      //myseg.value = 1;
      seg=  my_array[value[0]];            //A,B,C,D,E,F,G,DP
      
    }
    else if (myseg.segment1 != 1&&myseg.segment2 == 1&&myseg.segment3 != 1){
      //led=  c{0,0,0,0,0,0,1,0};
      sel = ~c{0,0,1,0};
      seg=  my_array[value[1]];
    }
    else if (myseg.segment1 == 1&&myseg.segment2 == 1&&myseg.segment3 != 1){
      //led=  c{0,0,0,0,0,1,0,0};
      
      sel = ~c{0,1,0,0};
      seg=  my_array[value[2]];
    }
    else if (myseg.segment1 != 1&&myseg.segment2 != 1&&myseg.segment3 == 1){
      rst=1;
      //led=  c{0,0,0,0,1,0,0,0};
      sel = ~c{1,0,0,0};
      seg=  my_array[value[3]];
    }    
  }
}

حالا بیایید نگاهی دقیق‌تر به کد بالا بی‌اندازیم.‌

sig my_array[16][8];
  sig value[4][4];

تعریف آرایه 2 بعدی برای مقادیر نمایش داده شده و انتخاب نمایشگر جهت نمایش

segment myseg;

اتصال برنامه اصلی به بخش شمارنده

myseg.button[0]=button[0];  
    myseg.button[1]=button[1];  

انتقال مقادیر شمارنده دکمه ها به بخش شمارنده

//A,B,C,D,E,F,G,DP
    my_array[0]  = c{1,1,1,1,1,1,0,0};
    my_array[1]  = c{0,1,1,0,0,0,0,0};
    my_array[2]  = c{1,1,0,1,1,0,1,0};
    my_array[3]  = c{1,1,1,1,0,0,1,0};
    my_array[4]  = c{0,1,1,0,0,1,1,0};
    my_array[5]  = c{1,0,1,1,0,1,1,0};
    my_array[6]  = c{0,0,1,1,1,1,1,0};
    my_array[7]  = c{1,1,1,0,0,0,0,0};
    my_array[8]  = c{1,1,1,1,1,1,1,0};
    my_array[9]  = c{1,1,1,0,0,1,1,0};
    my_array[10] = c{1,1,1,0,1,1,1,0};
    my_array[11] = c{0,0,1,1,1,1,1,0};
    my_array[12] = c{0,0,0,1,1,0,1,0};
    my_array[13] = c{0,1,1,1,1,0,1,0};
    my_array[14] = c{1,0,0,1,1,1,1,0};
    my_array[15] = c{1,0,0,0,1,1,1,0};

تعریف تمامی حالت‌ها جهت نمایش اعداد

حال پروژه را Build کرده و بر روی ماژول خود آپلود کنید.

در این کد با استفاده از 2 دکمه موجود می‌توان مقادیر نمایش داده شده را زیاد یا کم کرد.

آموزش های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد.