Xilinx FPGA:vivado实现超声波测距

项目要求:

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

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

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
相关推荐
DQI-king13 小时前
ZYNQ学习记录FPGA(二)Verilog语言
学习·fpga开发·zynq
9527华安13 小时前
国产安路FPGA纯verilog图像缩放,工程项目解决方案,提供5套TD工程源码和技术支持
fpga开发·verilog·图像缩放·双线性插值·安路fpga
俺不是西瓜太郎´•ﻌ•`16 小时前
实验四:图像灰度处理
fpga开发
GateWorld19 小时前
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析(四)DPHY ECC
fpga开发·mipi csi2
贝塔实验室19 小时前
FPGA 的硬件结构
arm开发·fpga开发·职场和发展·硬件架构·硬件工程·fpga·安全架构
GateWorld1 天前
《深入解析SPI协议及其FPGA高效实现》-- 第三篇:FPGA实现关键技术与优化
fpga开发·开源协议
XMAIPC_Robot1 天前
RK3568/RK3588 KVM系统虚拟化解决方案
网络·fpga开发·边缘计算
俺不是西瓜太郎´•ﻌ•`1 天前
大实验:基于赛灵思csg324100T,pmodMAXsonar的危险距离警报
fpga开发
ThreeYear_s2 天前
基于FPGA的超声波显示水位距离,通过蓝牙传输水位数据到手机,同时支持RAM存储水位数据,读取数据。
fpga开发
szxinmai主板定制专家2 天前
【飞腾AI加固服务器】全国产化飞腾+昇腾310+PCIe Switch的AI大模型服务器解决方案
运维·服务器·arm开发·人工智能·fpga开发