設(shè)計(jì)原理
在之前也出了幾篇源碼系列,基本上都是一些小設(shè)計(jì),源碼系列主要就會想通過實(shí)操訓(xùn)練讓各位學(xué)習(xí)者,尤其是初學(xué)者去更好的理解學(xué)習(xí)FPGA,或者給要的學(xué)生提供一些源碼,之前設(shè)計(jì)過各個芯片的配置等,之后筆者會通過簡單的例子來讓大家去系統(tǒng)的學(xué)習(xí)和認(rèn)識FPGA。本次的電子琴設(shè)計(jì)也算是一次簡單的各個模塊的聯(lián)系調(diào)用的一個過程,也可以幫助各位去加深理解,多動手,熟練掌握會有意想不到的效果。
本次的設(shè)計(jì)主要是通過控制ps2鍵盤來使蜂鳴器發(fā)出哆來咪法嗦拉西7種音,音符又有高低音之分等,本次只選擇發(fā)出高音的多來咪發(fā)嗦啦西。本設(shè)計(jì)中還用到了VGA的設(shè)計(jì),通過VGA來在顯示屏上畫出如下圖的黑白的電子琴鍵:
當(dāng)按下多來咪發(fā)嗦啦西時,對應(yīng)的鍵值變顏色表示按下,不變色表示不按下,顏色自己可以調(diào)節(jié),但是琴的按鍵必須為黑白色來顯示出來。
當(dāng)按下按鍵的時候,蜂鳴器來鳴響對應(yīng)時間的音符,本設(shè)計(jì)蜂鳴器響的時間為0.25S一個音符持續(xù)的時間。
本次設(shè)計(jì)用到的PS2和VGA的設(shè)計(jì)原理筆者在這里就不過多的介紹了,不明白的可以翻看前面發(fā)的文檔內(nèi)容。
在本設(shè)計(jì)中介紹蜂鳴器的使用和各音符發(fā)聲的頻率大小。本設(shè)計(jì)用的是無源蜂鳴器,原理圖如下:
由于FPGA的驅(qū)動能力不夠,我們添加了一個三極管來驅(qū)動這個無源蜂鳴器,而無源蜂鳴器的主要特點(diǎn)是內(nèi)部不帶振蕩源,所以如果使用直流信號是無法使無源蜂鳴器鳴叫的,必須使用方波去驅(qū)動它。
現(xiàn)在我們明白了,只要往蜂鳴器發(fā)送一定頻率的方波,就可以使得蜂鳴器發(fā)出聲音,然后現(xiàn)在的問題是,我們究竟要往蜂鳴器發(fā)送什么頻率的方波信號呢?具體的頻率可以查看下圖:
現(xiàn)在我們知道如何讓蜂鳴器響起,又知道發(fā)送什么頻率可以讓蜂鳴器響起什么的聲音,所以我相信我們已經(jīng)有能力讓蜂鳴器響起我們需要的音樂了。
設(shè)計(jì)架構(gòu)
設(shè)計(jì)架構(gòu)圖:
在這里沒有去畫設(shè)計(jì)框架圖,就直接給大家展示RTL級視圖,各位也可以通過RTL級視圖看到設(shè)計(jì)的總框架。
設(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的時間 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ù)對應(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 endmoduleVGA模塊代碼:
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_hsps_2rec模塊代碼:v_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
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)證正確無誤,筆者在這邊就不過多的驗(yàn)證,源工程已提供給各位大俠,如有需要,可以自行獲取,供大家參考學(xué)習(xí)。
-
FPGA
+關(guān)注
關(guān)注
1640文章
21896瀏覽量
611074 -
三極管
+關(guān)注
關(guān)注
144文章
3644瀏覽量
123467 -
電子琴
+關(guān)注
關(guān)注
4文章
154瀏覽量
30936 -
無源蜂鳴器
+關(guān)注
關(guān)注
0文章
42瀏覽量
11298
原文標(biāo)題:源碼系列:基于FPGA的電子琴設(shè)計(jì)(附源工程)
文章出處:【微信號:HXSLH1010101010,微信公眾號:FPGA技術(shù)江湖】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦

fpga電子琴,可揚(yáng)聲器雙鍵和弦,可蜂鳴器和揚(yáng)聲器切換,可自動演奏
【Artix-7 50T FPGA申請】基于Artix-7的智能家居
基于FPGA的電子琴設(shè)計(jì)與實(shí)現(xiàn)

基于fpga電子琴電路圖分析

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

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

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

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

評論