0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于FPGA的電子琴設(shè)計(jì)

FPGA技術(shù)江湖 ? 來(lái)源:FPGA技術(shù)江湖 ? 2025-01-20 14:07 ? 次閱讀

設(shè)計(jì)原理

在之前也出了幾篇源碼系列,基本上都是一些小設(shè)計(jì),源碼系列主要就會(huì)想通過(guò)實(shí)操訓(xùn)練讓各位學(xué)習(xí)者,尤其是初學(xué)者去更好的理解學(xué)習(xí)FPGA,或者給要的學(xué)生提供一些源碼,之前設(shè)計(jì)過(guò)各個(gè)芯片的配置等,之后筆者會(huì)通過(guò)簡(jiǎn)單的例子來(lái)讓大家去系統(tǒng)的學(xué)習(xí)和認(rèn)識(shí)FPGA。本次的電子琴設(shè)計(jì)也算是一次簡(jiǎn)單的各個(gè)模塊的聯(lián)系調(diào)用的一個(gè)過(guò)程,也可以幫助各位去加深理解,多動(dòng)手,熟練掌握會(huì)有意想不到的效果。

本次的設(shè)計(jì)主要是通過(guò)控制ps2鍵盤(pán)來(lái)使蜂鳴器發(fā)出哆來(lái)咪法嗦拉西7種音,音符又有高低音之分等,本次只選擇發(fā)出高音的多來(lái)咪發(fā)嗦啦西。本設(shè)計(jì)中還用到了VGA的設(shè)計(jì),通過(guò)VGA來(lái)在顯示屏上畫(huà)出如下圖的黑白的電子琴鍵:

當(dāng)按下多來(lái)咪發(fā)嗦啦西時(shí),對(duì)應(yīng)的鍵值變顏色表示按下,不變色表示不按下,顏色自己可以調(diào)節(jié),但是琴的按鍵必須為黑白色來(lái)顯示出來(lái)。

當(dāng)按下按鍵的時(shí)候,蜂鳴器來(lái)鳴響對(duì)應(yīng)時(shí)間的音符,本設(shè)計(jì)蜂鳴器響的時(shí)間為0.25S一個(gè)音符持續(xù)的時(shí)間。

本次設(shè)計(jì)用到的PS2和VGA的設(shè)計(jì)原理筆者在這里就不過(guò)多的介紹了,不明白的可以翻看前面發(fā)的文檔內(nèi)容。

在本設(shè)計(jì)中介紹蜂鳴器的使用和各音符發(fā)聲的頻率大小。本設(shè)計(jì)用的是無(wú)源蜂鳴器,原理圖如下:

0bee9e88-d6e4-11ef-9310-92fbcf53809c.png

由于FPGA的驅(qū)動(dòng)能力不夠,我們添加了一個(gè)三極管來(lái)驅(qū)動(dòng)這個(gè)無(wú)源蜂鳴器,而無(wú)源蜂鳴器的主要特點(diǎn)是內(nèi)部不帶振蕩源,所以如果使用直流信號(hào)是無(wú)法使無(wú)源蜂鳴器鳴叫的,必須使用方波去驅(qū)動(dòng)它。

現(xiàn)在我們明白了,只要往蜂鳴器發(fā)送一定頻率的方波,就可以使得蜂鳴器發(fā)出聲音,然后現(xiàn)在的問(wèn)題是,我們究竟要往蜂鳴器發(fā)送什么頻率的方波信號(hào)呢?具體的頻率可以查看下圖:

0bff6b28-d6e4-11ef-9310-92fbcf53809c.png

現(xiàn)在我們知道如何讓蜂鳴器響起,又知道發(fā)送什么頻率可以讓蜂鳴器響起什么的聲音,所以我相信我們已經(jīng)有能力讓蜂鳴器響起我們需要的音樂(lè)了。

設(shè)計(jì)架構(gòu)

設(shè)計(jì)架構(gòu)圖:

