Xilinx FPGA:vivado实现超声波测距

项目要求:

超声波模块测出的距离显示在数码管上

产生时钟使能信号的模块:

`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信号的模块

`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信号高脉冲计时

`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

译码器模块:

`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

数码管模块

`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

顶层

`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

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值