在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<abbr id="27omo"></abbr>

<menu id="27omo"><dl id="27omo"></dl></menu>
    • <label id="27omo"><tt id="27omo"></tt></label>

      新聞中心

      乒乓球比賽

      作者: 時(shí)間:2023-12-22 來(lái)源:電子森林 收藏

      FPGA可以輕松成為視頻生成器。

      本文引用地址:http://www.biyoush.com/article/202312/454181.htm

      乒乓球游戲包括在屏幕上彈跳的球。槳(此處由鼠標(biāo)控制)使用戶能夠使球彈回。

      盡管可以使用其他任何FPGA開(kāi)發(fā)板,但我們都使用Pluto FPGA板。


      驅(qū)動(dòng)VGA顯示器

      一個(gè)VGA監(jiān)視器需要5個(gè)信號(hào)才能顯示圖片:

      • R,G和B(紅色,綠色和藍(lán)色信號(hào))。
      • HS和VS(水平和垂直同步)。

      R,G和B是模擬信號(hào),而HS和VS是數(shù)字信號(hào)。

      通過(guò)FPGA引腳創(chuàng)建

      以下是驅(qū)動(dòng)VGA接口的方法:

      • VGA連接器(HS和VS)的引腳13和14是數(shù)字信號(hào),因此可以直接從兩個(gè)FPGA引腳驅(qū)動(dòng)(或通過(guò)低阻值電阻,例如10Ω或20Ω)驅(qū)動(dòng)。
      • 引腳1、2和3(R,G和B)是75 are模擬信號(hào),標(biāo)稱(chēng)值為0.7V。對(duì)于3.3V FPGA輸出,請(qǐng)使用三個(gè)270Ω串聯(lián)電阻。電阻與監(jiān)視器輸入中的75Ω電阻形成分壓器,因此
      • 3.3V變?yōu)?.3 * 75 /(270 + 75)= 0.72V,非常接近0.7V。以0和1的不同組合來(lái)驅(qū)動(dòng)這3個(gè)引腳時(shí),最多可以得到8種顏色。

      接地引腳是引腳5、6、7、8和10。

      這是連接到面包板上Pluto的母VGA連接器的視圖。

      VGA母頭連接器至12針接頭連接器的后視圖。12針插頭可輕松連接到面包板。三個(gè)270Ω串聯(lián)電阻清晰可見(jiàn)。我們也可以使用轉(zhuǎn)接板。

      頻率發(fā)生器

      監(jiān)視器始終從上到下逐行顯示圖片。每條線從左到右繪制。

      這是硬編碼的,您無(wú)法更改。

      但是,您可以通過(guò)以固定間隔在HS和VS上發(fā)送短脈沖來(lái)指定何時(shí)開(kāi)始繪制圖形。HS畫(huà)了一條新線開(kāi)始繪制;而VS告訴您已經(jīng)到達(dá)底部(使監(jiān)視器回到頂部)。

      對(duì)于標(biāo)準(zhǔn)640×480 ,脈沖頻率應(yīng)為:

      垂直頻率(VS)水平頻率(HS)
      60 Hz(= 60脈沖每秒)31.5 kHz(= 31500脈沖/秒)

      要?jiǎng)?chuàng)建標(biāo)準(zhǔn)視頻信號(hào),需要處理更多細(xì)節(jié),例如脈沖的持續(xù)時(shí)間以及HS和VS之間的關(guān)系。在此頁(yè)面上獲得一個(gè)想法。

      我們的第一個(gè)視頻生成器

      如今,VGA監(jiān)視器是多同步的,因此可以適應(yīng)非標(biāo)準(zhǔn)頻率-不再需要精確地生成60Hz和31.5KHz(但是,如果您使用的是舊的(非多同步)VGA監(jiān)視器,則需要生成精確的頻率)。

      讓我們從X和Y計(jì)數(shù)器開(kāi)始。

      reg [9:0] CounterX;
      reg [8:0] CounterY;
      wire CounterXmaxed = (CounterX==767); 
      always @(posedge clk)if(CounterXmaxed)
        CounterX <= 0;else
        CounterX <= CounterX + 1; 
        always @(posedge clk)if(CounterXmaxed)
          CounterY <= CounterY + 1;

      CounterX計(jì)數(shù)768個(gè)值(從0到767),CounterY計(jì)數(shù)512個(gè)值(0到511)。

      現(xiàn)在,使用CounterX生成HS,使用CounterY生成VS。使用25MHz時(shí)鐘,HS的頻率為32.5KHz,VS的頻率為63.5Hz。脈沖需要激活足夠長(zhǎng)的時(shí)間,以使監(jiān)視器能夠檢測(cè)到它們。讓我們?yōu)镠S使用16個(gè)時(shí)鐘脈沖(0.64μs),為VS使用完整的水平線長(zhǎng)脈沖(768個(gè)時(shí)鐘或30μs)。這比VGA規(guī)范所要求的要短,但仍然可以正常工作。

      我們從D觸發(fā)器生成HS和VS脈沖(以獲得無(wú)毛刺輸出)。

      reg vga_HS, vga_VS;always @(posedge clk)begin
        vga_HS <= (CounterX[9:4]==0);   // active for 16 clocks
        vga_VS <= (CounterY==0);   // active for 768 clocksend

      VGA輸出必須為負(fù),因此我們將信號(hào)反相。

      assign vga_h_sync = ~vga_HS;
      assign vga_v_sync = ~vga_VS;

      最后,我們可以驅(qū)動(dòng)R,G和B信號(hào)。首先,我們可以使用X和Y計(jì)數(shù)器的一些位來(lái)獲得漂亮的正方形顏色圖案…

      assign R = CounterY[3] | (CounterX==256);
      assign G = (CounterX[5] ^ CounterX[6]) | (CounterX==256);
      assign B = CounterX[4] | (CounterX==256);

      …然后我們?cè)赩GA監(jiān)視器上得到一張照片!

      畫(huà)有用的圖片

      最好將同步生成器重寫(xiě)為HDL模塊,以便在外部生成R,G和B。同樣,如果X和Y計(jì)數(shù)器從繪圖區(qū)域開(kāi)始計(jì)數(shù),它們將更加有用。 可以在這里找到新文件。

      現(xiàn)在,我們可以使用它在屏幕周?chē)L制邊框。

      module pong(clk, vga_h_sync, vga_v_sync, vga_R, vga_G, vga_B);
      input clk;
      output vga_h_sync, vga_v_sync, vga_R, vga_G, vga_B;
      wire inDisplayArea;
      wire [9:0] CounterX;
      wire [8:0] CounterY; 
      hvsync_generator syncgen(.clk(clk), .vga_h_sync(vga_h_sync), .vga_v_sync(vga_v_sync),
                                  .inDisplayArea(inDisplayArea), .CounterX(CounterX), .CounterY(CounterY)); 
                                  // Draw a border around the screen
      wire border = (CounterX[9:3]==0) || (CounterX[9:3]==79) || (CounterY[8:3]==0) || (CounterY[8:3]==59);
      wire R = border;wire G = border;wire B = border;
      reg vga_R, vga_G, vga_B;
      always @(posedge clk)begin
        vga_R <= R & inDisplayArea;
        vga_G <= G & inDisplayArea;
        vga_B <= B & inDisplayArea;
        end 
        endmodule

      畫(huà)槳

      讓我們使用鼠標(biāo)在屏幕上左右移動(dòng)操縱桿。

      該解碼器正交頁(yè)面顯示的秘密。代碼如下:

      reg [8:0] PaddlePosition;
      reg [2:0] quadAr, quadBr;
      always @(posedge clk) quadAr <= {quadAr[1:0], quadA};
      always @(posedge clk) quadBr <= {quadBr[1:0], quadB}; 
      always @(posedge clk)if(quadAr[2] ^ quadAr[1] ^ quadBr[2] ^ quadBr[1])begin
        if(quadAr[2] ^ quadBr[1])
        begin
          if(~&PaddlePosition)        // make sure the value doesn't overflow
            PaddlePosition <= PaddlePosition + 1;
        end
        else
        begin
          if(|PaddlePosition)        // make sure the value doesn't underflow
            PaddlePosition <= PaddlePosition - 1;
        endend

      現(xiàn)在知道“ PaddlePosition”的值,我們可以顯示槳了。

      wire border = (CounterX[9:3]==0) || (CounterX[9:3]==79) || (CounterY[8:3]==0) || (CounterY[8:3]==59);
      wire paddle = (CounterX>=PaddlePosition+8) && (CounterX<=PaddlePosition+120) && (CounterY[8:4]==27); 
      wire R = border | (CounterX[3] ^ CounterY[3]) | paddle;
      wire G = border | paddle;
      wire B = border | paddle;

      畫(huà)球

      球需要在屏幕上移動(dòng),并在碰到物體(邊界或球拍)時(shí)反彈。

      首先,我們展示球。它是16×16像素的正方形。當(dāng)CounterX和CounterY到達(dá)其坐標(biāo)時(shí),我們將激活球的繪制。

      reg [9:0] ballX;reg [8:0] ballY;
      reg ball_inX, ball_inY; 
      always @(posedge clk)if(ball_inX==0) ball_inX <= (CounterX==ballX) & ball_inY; 
      else ball_inX <= !(CounterX==ballX+16); 
      always @(posedge clk)if(ball_inY==0) ball_inY <= (CounterY==ballY); 
      else ball_inY <= !(CounterY==ballY+16); 
      wire ball = ball_inX & ball_inY;

      現(xiàn)在進(jìn)行碰撞。那是這個(gè)項(xiàng)目的困難部分。

      我們可以檢查球相對(duì)于屏幕上每個(gè)對(duì)象的坐標(biāo),并確定是否存在碰撞。但是隨著對(duì)象數(shù)量的增加,這將很快成為一場(chǎng)噩夢(mèng)。

      取而代之的是,我們定義4個(gè)“熱點(diǎn)”像素,在球每側(cè)的中間一個(gè)像素。如果物體(邊界或球拍)在球繪制其“熱點(diǎn)”之一的同時(shí)重繪自身,則我們知道球的那一側(cè)存在碰撞。

      wire border = (CounterX[9:3]==0) || (CounterX[9:3]==79) || (CounterY[8:3]==0) || (CounterY[8:3]==59);
      wire paddle = (CounterX>=PaddlePosition+8) && (CounterX<=PaddlePosition+120) && (CounterY[8:4]==27);
      wire BouncingObject = border | paddle; // active if the border or paddle is redrawing itself 
      reg CollisionX1, CollisionX2, CollisionY1, CollisionY2;
      always @(posedge clk) if(BouncingObject & (CounterX==ballX ) & (CounterY==ballY+ 8)) CollisionX1<=1;
      always @(posedge clk) if(BouncingObject & (CounterX==ballX+16) & (CounterY==ballY+ 8)) CollisionX2<=1;
      always @(posedge clk) if(BouncingObject & (CounterX==ballX+ 8) & (CounterY==ballY )) CollisionY1<=1;
      always @(posedge clk) if(BouncingObject & (CounterX==ballX+ 8) & (CounterY==ballY+16)) CollisionY2<=1;

      (我通過(guò)從未重置碰撞觸發(fā)器來(lái)簡(jiǎn)化了上面的代碼,下面提供了完整的代碼)。

      現(xiàn)在,我們更新球的位置,但每個(gè)視頻幀僅更新一次。

      reg UpdateBallPosition;       // active only once for every video frame
      always @(posedge clk) UpdateBallPosition <= (CounterY==500) & (CounterX==0); 
      reg ball_dirX, ball_dirY;
      always @(posedge clk)if(UpdateBallPosition)begin
        if(~(CollisionX1 & CollisionX2))        // if collision on both X-sides, don't move in the X direction
        begin
          ballX <= ballX + (ball_dirX ? -1 : 1);
          if(CollisionX2) ball_dirX <= 1; 
          else if(CollisionX1) ball_dirX <= 0;
        end   if(~(CollisionY1 & CollisionY2))        // if collision on both Y-sides, don't move in the Y direction
        begin
          ballY <= ballY + (ball_dirY ? -1 : 1);
          if(CollisionY2) ball_dirY <= 1; 
          else if(CollisionY1) ball_dirY <= 0;
        end
        end

      最后,我們可以將所有內(nèi)容整合在一起。

      wire R = BouncingObject | ball | (CounterX[3] ^ CounterY[3]);
      wire G = BouncingObject | ball;
      wire B = BouncingObject | ball; 
      reg vga_R, vga_G, vga_B;
      always @(posedge clk)begin
        vga_R <= R & inDisplayArea;
        vga_G <= G & inDisplayArea;
        vga_B <= B & inDisplayArea;
        end

      哇,其實(shí)并不難。



      評(píng)論


      相關(guān)推薦

      技術(shù)專(zhuān)區(qū)

      關(guān)閉