本(běn)文(wén)为(wèi)明(míng)德揚原創及(jí)录(lù)用(yòng)文(wén)章(zhāng),轉(zhuǎn)载請注明(míng)出(chū)处!
1.1 總(zǒng)體(tǐ)設計(jì)
1.1.1 概述
学習了(le)明(míng)德揚至(zhì)簡設計(jì)法和(hé)明(míng)德揚設計(jì)規範,本(běn)人(rén)用(yòng)FPGA設計(jì)了(le)一(yī)个(gè)测距系(xì)統。該系(xì)統采用(yòng)超聲波(bō)進(jìn)行测量(liàng)距離再在(zài)數碼管(guǎn)上(shàng)顯示。在(zài)本(běn)案(àn)例的(de)設計(jì)过(guò)程中(zhōng)包(bāo)括了(le)超聲波(bō)的(de)驅動(dòng)、三(sān)線(xiàn)式數碼管(guǎn)顯示等技術(shù)。經(jīng)过(guò)逐步改進(jìn)、調試等一(yī)系(xì)列工作後(hòu),最(zuì)終(zhōng)完成(chéng)了(le)此(cǐ)設計(jì),并進(jìn)行上(shàng)板验(yàn)證,下(xià)面(miàn)将完整的(de)設計(jì)記(jì)录(lù)與(yǔ)大家(jiā)分(fēn)享。
1.1.2 設計(jì)目标(biāo)
此(cǐ)系(xì)統将实时(shí)顯示前(qián)方(fāng)障礙與(yǔ)裝(zhuāng)置之間(jiān)的(de)距離。
1.1.3 系(xì)統結構框图(tú)
系(xì)統結構框图(tú)如(rú)下(xià)所(suǒ)示:
1.1.4 模块(kuài)功能(néng)
hc_sr04模块(kuài)实現(xiàn)功能(néng):
該模块(kuài)通(tòng)过(guò)控制觸發(fà)信(xìn)号(hào)trig(10us的(de)TTL)使內(nèi)部(bù)循环(huán)發(fà)出(chū)8个(gè)40KHZ脈沖即驅動(dòng)超聲波(bō),接收(shōu)回(huí)響信(xìn)号(hào)echo,通(tòng)过(guò)echo得到(dào)距離。
顯示模块(kuài)实現(xiàn)功能(néng):
該模块(kuài)完成(chéng)了(le)对(duì)所(suǒ)测距離通(tòng)过(guò)數碼管(guǎn)对(duì)其顯示。
1.1.5頂层信(xìn)号(hào)
1.1.6頂层代(dài)碼
module top(
clk ,
rst_n ,
echo ,
trig ,
sel,
seg
);
input clk ;
input rst_n ;
input echo ;
output trig ;
wire [3:0] s_g ;
wire [3:0] s_s ;
wire [3:0] s_b ;
wire [3:0] s_q ;
output [7:0] sel ;
output [7:0] seg ;
hc_sr04 hc_sr04_1(
.clk (clk) ,
.rst_n (rst_n) ,
.echo (echo) ,
.trig (trig) ,
.s_g (s_g ),
.s_s (s_s ),
.s_b (s_b ),
.s_q (s_q )
);
seg_disp u_seg_disp(
.clk (clk ),
.rst_n (rst_n),
.segment_data({s_q,s_b,s_s,s_g}),
.segment (seg ),
.seg_sel (sel )
);
endmodule
1.2 hc_sr04模块(kuài)設計(jì)
1.2.1 接口(kǒu)信(xìn)号(hào)
1.2.2 設計(jì)思(sī)路(lù)
我(wǒ)们(men)只(zhī)需要(yào)提(tí)供一(yī)个(gè)短(duǎn)期(qī)的(de)10uS脈沖觸發(fà)信(xìn)号(hào)trig,該模块(kuài)內(nèi)部(bù)将發(fà)出(chū)8个(gè)40kHz周期(qī)電(diàn)平并檢测回(huí)波(bō),一(yī)旦檢测到(dào)有(yǒu)回(huí)波(bō)信(xìn)号(hào)則輸出(chū)回(huí)響信(xìn)号(hào),回(huí)響信(xìn)号(hào)echo是(shì)一(yī)个(gè)脈沖的(de)宽(kuān)度(dù)成(chéng)正(zhèng)比的(de)距離變(biàn)量(liàng),可(kě)通(tòng)过(guò)發(fà)射信(xìn)号(hào)到(dào)收(shōu)到(dào)的(de)回(huí)響信(xìn)号(hào)时(shí)間(jiān)間(jiān)隔可(kě)以(yǐ)計(jì)算得到(dào)距離。建議测量(liàng)周期(qī)为(wèi)60ms以(yǐ)上(shàng),以(yǐ)防止發(fà)射信(xìn)号(hào)对(duì)回(huí)響信(xìn)号(hào)的(de)影響,这(zhè)里(lǐ)我(wǒ)们(men)采用(yòng)的(de)是(shì)1s测量(liàng)一(yī)次(cì)。
时(shí)鐘(zhōng)計(jì)數器cnt0:用(yòng)于(yú)計(jì)算 1 秒(miǎo)的(de)时(shí)鐘(zhōng)个(gè)數,加一(yī)条(tiáo)件(jiàn)为(wèi)1,表(biǎo)示一(yī)直(zhí)計(jì)數;結束(shù)条(tiáo)件(jiàn)为(wèi)數到(dào) TIME_1S ,表(biǎo)示數到(dào) 1 秒(miǎo)就(jiù)清(qīng)零(líng)。
距離計(jì)數器 h_cnt:用(yòng)于(yú)計(jì)算flag为(wèi)高(gāo)電(diàn)平的(de)宽(kuān)度(dù)的(de)时(shí)間(jiān),如(rú)果(guǒ)flag为(wèi)1,h_cnt就(jiù)加一(yī);每完成(chéng)1秒(miǎo)計(jì)數後(hòu)h_cnt就(jiù)變(biàn)为(wèi)0,此(cǐ)外(wài)h_cnt等于(yú)h_cnt。
模块(kuài)时(shí)序图(tú)
1.2.3 參考代(dài)碼
module hc_sr04( clk , rst_n , echo , trig , s_g , s_s , s_b , s_q ); parameter DATA_W = 14 ; parameter TIME_1S = 50_000_000; input clk ; input rst_n ; input echo ; output trig ; output[ 3:0] s_g ; output[ 3:0] s_s ; output[ 3:0] s_b ; output[ 3:0] s_q ; wire trig ; reg [ 3:0] s_g ; reg [ 3:0] s_s ; reg [ 3:0] s_b ; reg [ 3:0] s_q ; reg [DATA_W-1:0] distance; reg [25:0] cnt0 ; reg [20:0] h_cnt ; reg echo_2 ; reg echo_1 ; wire add_cnt0; wire end_cnt0; wire flag_h ; wire flag_l ; always @(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt0 <= 0; end else if(add_cnt0)begin if(end_cnt0) cnt0 <= 0; else cnt0 <= cnt0 + 1'b1; end end assign add_cnt0 = 1; assign end_cnt0 = add_cnt0 && cnt0 == TIME_1S - 1; assign trig = (cnt0>=500&&cnt0<1000)?1:0; always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin echo_1 <= 0; echo_2 <= 0; end else begin echo_1 <= echo ; echo_2 <= echo_1; end end always @(posedge clk or negedge rst_n)begin if(!rst_n)begin h_cnt <= 0; end else if(add_h_cnt)begin if(end_h_cnt) h_cnt <= 0; else h_cnt <= h_cnt + 1; end else if(end_cnt0)begin h_cnt <= 0; end end assign add_h_cnt = echo_2; assign end_h_cnt = 0 ; always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin distance <= 0; end else if(add_cnt0 && cnt0 == 45_000_000-1)begin distance <= h_cnt*34/10000; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin s_g <= 0; end else begin s_g <= distance%10; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin s_s <= 0; end else begin s_s <= (distance/10)%10; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin s_b <= 0; end else begin s_b <= (distance/100)%10; end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin s_q <= 0; end else begin s_q <= (distance/1000)%10; end end endmodule
1.3 顯示模块(kuài)設計(jì)
1.3.1接口(kǒu)信(xìn)号(hào)
1.3.2設計(jì)思(sī)路(lù)
該模块(kuài)对(duì)數碼管(guǎn)的(de)位選信(xìn)号(hào)sel每隔1ms的(de)时(shí)間(jiān)移位一(yī)次(cì),也(yě)就(jiù)是(shì)1ms循环(huán)亮(liàng)一(yī)个(gè)燈(dēng),由(yóu)于(yú)1ms的(de)頻率肉(ròu)眼(yǎn)观察不(bù)出(chū),我(wǒ)们(men)看(kàn)到(dào)的(de)就(jiù)是(shì)4个(gè)燈(dēng)全(quán)亮(liàng)。
对(duì)輸入(rù)距離distance進(jìn)行求餘处理,得到(dào)每一(yī)位的(de)數據(jù),通(tòng)过(guò)case語(yǔ)句(jù),讓每一(yī)位數據(jù)形成(chéng)段(duàn)選信(xìn)号(hào),通(tòng)过(guò)位選信(xìn)号(hào)的(de)控制顯示在(zài)对(duì)應(yìng)的(de)數碼管(guǎn)上(shàng)。
1.3.3參考代(dài)碼
module seg_disp( clk , rst_n , segment_data, segment , seg_sel ); parameter ZERO = 8'b1100_0000 ; parameter ONE = 8'b1111_1001 ; parameter TWO = 8'b1010_0100 ; parameter THREE = 8'b1011_0000 ; parameter FOUR = 8'b1001_1001 ; parameter FIVE = 8'b1001_0010 ; parameter SIX = 8'b1000_0010 ; parameter SEVEN = 8'b1111_1000 ; parameter EIGHT = 8'b1000_0000 ; parameter NINE = 8'b1001_0000 ; input clk ; input rst_n ; input [31:0] segment_data ; output [7:0 ] segment ; output [7:0 ] seg_sel ; reg [7:0 ] segment ; reg [7:0 ] seg_sel ; reg [10:0] delay ; reg [3:0 ] delay_time ; wire add_delay_time ; wire end_delay_time ; wire add_delay ; wire end_delay ; wire [3:0 ] segment_tmp ; always @(posedge clk or negedge rst_n) begin if (rst_n==0) begin delay <= 0; end else if(add_delay) begin if(end_delay) delay <= 0; else delay <= delay+1 ; end end assign add_delay = 1; assign end_delay = add_delay && delay == 2000-1 ; always @(posedge clk or negedge rst_n) begin if (rst_n==0) begin delay_time <= 0; end else if(add_delay_time) begin if(end_delay_time) delay_time <= 0; else delay_time <= delay_time+1 ; end end assign add_delay_time = end_delay; assign end_delay_time = add_delay_time && delay_time == 8-1 ; assign segment_tmp = segment_data[(1+delay_time)*4-1 -:4]; always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin segment <= ZERO; end else begin case(segment_tmp) 4'd0:segment <= ZERO; 4'd1:segment <= ONE ; 4'd2:segment <= TWO ; 4'd3:segment <= THREE; 4'd4:segment <= FOUR ; 4'd5:segment <= FIVE ; 4'd6:segment <= SIX ; 4'd7:segment <= SEVEN; 4'd8:segment <= EIGHT; 4'd9:segment <= NINE ; default:begin segment <= segment; end endcase end end always @(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin seg_sel <= 8'b1111_1111; end else begin seg_sel <= ~(8'b1<<delay_time); end end endmodule
1.4 效果(guǒ)和(hé)總(zǒng)結
上(shàng)板验(yàn)證效果(guǒ)
在(zài)这(zhè)个(gè)設計(jì)中(zhōng),使用(yòng)明(míng)德揚的(de)至(zhì)簡設計(jì)法,讓我(wǒ)的(de)思(sī)路(lù)非(fēi)常清(qīng)晰,邏輯非(fēi)常嚴谨,虽然沒(méi)有(yǒu)做到(dào)一(yī)遍(biàn)成(chéng)功,但在(zài)調試过(guò)程中(zhōng)我(wǒ)都比較快(kuài)速的(de)找(zhǎo)到(dào)問(wèn)題(tí),并快(kuài)速解(jiě)決。对(duì)于(yú)学習FPGA的(de)同(tóng)学,我(wǒ)非(fēi)常推薦使用(yòng)明(míng)德揚至(zhì)簡設計(jì)法和(hé)明(míng)德揚模块(kuài)進(jìn)行学習和(hé)設計(jì)。
教学視頻和(hé)工程源代(dài)碼請移步明(míng)德揚論壇学習!
感(gǎn)興趣的(de)朋友也(yě)可(kě)以(yǐ)訪問(wèn)明(míng)德揚論壇(www.fpgabbs.cn)進(jìn)行FPGA相關(guān)工程設計(jì)学習,也(yě)欢迎大家(jiā)在(zài)評論與(yǔ)我(wǒ)進(jìn)行讨論!
也(yě)可(kě)以(yǐ)看(kàn)一(yī)下(xià)我(wǒ)们(men)往期(qī)的(de)文(wén)章(zhāng):
《基于(yú)FPGA的(de)密碼鎖設計(jì)》
《波(bō)形相位頻率可(kě)調DDS信(xìn)号(hào)發(fà)生(shēng)器》
《基于(yú)FPGA的(de)曼徹斯特(tè)編碼解(jiě)碼設計(jì)》
《基于(yú)FPGA的(de)出(chū)租車計(jì)費系(xì)統》
《數電(diàn)基礎與(yǔ)Verilog設計(jì)》《基于(yú)FPGA的(de)頻率、電(diàn)壓测量(liàng)》
《基于(yú)FPGA的(de)漢明(míng)碼編碼解(jiě)碼設計(jì)》
《關(guān)于(yú)鎖存器問(wèn)題(tí)的(de)讨論》
《阻塞賦值與(yǔ)非(fēi)阻塞賦值》
《參數例化(huà)时(shí)自(zì)動(dòng)計(jì)算位宽(kuān)的(de)解(jiě)決辦(bàn)法》
1.15公司簡介
明(míng)德揚是(shì)一(yī)家(jiā)專注于(yú)FPGA領域的(de)專業性(xìng)公司,公司主(zhǔ)要(yào)業务包(bāo)括開(kāi)發(fà)板、教育培訓、項目承接、人(rén)才服(fú)务等多(duō)个(gè)方(fāng)向(xiàng)。
點(diǎn)撥開(kāi)發(fà)板——学習FPGA的(de)入(rù)門(mén)之選。
MP801開(kāi)發(fà)板——千(qiān)兆(zhào)网(wǎng)、ADDA、大容量(liàng)SDRAM等,学習和(hé)項目需求一(yī)步到(dào)位。
网(wǎng)絡培訓班——不(bù)管(guǎn)时(shí)間(jiān)和(hé)空間(jiān),明(míng)德揚随时(shí)在(zài)你身(shēn)邊(biān),助你快(kuài)速学習FPGA。
周末(mò)培訓班——明(míng)天(tiān)的(de)你会(huì)感(gǎn)激現(xiàn)在(zài)的(de)努力進(jìn)取(qǔ),升(shēng)職加薪明(míng)德揚来(lái)助你。
就(jiù)業培訓班——七(qī)大企業級項目实訓,獲得豐富的(de)項目經(jīng)验(yàn),高(gāo)薪就(jiù)業。
專題(tí)課程——高(gāo)手(shǒu)修煉課:提(tí)升(shēng)設計(jì)能(néng)力;
实用(yòng)調試技巧課:提(tí)升(shēng)定(dìng)位和(hé)解(jiě)決問(wèn)題(tí)能(néng)力;
FIFO架構設計(jì)課:助你快(kuài)速成(chéng)为(wèi)架構設計(jì)师(shī);
时(shí)序約束(shù)、數字(zì)信(xìn)号(hào)处理、PCIE、綜合項目实踐課等你来(lái)選。
項目承接——承接企業FPGA研發(fà)項目。人(rén)才服(fú)务——提(tí)供人(rén)才推薦、人(rén)才代(dài)培、人(rén)才派遣等服(fú)务。








