文(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)德揚論壇学習!
温(wēn)馨提(tí)示:明(míng)德揚2023推出(chū)了(le)全(quán)新課程——邏輯設計(jì)基本(běn)功修煉課,降低学習FPGA門(mén)檻的(de)同(tóng)时(shí),增加了(le)学習的(de)趣味性(xìng),并組織了(le)考試赢積分(fēn)活動(dòng)
http://www.minyingyiyuan.com/ffkc/415.html
(點(diǎn)擊→了(le)解(jiě)課程詳情(qíng)☝)感(gǎn)興趣請聯系(xì)易老(lǎo)师(shī):13112063618(微信(xìn)同(tóng)步)