---
title: 基于 ZYNQ ECO开发板 超声波模块
url: "https://www.fpgalearn.com/9114.html"
kind: article
id: 9114
excerpt: 超声波模块 `timescale 1ns / 1ps module SR_04( input clk , input rst_n , input echo , …
published_at: 2025-05-08
author: FPGA小白
tags: ECO开发板, FPGA工程, FPGA源码, 超声波
word_count: 2614
source: "https://www.fpgalearn.com"
---

# 基于 ZYNQ ECO开发板 超声波模块

> 标签：ECO开发板、FPGA工程、FPGA源码、超声波
> 超声波模块 `timescale 1ns / 1ps module SR_04( input clk , input rst_n , input echo , …

> 超声波模块 `timescale 1ns / 1ps module SR_04( input clk , input rst_n , input echo , …

## 超声波模块
```
`timescale 1ns / 1ps
module SR_04(
        input               clk     ,
        input               rst_n   ,
        input               echo    ,   //接收端，判断端口返回值
        output     [15:0]   dis     ,   //最终距离
        output              trig        //脉冲发出
    );

    parameter   delay = (50*15) + (50*1000*100);    //60ms以上的周期
    parameter   s1 = 0;         //空闲
    parameter   s2 = 1;         //echo开始计时
    parameter   s3 = 2;         //计时结束

    reg     [31:0]  cnt_trig;
    reg     [31:0]  cnt_echo;
    reg     [31:0]  cnt_echo_reg;
    reg [2:0]   c_state;
    reg [2:0]   n_state;

    always @(posedge clk)
        if(!rst_n)
            cnt_trig 0) && (cnt_trig<(50*15))) ? 1:0;

    always  @(posedge clk)
        if(!rst_n)
            c_state <= s1;
        else
            c_state <= n_state;

     always @(*)
        case(c_state)
            s1: begin
                if(echo == 1)
                    n_state = s2;
                else
                    n_state = s1;
                 end
            s2: begin
                if(echo == 0)
                    n_state = s3;
                else
                    n_state = s2;
            end
            s3: begin
                n_state = s1;
             end
         endcase

always @(posedge clk)
    if(!rst_n)begin
        cnt_echo<=0;
        cnt_echo_reg <= 0;
    end
    else    begin
            case(c_state)
                s1: begin
                    cnt_echo<=0;
                    cnt_echo_reg <= cnt_echo_reg;
                    end
                s2: begin
                    cnt_echo<=cnt_echo +1;
                    cnt_echo_reg <= cnt_echo_reg;
                   end
                s3: begin
                    cnt_echo<=cnt_echo;
                    cnt_echo_reg <= cnt_echo;
                    end
            endcase
     end

assign  dis = (cnt_echo_reg * 20)/1000/58;

endmodule
```
模块的输入包括时钟信号clk、复位信号rst_n、echo信号（接收端返回值）；输出包括距离信号dis和脉冲发出信号trig。
该模块定义了一些参数和寄存器用于跟踪计数。delay参数定义了周期的延迟时间，s1、s2和s3分别表示状态机的三个状态。
在时钟信号上升沿触发的always块中，根据复位信号的状态设置计数器cnt_trig的值。当cnt_trig达到delay-1时，将其重置为0。根据cnt_trig的值，将trig输出设置为1或0，以控制脉冲发出。
另一个时钟信号上升沿触发的always块中，根据复位信号和状态机的当前状态设置计数器cnt_echo和cnt_echo_reg的值。根据状态机的状态，cnt_echo的值会进行递增或保持不变。cnt_echo_reg保存上一个状态的计数器值。
最后，通过组合逻辑，将cnt_echo_reg乘以20，除以1000，再除以58，得到距离值dis。
这个超声波模块的功能是通过计数器实现超声波测距。它通过测量超声波从发射到接收的时间，然后将时间转换为距离值。相当于我们可以在其他地方得到超声波距离。
输出dis单位为 cm
## LED
```
`timescale 1ns / 1ps

module led_mk(
    input               clk         ,
    input               rst_n       ,
    input   [4:0]       led_zt      ,
    output  reg[3:0]    led
    );
    parameter led1 = 0;
    parameter led2 = 1;
    parameter led3 = 2;
    parameter led4 = 3;
    parameter led5 = 4;

    reg [3:0]   c_led;
    reg [3:0]   n_led;

    always @(posedge clk)
        if(!rst_n)
            c_led <= led1;
        else
            c_led <= n_led;

    always @(*)
        if(!rst_n)
            n_led = 0;
        else begin
            case(led_zt)
                led1: begin
                    n_led = led1;
                    end
                led2:begin
                     n_led = led2;
                    end
                led3:begin
                     n_led = led3;
                    end
                led4:begin
                     n_led = led4;
                    end
                led5:begin
                     n_led = led5;
                    end
                default:
                    n_led =  n_led;
              endcase
        end

       always @(posedge clk)
            if(!rst_n)
                led <= 0;
            else begin
                case(c_led)
                led1: begin
                        led <= 4'b0000;
                    end
                led2:begin
                        led <= 4'b0001;
                    end
                led3:begin
                        led <= 4'b0011;
                    end
                led4:begin
                        led <= 4'b0111;
                    end
                led5:begin
                        led <= 4'b1111;
                    end
                default:
                    led <= led;
                 endcase
            end
endmodule
```
这里通过输入的led_zt来控制ed显示的状态
## 超声波测距
```
`timescale 1ns / 1ps
module sr_led(
        input       clk     ,
        input       rst_n   ,
        input               echo    ,   //接收端，判断端口返回值
        output              trig    ,   //脉冲发出
        output  reg [3:0]       led
    );
    wire    [15:0]  dis;
    wire     [3:0]   led_dd;
    reg     [4:0]   led_zt;

    always  @(posedge clk)
        if(!rst_n)  begin
            led  csb4 )
            led_zt  csb3 && dis  csb2 && dis  csb1 && dis  csb0 && dis <= csb1)
            led_zt <= 0;

led_mk  kk(
    .    clk      (clk   )   ,
    .    rst_n    (rst_n )   ,
    .    led_zt   (led_zt)   ,
    .    led      (led_dd   )
    );

SR_04   sr(
        .   clk    (clk  ) ,
        .   rst_n  (rst_n) ,
        .   echo   (echo ) ,   //接收端，判断端口返回值
        .   dis    (dis  ) ,   //最终距离
        .   trig   (trig )     //脉冲发出
    );
endmodule
```
通过调用l超声波距离远近来控制led状态