在這里沒(méi)有去畫(huà)設(shè)計(jì)框架圖,就直接給大家展示RTL級(jí)視圖,各位也可以通過(guò)RTL級(jí)視圖看到設(shè)計(jì)的總框架。

0c250f36-d6e4-11ef-9310-92fbcf53809c.png

設(shè)計(jì)代碼

頂層模塊music_ps2代碼:

module music_ps2(clk, rst_n, hs, vs, r_g_b, ps2_clk, ps2_data, beep);
  
  input clk;
  input rst_n;


  output  hs;
  output  vs;
  output  [7:0]r_g_b;
  output  beep;
  
  input ps2_clk;
  input ps2_data;
  
  wire flag;
  wire [7:0] data, data_n;
  wire clk_1M;
  
  
  frenp frep_dut(
    .clk(clk),
    .rst_n(rst_n),
    .clk_1M(clk_1M)
    );
    
  ps2_rec rec_dut(
    .clk(clk_1M),
    .rst_n(rst_n),
    .ps2_clk(ps2_clk),
    .ps2_data(ps2_data),
    .flag(flag),
    .data(data)
  );
  
  decode decode_dut(
    .clk(clk_1M),
    .rst_n(rst_n),
    .flag(flag),
    .data(data),
    .data_n(data_n)
  );
  
  music music_dut(
    .clk(clk_1M),
    .rst_n(rst_n),
    .data_n(data_n),
    .beep(beep)
  );
  
  vga vga_dut(
    .clk(clk),
    .rst_n(rst_n),
    .hs(hs),
    .vs(vs),
    .r_g_b(r_g_b),
    .data_n(data_n)
  );
endmodule 

蜂鳴器music模塊代碼:

module music(clk, rst_n, data_n, beep); 端口列表


  input clk;
  input rst_n;
  input [7:0] data_n;  //輸入的鍵值
  output reg beep;     //蜂鳴器
  
  reg [10:0] music_data;
  wire [10:0] data;


  always @ (posedge clk)
    if(!rst_n)
      begin
        music_data <= 0;
      end
    else
      case (data_n)
        1  :  music_data <= 478;  //蜂鳴器的高音1
        2  :  music_data <= 425;  //蜂鳴器的高音2
        3  :  music_data <= 379;  //蜂鳴器的高音3
        4  :  music_data <= 358;  //蜂鳴器的高音4
        
        5  :  music_data <= 319;  //蜂鳴器的高音5
        6  :  music_data <= 284;  //蜂鳴器的高音6
        7  :  music_data <= 253;  //蜂鳴器的高音7
        default: music_data <= 0;
      endcase
  
  
  reg [20:0] count, cnt;


  always @ (posedge clk)
    if(!rst_n && !data_n)
      begin
        count <= 0;
      end
    else
      if(count < 250_000 - 1)
        begin
          count <= count + 1;
        end
      else
        begin
          count <= 0;
        end
  
  //計(jì)數(shù)0.25S的時(shí)間
  assign data = (count == 250_000 - 1) ? music_data : data;
   
  always @ (posedge clk)
    if(!rst_n)
      begin
        cnt <= 1;
        beep <= 0;
      end
    else
      if(data == 0)    //控制蜂鳴器不響
        begin
          cnt <= 1;
          beep <= 0;
        end
      else if(cnt < data)    //計(jì)數(shù)對(duì)應(yīng)的頻率
        begin
          cnt <= cnt + 1;
        end
      else
        begin
          cnt <= 1;     //蜂鳴器響
          beep <= ~beep;
        end






endmodule 

frenp模塊代碼:

module frenp(clk,rst_n,clk_1M);


  input clk;
  input rst_n;
  
  output reg clk_1M;
  
  reg [4:0] count;
  
  always @(posedge clk or negedge rst_n)
    if(!rst_n)
      begin
        count <= 5'd0;
        clk_1M <= 1'b1;
      end
    else
      begin
        if(count == 50_000_000 / 1000_000 / 2 - 1)
          begin
            count <= 5'd0;
            clk_1M <= ~clk_1M;
          end
        else
          begin
            count <= count + 1'b1;
          end
      end


