项目要求:
超声波模块测出的距离显示在数码管上
产生时钟使能信号的模块:
Matlab
`timescale 1ns / 1ps
//产生1us为周期的时钟使能信号
//1us/20ns=50,div_cnt内部计数周期为0~49
module vlg_en(
input sys_clk ,
input rst_n ,
output reg clk_en //clk_en的时钟周期为1us
);
reg [7:0] div_cnt ;
//对输入时钟sys_clk做分频计数,产生1us的时钟使能信号
always @(posedge sys_clk )
if(!rst_n)
div_cnt <= 0 ;
else if ( div_cnt == 50 )
div_cnt <= 0 ;
else
div_cnt <= div_cnt +1 ;
//产生时钟使能信号
always@(posedge sys_clk )
if(!rst_n)
clk_en <= 0 ;
else if ( div_cnt == 49 )
clk_en <= 1 ;
else
clk_en <= 0 ;
endmodule
产生trig信号的模块
Matlab
`timescale 1ns / 1ps
module vlg_trig(
input sys_clk ,
input rst_n ,
input clk_en , //1us为周期的时钟使能信号
output reg trig
);
parameter trig_50000 = 16'd50_000 ;
reg [16:0] trig_cnt ; // T=50ms t=1us 50ms/1us = 50000 位宽是16
//trig_cnt计满50ms
always@(posedge sys_clk)
if(!rst_n)
trig_cnt <= 0 ;
else if ( clk_en == 1 && trig_cnt == trig_50000 -1 )
trig_cnt <= 0 ;
else if ( clk_en == 1 )
trig_cnt <= trig_cnt +1 ;
else
trig_cnt <= trig_cnt ;
//产生保持10us的高脉冲trig信号
always@(posedge sys_clk)
if (!rst_n)
trig <= 0 ;
else if ( trig_cnt > 0 && trig_cnt < 4'd10)
trig <= 1 ;
else
trig <= 0 ;
endmodule
对echo信号高脉冲计时
Matlab
`timescale 1ns / 1ps
module vlg_echo(
input sys_clk ,
input rst_n ,
input clk_en ,
input echo ,
// output reg[15:0] num_max ,
output wire[15:0] distance
);
reg[15:0] num_max ;
reg [1:0] r_echo ;//echo信号的边沿检测
wire pos_echo ;
wire neg_echo ;
reg cnt_en ;
reg [15:0] echo_cnt ;
always@(posedge sys_clk)
if(!rst_n)
r_echo <= 0 ;
else
r_echo <= { r_echo[0],echo} ; // echo 是原始信号 r_echo[0] 是延迟一拍的echo
assign pos_echo = r_echo[0] & ~r_echo[1] ; //这句话中的r_echo[0]是原始信号echo,r_echo[1]是是延迟一拍的echo
assign neg_echo = ~r_echo[0] & r_echo[1] ;
always @(posedge sys_clk)
if(!rst_n)
cnt_en <= 0 ;
else if ( pos_echo ) cnt_en <= 1 ;
else if ( neg_echo ) cnt_en <= 0 ;
else
cnt_en <= cnt_en ;
//对echo信号高脉冲计时,以us为单位
always @(posedge sys_clk )
if(!rst_n)
echo_cnt <= 0 ;
else if ( !cnt_en )
echo_cnt <= 0 ;
else if ( cnt_en )
echo_cnt <= echo_cnt +1 ;
else
echo_cnt <= 0 ;
//对echo_cnt计数最大值进行锁存
always@(posedge sys_clk)
if( !rst_n )
num_max <= 0 ;
else if ( neg_echo )
num_max <= echo_cnt ;
assign distance = num_max * 20 /58 /1000 ;
endmodule
译码器模块:
Matlab
`timescale 1ns / 1ps
module translate(
input [3:0] num ,
output reg[7:0] seg
);
always@(*)
case(num)
4'd0: seg = 8'h3f;
4'd1: seg = 8'h06;
4'd2: seg = 8'h5b;
4'd3: seg = 8'h4f;
4'd4: seg = 8'h66;
4'd5: seg = 8'h6d;
4'd6: seg = 8'h7d;
4'd7: seg = 8'h07;
4'd8: seg = 8'h7f;
4'd9: seg = 8'h6f;
default:;
endcase
endmodule
数码管模块
Matlab
`timescale 1ns / 1ps
module state_SEG(
input sys_clk ,
input rst_n ,
input [15:0] number ,
output wire[3:0] DIG ,
output wire[7:0] SEG
);
parameter MODE =0 ;
reg [3:0] num ;
reg [3:0] dig ;
wire [7:0] seg ;
//例化译码器模块
translate translate1(
. num ( num ) ,
. seg ( seg )
);
//数据提取
wire [3:0] num_ge ;
wire [3:0] num_shi ;
wire [3:0] num_bai ;
wire [3:0] num_qian ;
assign num_ge = number%10 ;
assign num_shi = number/10%10 ;
assign num_bai = number/100%10 ;
assign num_qian = number/1000%10 ;
//状态机
parameter TIME_1ms = 16'd50_00 ;
localparam IDLE = 4'b0000 ;
localparam GE = 4'b0001 ;
localparam SHI = 4'b0010 ;
localparam BAI = 4'b0100 ;
localparam QIAN = 4'b1000 ;
reg [3:0] cur_state ;
reg [3:0] next_state ;
reg [15:0] cnt_1ms ;
always@(posedge sys_clk)
if(!rst_n)
cur_state <= IDLE ;
else
cur_state <= next_state ;
always@(*)
case(cur_state)
IDLE :
begin
next_state = GE ;
end
GE :
begin
if ( cnt_1ms == TIME_1ms -1 )
next_state = SHI ;
else
next_state = cur_state ;
end
SHI :
begin
if ( cnt_1ms == TIME_1ms -1 )
next_state = BAI ;
else
next_state = cur_state ;
end
BAI :
begin
if ( cnt_1ms == TIME_1ms -1 )
next_state = QIAN ;
else
next_state = cur_state ;
end
QIAN :
begin
if ( cnt_1ms == TIME_1ms -1 )
next_state = GE ;
else
next_state = cur_state ;
end
default:;
endcase
always@(posedge sys_clk)
if(!rst_n)begin
cnt_1ms <= 0 ;
dig <= 0 ;
num <= 0 ;
end
else
case(cur_state)
IDLE :
begin
cnt_1ms <= 0 ;
dig <= 0 ;
num <= 0 ;
end
GE :
begin
dig <= 4'b1110 ;
num <= num_ge ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
SHI :
begin
dig <= 4'b1101 ;
num <= num_shi ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
BAI :
begin
dig <= 4'b1011 ;
num <= num_bai ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
QIAN :
begin
dig <= 4'b0111 ;
num <= num_qian ;
if( cnt_1ms == TIME_1ms -1 )
cnt_1ms <= 0 ;
else
cnt_1ms <= cnt_1ms +1 ;
end
default:;
endcase
assign DIG = ( MODE == 0 ) ? dig :~dig ;
assign SEG = ( MODE == 0 ) ? seg :~seg ;
endmodule
顶层
Matlab
`timescale 1ns / 1ps
module vlg_top(
input sys_clk ,
input rst_n ,
input echo ,
output trig ,
output wire[3:0] DIG ,
output wire[7:0] SEG
);
//使能时钟产生模块
wire clk_en ;
vlg_en vlg_en1(
. sys_clk (sys_clk) ,
. rst_n (rst_n ) ,
. clk_en (clk_en ) //clk_en的时钟周期为1us
);
//产生超声波测距模块的触发信号trig
vlg_trig vlg_trig1(
. sys_clk (sys_clk) ,
. rst_n (rst_n ) ,
. clk_en (clk_en ) , //1us为周期的时钟使能信号
. trig (trig )
);
//回响信号echo的高电平时间采集
wire[15:0] distance ;
vlg_echo vlg_echo1(
. sys_clk (sys_clk) ,
. rst_n (rst_n ) ,
. clk_en (clk_en ) ,
. echo (echo ) ,
. distance (distance)
);
//数码管模块
state_SEG state_SEG1(
. sys_clk (sys_clk) ,
. rst_n (rst_n ) ,
. number (distance ) ,
. DIG ( DIG ) ,
. SEG ( SEG )
);
endmodule