endmodule
VGA模塊代碼:
module vga(
      clk,
      rst_n,
      hs,
      vs,
      r_g_b,
      data_n
      );
  input clk;
  input rst_n;
  input [7:0] data_n;


  output reg hs;
  output reg vs;
  output reg [7:0]r_g_b;


  reg [10:0] count_hs;  //列計(jì)數(shù)
  reg [10:0] count_vs; //行計(jì)數(shù)
  parameter h_a=96,h_b=48,h_c=640,h_d=16,h_e=800,
         v_a=2,v_b=33,v_c=480,v_d=10,v_e=525;




  reg clk_25M;
  always @ (posedge clk)
    if(!rst_n)
      clk_25M <= 1;
    else
      clk_25M <= ~ clk_25M;
  /*================列掃描=================*/


  always@(posedge clk_25M or negedge rst_n )
    begin
      if(!rst_n)
        begin
        count_hs<=0;
        end 
      else
        begin
          if(count_hs==h_e)
            count_hs<=0;
          else
            count_hs<=count_hs+11'd1;
        end 
    end 
  /*================行掃描=================*/
  always@(posedge clk_25M or negedge rst_n )
    begin
      if(!rst_n)
        begin
      count_vs<=0;
        end 
      else
        begin
          if(count_vs==v_e)
            count_vs<=0;
          else
            begin
              if(count_hs==h_e)
                count_vs<=count_vs+11'd1;
              else
                count_vs<=count_vs;
            end
        end 
    end 
  /*================列同步=================*/
  always@(posedge clk_25M or negedge rst_n )
    begin
      if(!rst_n)
        begin
        hs<=1;
        end 
      else
        begin
          if(count_hs>=h_a)
            hs<=1;
          else
            hs<=0;  
        end 
    end 
  /*================行同步=================*/
  always@(posedge clk_25M or negedge rst_n )
    begin
      if(!rst_n)
        begin
        vs<=1;
        end 
      else
        begin
          if(count_vs>=v_a)
            vs<=1;
          else
            vs<=0;
        end 
    end 
    /*=============有效區(qū)域顯示====================*/
  reg yes;
  always@(posedge clk_25M or negedge rst_n)
    begin
      if(!rst_n)
        begin
          yes <= 0;
        end 
      else
        begin
          if((count_hs>h_a+h_b)&&(count_hsv_a+v_b)&&(count_vs 100 )
          flag <= 1;   
        else if ((count_hs - (144 + 30 * 1)) <= 30  && count_vs < 400 && count_vs > 100 )
          flag <= 0;   // 黑
        else if ((count_hs - (144 + 30 * 2)) <= 30  && count_vs < 400 && count_vs > 100 )
          flag <= 2;     
        else if ((count_hs - (144 + 30 * 3)) <= 30  && count_vs < 400 && count_vs > 100 )
          flag <= 0; 
        else if ((count_hs - (144 + 30 * 4)) <= 30  && count_vs < 400 && count_vs > 100 )
          flag <= 3;   
        else if ((count_hs - (145 + 30 * 5)) <= 4  && count_vs > 100 )
          flag <= 0;   
      
        else if ((count_hs - (149 + 30 * 5)) <= 30  && count_vs < 400 && count_vs > 100 )
          flag <= 4;   // 白
        else if ((count_hs - (149 + 30 * 6)) <= 30  && count_vs < 400 && count_vs > 100 )
          flag <= 0;   // 黑
        else if ((count_hs - (149 + 30 * 7)) <= 30  && count_vs < 400 && count_vs > 100 )
          flag <= 5;     
        else if ((count_hs - (149 + 30 * 8)) <= 30  && count_vs < 400 && count_vs > 100 )
          flag <= 0; 
        else if ((count_hs - (149 + 30 * 9)) <= 30  && count_vs < 400 && count_vs > 100 )
          flag <= 6;   
        else if ((count_hs - (149 + 30 * 10)) <= 30  && count_vs < 400 && count_vs > 100 )
          flag <= 0;  
        else if ((count_hs - (149 + 30 * 11)) <= 30  && count_vs < 400 && count_vs > 100 )
          flag <= 7;     
        else if ((count_hs - (150 + 30 * 12))  <= 4  && count_vs > 100 )
          flag <= 0;  
        
        
        else if (count_hs < 186 && count_vs >= 400)
            flag <= 1; 
        else if (count_hs < 190 && count_vs >= 400)
            flag <= 0; 
        else if (count_hs < 234 + 12 && count_vs >= 400)
            flag <= 2;  
        else if (count_hs < 250 && count_vs >= 400)
            flag <= 0;   
        else if (count_hs < 295 && count_vs >= 400)
            flag <= 3;  
        
        
        else if (count_hs < 329 + 12 && count_vs >= 400)
            flag <= 4; 
        else if (count_hs < 329 + 16 && count_vs >= 400)
            flag <= 0;  
        else if (count_hs < 389+12 && count_vs >= 400)
            flag <= 5;   
        else if (count_hs < 389 + 16 && count_vs >= 400)
            flag <= 0;  
        else if (count_hs < 449 + 12   && count_vs >= 400)
            flag <= 6; 
        else if (count_hs < 449 + 16&& count_vs >= 400)
            flag <= 0; 
        else if (count_hs < 510 && count_vs >= 400)
            flag <= 7; 
        else
          flag <= 8; ;
        
      end
    else
      flag<=0;


  reg [1:0] state;
    
  always @ (posedge clk)
    if(!rst_n)
      begin
        state <= 0;
        r_g_b<=8'b000_000_00;
      end
    else 
      if(data_n)
        begin
          if(flag == data_n)
            r_g_b<=8'b111_100_11;
          else if(flag != data_n && flag !=8 && flag !=0)
            r_g_b<=8'b111_111_111;
          else if (flag == 0)
            r_g_b<=8'b000_000_000;
          else if(flag == 8)
            r_g_b<=8'b000_111_00;
        end
      else
        begin
          if(flag !=8 && flag !=0)
            r_g_b<=8'b111_111_111;
          else if (flag == 0)
            r_g_b<=8'b000_000_000;
          else if(flag == 8)
            r_g_b<=8'b000_111_00;
            
        end
        
endmodule
ps_2rec模塊代碼:
module ps2_rec(clk,rst_n,ps2_clk,ps2_data,flag,data);


  input clk;
  input rst_n;
  input ps2_clk;
  input ps2_data;
  
  output reg flag;
  output  [7:0] data;
  
  wire  nege_dge;
  
  reg  [1:0] signle_s;
  always @ (posedge clk or negedge rst_n)
    if(!rst_n)
      begin
        signle_s <= 2'b11;
      end
    else
      begin
        signle_s[0] <= ps2_clk;
        signle_s[1] <= signle_s[0];
      end
  
  assign nege_dge = ~signle_s[0] && signle_s[1]; 


  
  reg [3:0] count;
  reg [10:0] temp ;
  
  assign data = temp[8:1];
  
  always @  (posedge clk or negedge rst_n)
    if(!rst_n)
      begin
        count <= 4'd0;
        flag <= 1'b0;
        temp <= 11'd0;
      end
    else
      begin
        if(nege_dge && count < 11)
          begin
            count <= count + 1'd1;
            temp[count] <= ps2_data;
          end
        else
          begin
            if(count == 11)
              begin
                count <= 4'd0;
                flag <= 1'b1;
              end
            else
              begin
                flag <= 1'b0;
              end
          end
      end
??????
endmodule 
代碼驗(yàn)證正確無(wú)誤,筆者在這邊就不過(guò)多的驗(yàn)證,源工程已提供給各位大俠,如有需要,可以自行獲取,供大家參考學(xué)習(xí)。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • FPGA
    +關(guān)注

    關(guān)注

    1630

    文章

    21783

    瀏覽量

    605025
  • 三極管
    +關(guān)注

    關(guān)注

    143

    文章

    3622

    瀏覽量

    122220
  • 電子琴
    +關(guān)注

    關(guān)注

    4

    文章

    153

    瀏覽量

    30601
  • 無(wú)源蜂鳴器
    +關(guān)注

    關(guān)注

    0

    文章

    42

    瀏覽量

    11173

原文標(biāo)題:源碼系列:基于FPGA的電子琴設(shè)計(jì)(附源工程)

文章出處:【微信號(hào):HXSLH1010101010,微信公眾號(hào):FPGA技術(shù)江湖】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    fpga電子琴,可揚(yáng)聲器雙鍵和弦,可蜂鳴器和揚(yáng)聲器切換,可自動(dòng)演奏

    元器件揚(yáng)聲器電子琴樂(lè)器/玩具喇叭/蜂鳴器
    游泳的鳥(niǎo)兒
    發(fā)布于 :2022年08月15日 16:36:29

    基于FPGA電子琴設(shè)計(jì)

    基于FPGA電子琴設(shè)計(jì)代碼誰(shuí)有嗎?想要一份學(xué)習(xí)一下
    發(fā)表于 05-19 23:25

    【Artix-7 50T FPGA申請(qǐng)】基于Artix-7的智能家居

    ,在此基礎(chǔ)上設(shè)計(jì)過(guò)基于FPGA電子琴。同時(shí)此前在電子發(fā)燒友成功申請(qǐng)獲得過(guò)云路由和樹(shù)莓派的試用,認(rèn)真對(duì)待每次試用機(jī)會(huì),認(rèn)真撰寫(xiě)心得體會(huì)。如果獲得Artix-7 FPGA的試用機(jī)會(huì),試用
    發(fā)表于 11-10 12:34

    基于FPGA電子琴設(shè)計(jì)

    基于FPGA電子琴設(shè)計(jì)
    發(fā)表于 12-11 09:46

    電子琴設(shè)計(jì)

    電子琴設(shè)計(jì)
    發(fā)表于 08-19 12:01 ?251次下載

    基于FPGA的PS2鍵盤(pán)鼠標(biāo)控制電子琴

    基于 FPGA的PS2鍵盤(pán)鼠標(biāo)控制電子琴論文
    發(fā)表于 10-29 17:18 ?31次下載

    基于FPGA電子琴設(shè)計(jì) 畢業(yè)論文分享

    基于FPGA電子琴設(shè)計(jì)畢業(yè)時(shí)的論文
    發(fā)表于 04-29 16:20 ?34次下載

    簡(jiǎn)易電子琴設(shè)計(jì)及FPGA功能驗(yàn)證

    FPGA簡(jiǎn)易電子琴設(shè)計(jì)具體的模塊分析和源程序,
    發(fā)表于 02-16 16:32 ?31次下載

    基于FPGA電子琴設(shè)計(jì)與實(shí)現(xiàn)

    樂(lè)曲都是由一連串的音符組成,按照樂(lè)曲的樂(lè)譜依次輸出這些音符所對(duì)應(yīng)的頻率,就可以在揚(yáng)聲器上連續(xù)地發(fā)出各個(gè)音符的音調(diào)。為了準(zhǔn)確地演奏出一首樂(lè)曲,僅僅讓揚(yáng)聲器能夠發(fā)出聲音是遠(yuǎn)遠(yuǎn)不夠的,還必須準(zhǔn)確地控制樂(lè)曲的節(jié)奏,即每個(gè)音符的持續(xù)時(shí)間。由此可見(jiàn),樂(lè)曲中每個(gè)音符的發(fā)音頻率以及音符持續(xù)的時(shí)間是樂(lè)曲能夠連續(xù)演奏的兩個(gè)關(guān)鍵因素。
    發(fā)表于 11-28 15:09 ?2.3w次閱讀
    基于<b class='flag-5'>FPGA</b>的<b class='flag-5'>電子琴</b>設(shè)計(jì)與實(shí)現(xiàn)

    基于fpga電子琴電路圖分析

    我們生活在一個(gè)信息高速發(fā)達(dá)的時(shí)代,各種各樣電子產(chǎn)品層出不窮。對(duì)于廣大老百姓來(lái)說(shuō),電子琴可以說(shuō)已經(jīng)不再是什么“新鮮玩意”了,它現(xiàn)在作為一種休閑和娛樂(lè)的產(chǎn)品早就推出市面,面向百姓,進(jìn)入了我們的生活。作為
    發(fā)表于 11-29 08:09 ?8935次閱讀
    基于<b class='flag-5'>fpga</b><b class='flag-5'>電子琴</b>電路圖分析

    使用FPGA設(shè)計(jì)電子琴的工程文件和九個(gè)數(shù)電實(shí)驗(yàn)報(bào)告資料合集免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是使用FPGA設(shè)計(jì)電子琴的工程文件和九個(gè)數(shù)電實(shí)驗(yàn)報(bào)告資料合集免費(fèi)下載包括了:  TTL和CMOS集成門(mén)電路參數(shù)測(cè)試,  譯碼器、編碼器的應(yīng)用 ,  數(shù)據(jù)選擇器
    發(fā)表于 06-03 08:00 ?5次下載
    使用<b class='flag-5'>FPGA</b>設(shè)計(jì)<b class='flag-5'>電子琴</b>的工程文件和九個(gè)數(shù)電實(shí)驗(yàn)報(bào)告資料合集免費(fèi)下載

    使用FPGA設(shè)計(jì)電子琴的資料合集免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是使用FPGA設(shè)計(jì)電子琴的資料合集免費(fèi)下載。
    發(fā)表于 05-29 08:00 ?4次下載
    使用<b class='flag-5'>FPGA</b>設(shè)計(jì)<b class='flag-5'>電子琴</b>的資料合集免費(fèi)下載

    使用FPGA實(shí)現(xiàn)電子琴設(shè)計(jì)的論文

    介紹了基于FPGA電子琴的工作原理和設(shè)計(jì)過(guò)程。用Altera 公司的EP2C8Q208C8N 芯片為核心器件,通過(guò)運(yùn)用硬件編程語(yǔ)言VHDL 描述,在Quartus II 平臺(tái)上,實(shí)現(xiàn)了電子琴
    發(fā)表于 07-24 16:51 ?18次下載
    使用<b class='flag-5'>FPGA</b>實(shí)現(xiàn)<b class='flag-5'>電子琴</b>設(shè)計(jì)的論文

    基于FPGA的簡(jiǎn)易電子琴的實(shí)現(xiàn)

    本系統(tǒng)是采用EDA技術(shù)設(shè)計(jì)的一個(gè)簡(jiǎn)易的八音符電子琴,該系統(tǒng)基于計(jì)算機(jī)中時(shí)鐘分頻器的原理,采用自頂向下的設(shè)計(jì)方法來(lái)實(shí)現(xiàn),它可以通過(guò)按鍵輸入來(lái)控制音響。多功能電子琴的設(shè)計(jì)是在原有普通電子琴的基礎(chǔ)上
    發(fā)表于 04-28 11:16 ?45次下載

    基于FPGA電子琴設(shè)計(jì)

    電子發(fā)燒友網(wǎng)站提供《基于FPGA電子琴設(shè)計(jì).pdf》資料免費(fèi)下載
    發(fā)表于 10-10 09:40 ?11次下載
    基于<b class='flag-5'>FPGA</b>的<b class='flag-5'>電子琴</b>設(shè)計(jì)