基于FPGA的超声波显示水位距离,通过蓝牙传输水位数据到手机,同时支持RAM存储水位数据,读取数据。

news2025/6/9 19:12:01

基于FPGA的超声波显示水位距离

  • 前言
  • 一、整体框架
  • 二、代码架构
    • 1.超声波测距模块
    • 2.蓝牙数据发送模块
    • 3.数码管数据切换模块
    • 4.数码管驱动模块
    • 6.串口驱动
    • 7.顶层模块
    • 8.RAM ip核
  • 仿真相关截图

前言

随着工业化进程的加速和环境保护意识的提升,对水资源管理和水位监测的需求日益迫切。传统的水位监测系统多采用单片机或PLC作为控制核心存在处理速度慢、实时性差、扩展性有限等问题。基于FPGA的水位监测系统以其强大的并行处理能力、高度的灵活性和可重配置性,为水位监测提供了新的解决方案。本课题旨在设计并实现一个基于FPGA的水位监测系统,通过实时采集水位数据,结合先进的数据处理算法,实现高效、准确的水位监测。

本课题聚焦于设计一个基于FPGA的水位监测系统,它通过部署在水源处的传感器精确获取水位信息,利用FPGA强大的并行处理能力实时分析数据一旦水位超限立即触发报警,并上传数据至监测中心进行记录和存储。
1)查找资料对水位监测技术进行了解,提出系统整体设计方案。
2)选择适合的传感器模块、FPGA模块、通信模块、显示块等进行系统硬件设计。
3)利用自顶向下的设计方法进行系统顶层设计,并分模块进行FPGA程序设进行软硬件系统调试。

一、整体框架

硬件需求:FPGA开发板、数码管模块、3个按键、1个复位按键、蓝牙模块、超声波测距模块、蜂鸣器模块

软件模块框架:
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、代码架构

(仿真不需要按键消抖,同时时间间隔缩小)

1.超声波测距模块

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/12 16:01:55
// Design Name: 
// Module Name: HC_SR04
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module HC_SR04(
     input                     sys_clk  ,  
     input                     rst_n,   
     //signal  
     input                     Echo,
     output     wire    [15:0] Distance,
     output     reg            Trig_signal
    );

parameter IDLE=4'd0;
parameter SEND=4'd1;
parameter RECIEVE=4'd2;
parameter OVER=4'd3;

parameter MAX_CNT=24'd500;
parameter time_1s=32'd50000000;
reg [3:0] state;
reg [3:0] state_1;
reg [23:0] cnt;
reg [31:0] time_cnt;
reg [23:0] distance_temp;
reg key_start;

assign Distance=distance_temp/1000;
always @(posedge sys_clk or negedge rst_n)begin
    if(!rst_n)begin
        time_cnt<=32'd0;
        key_start<=1'b0;
    end
    else if(time_cnt<time_1s)begin
        time_cnt<=time_cnt+1;
        key_start<=1'b0;
    end
    else if(time_cnt==time_1s)begin
        time_cnt<=32'd0;
        key_start<=1'b1;
    end
end

always @(posedge sys_clk or negedge rst_n)begin
    if(!rst_n)begin
        state<=IDLE;
        Trig_signal<=1'b0;
        state_1<=IDLE;
        distance_temp<=24'd10000000;
        cnt<=24'd0;
    end
    else begin
        case(state)
        IDLE:begin
            cnt<=24'd0;
            if(key_start==1'b1)begin
                state<=SEND;
            end
            else begin
                state<=IDLE;
            end
        end
        SEND:begin
            if(cnt<MAX_CNT)begin
                cnt<=cnt+1;
                Trig_signal<=1'b1;
                state<=SEND;
            end
            else begin
                cnt<=16'd0;
                Trig_signal<=1'b0;
                state<=RECIEVE;
            end
        end
        RECIEVE:begin
           case(state_1)
           IDLE:begin
               if(Echo==1'b1)begin
                  state_1<=RECIEVE;  
               end
               else begin
                  state_1<=IDLE;
               end
           end
           RECIEVE:begin
               if(Echo==1'b1)begin
                  cnt<=cnt+1;  
               end
               else begin
                  cnt<=cnt+1;
                  state_1<=OVER;
               end
           end
           OVER:begin
               state_1<=IDLE;
               state<=OVER;
           end
           default:state_1<=IDLE;
           endcase
        end
        OVER:begin
            distance_temp<=cnt*34;
            state<=IDLE;
        end
        default:state<=IDLE;
        endcase
    end
end

    

endmodule

2.蓝牙数据发送模块

module Bluetooth_data(
    input           clk,
    input           rst_n,
	 input  [3:0]    data_3,
	 input  [3:0]    data_2,
	 input  [3:0]    data_4,
	 
    input           uart_tx_done,
    input  [7 :0]   uart_rx_data,
    input           uart_rx_done,
    
    output  reg             uart_tx_en,
    output  reg     [7:0]   uart_tx_data
    
    
    );
	 
	 parameter IDLE              = 4'd0;
	 parameter WAIT_1s           = 4'd1;
	 parameter SEND              = 4'd2;
	 parameter OVER              = 4'd3;
	 
	 parameter count_max              = 32'd50000000; //
	 //spo2:23.6  ---->  74 65 6D 70 3A 32 33 2E 36 0d 0a
	 //hert:23.6  ---->  68 75 6D 69 3A 32 33 2E 36 0d 0a
	 reg  [87:0]   cmd_temp    ={8'h68,8'h20,8'h3a,8'h32,8'h32,8'h2e,8'h33,8'h63,8'h6d,8'h0d,8'h0a};
	 reg  [87:0]   cmd_humi    ={8'h68,8'h20,8'h3a,8'h32,8'h32,8'h2e,8'h33,8'h63,8'h6d,8'h0d,8'h0a};
	 reg	[3: 0]	state;
	 reg	[31:0]	count;
	 
	 reg  [5 :0]   tx_count;
	 reg	[1: 0]	tx_en_count;
	 reg           uart_tx_en_temp;
	 
	 reg	[1 :0]	change_count;
	 
	 wire	[7:0]		bluedata_1;
	 wire	[7:0]		bluedata_2;
	 wire	[7:0]		bluedata_3;


	 
	 assign bluedata_1=(data_4==4'd0)?8'h20:8'h30+data_4;
	 assign bluedata_2=8'h30+data_3;
	 assign bluedata_3=8'h30+data_2;

	  //����״̬tx_data
    always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        uart_tx_data <= 8'd0;
    end
	 else if(change_count==2'd0)begin
			if((state==SEND) && tx_count<8'd3 ) begin
				uart_tx_data <= cmd_temp[87 - tx_count *8 -:8];
			end
			else if((state==SEND) && tx_count==8'd3 ) begin
				uart_tx_data <= bluedata_1;
			end
			else if((state==SEND) && tx_count==8'd4 ) begin
				uart_tx_data <= bluedata_2;
			end
			else if((state==SEND) && tx_count==8'd5 ) begin
				uart_tx_data <= 8'h3a;
			end
			else if((state==SEND) && tx_count==8'd6 ) begin
				uart_tx_data <= bluedata_3;
			end
			else if((state==SEND) && tx_count<8'd11 ) begin
				uart_tx_data <= cmd_temp[87 - tx_count *8 -:8];
			end	
	 end
    
	 else if(change_count==2'd1)begin
			if((state==SEND) && tx_count<8'd3 ) begin
				uart_tx_data <= cmd_humi[87 - tx_count *8 -:8];
			end
			else if((state==SEND) && tx_count==8'd3 ) begin
				uart_tx_data <= bluedata_1;
			end
			else if((state==SEND) && tx_count==8'd4 ) begin
				uart_tx_data <= bluedata_2;
			end
			else if((state==SEND) && tx_count==8'd5 ) begin
				uart_tx_data <= 8'h3a;
			end
			else if((state==SEND) && tx_count==8'd6 ) begin
				uart_tx_data <= bluedata_3;
			end
			else if((state==SEND) && tx_count<8'd11 ) begin
				uart_tx_data <= cmd_humi[87 - tx_count *8 -:8];
			end	
	 end

	 end
	 
	   //tx_en time
    always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        tx_en_count <= 2'b0;
    end
    else if((state==SEND) && tx_en_count<2'd1 && tx_count==8'd0) begin
        tx_en_count <=tx_en_count+ 1'd1;
    end
    else if((state==SEND) && tx_en_count==2'd1 && tx_count==8'd0) begin
        tx_en_count <= 2'd3;
    end
    else if(state==OVER)begin
        tx_en_count <= 2'd0;
    end
    else begin
        tx_en_count <= tx_en_count;
    end
end
	 //����״̬tx_count
    always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        tx_count <= 8'd0;
    end
    else if(state==SEND) begin
        if(uart_tx_done==1'd1)
            tx_count <= tx_count+1'b1;
    end
    else begin
        tx_count <= 8'd0;
    end
end
	  //����״̬data_tx_en
    always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        uart_tx_en_temp <= 1'b0;
        uart_tx_en <= uart_tx_en_temp;
    end
    else if((state==SEND ) && tx_en_count==1) begin
        uart_tx_en_temp <= 1'b1;
        uart_tx_en <= uart_tx_en_temp;
    end
    else if((state==SEND ) && tx_count<8'd10 && uart_tx_done==1)begin
        uart_tx_en_temp <= 1'b1;
        uart_tx_en <= uart_tx_en_temp;
    end
	 else begin
		  uart_tx_en_temp <= 1'b0;
        uart_tx_en <= uart_tx_en_temp;
	 end
	 end
	 
	 //state go 
    always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        count <= 32'd0;
    end
	 else if(state == WAIT_1s && count < count_max)begin
		  count <= count + 32'd1;
	 end
	 else if(state == WAIT_1s && count == count_max)begin
		  count <= 32'd0;
	 end
	 else begin
		  count <= count;
	 end
	 end
	 
	 
	 
	 
	 //state go 
    always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        state <= IDLE;
		  change_count<=2'd0;
    end
    else begin
        case(state)
        IDLE:begin
				state<=WAIT_1s;
		  end
		  WAIT_1s:begin
				if(count==count_max)begin
					state<=SEND;
				end
				else begin
					state<=WAIT_1s;
				end
		  end
		  SEND:begin
				if(tx_count==6'd11)begin
                state <= OVER;
            end
            else begin
                state <= SEND;
            end
		  end
		  OVER:begin
				state <= IDLE;
				if(change_count<2'd1)begin
					change_count<=change_count+2'd1;
				end
				else if(change_count==2'd1)begin
					change_count<=2'd0;
				end
		  end
		  default:state <= IDLE;
		  endcase
	 end
	 end
	 
endmodule

3.数码管数据切换模块

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/05/26 14:56:37
// Design Name: 
// Module Name: display_data
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module display_data(
     input                     sys_clk  ,  
     input                     rst_n,   
	  input                     change_key,   
     input             [15:0]  Distance,
	  input             [15:0]  data_out,
	  output    wire    [3:0]   data_3,
	  output    wire    [3:0]   data_2,
	  output    wire    [3:0]   data_4,
	  output    reg     [3 :0]  display_point,
     output    reg     [15:0]  display_data
    );

 wire [15:0] Distance_temp;
 wire [15:0] data;
 wire [3:0]  data_1;
// wire [3:0] data_3;
// wire [3:0] data_2;
// wire [3:0] data_4;
 reg [1:0] cnt;

function [15:0]Hex_to_Doc;
input  [15:0] num_h;
begin
     Hex_to_Doc = num_h[3:0] + num_h[7:4]*16 +num_h[11:8]*256 +num_h[15:12]*4096;
end 
endfunction


 assign data=(cnt==2'd0)?Distance:data_out;
 
 assign Distance_temp=Hex_to_Doc(data);
 assign data_1=Distance_temp%10;
 assign data_2=(Distance_temp%100)/10;
 assign data_3=(Distance_temp%1000)/100;
 assign data_4=(Distance_temp/1000);
 
 
 
	 always @(posedge sys_clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt<=2'd0;
    end
    else if(change_key && cnt<2'd1)begin
        cnt<=cnt+1;
    end
    else if(change_key && cnt==2'd1)begin
        cnt<=2'd0;
    end
	 end
	
    
    always @(*)begin
				if(data_4==4'd0)begin
					display_data<={4'he,data_3,data_2,data_1};
					display_point<=4'b1111;
				end
				else begin
					display_data<={data_4,data_3,data_2,data_1};
					display_point<=4'b1111;
				end
            
    end
    
    
endmodule

4.数码管驱动模块

module seg_ctrl( 
    input				clk		,
    input				rst_n	,
    input		[15:0]	din		,//????6��???????????????��???????4��
    input       [3:0]   point_n ,//????��????????��
    output	reg	[3:0]	sel	,//????��?
    output	reg	[7:0]	dig  //???????
);								 
//---------<????????>--------------------------------------------------------- 
    parameter TIME_1MS = 50_000;//1ms

    //????????????????
    localparam NUM_0 = 7'b100_0000,//0
               NUM_1 = 7'b111_1001,//1
               NUM_2 = 7'b010_0100,//
               NUM_3 = 7'b011_0000,//
               NUM_4 = 7'b001_1001,//
               NUM_5 = 7'b001_0010,//
               NUM_6 = 7'b000_0010,//
               NUM_7 = 7'b111_1000,//
               NUM_8 = 7'b000_0000,//
               NUM_9 = 7'b001_0000,//
               A     = 7'b000_1000,//
               B     = 7'b000_0011,//b
               C     = 7'b100_0110,//
               OFF   = 7'b111_1111,//???
               CROSS = 7'b011_1111,//????
               //D     = 7'b010_0001,//d
               //E     = 7'b000_0110,//
               F     = 7'b000_1110;//

//---------<?????????>-----------------------------------------------------
    reg			[15:0]	cnt_1ms	   	;//1ms???????????????????????
    wire				add_cnt_1ms	;
    wire				end_cnt_1ms	;

    reg         [3:0]   disp_data   ;//??��??????????????
    reg                 point_n_r   ;//??��???????????��????
    
//****************************************************************
//--cnt_1ms
//****************************************************************
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_1ms <= 'd0;
        end 
        else if(add_cnt_1ms)begin 
            if(end_cnt_1ms)begin 
                cnt_1ms <= 'd0;
            end
            else begin 
                cnt_1ms <= cnt_1ms + 1'b1;
            end 
        end
    end 
    
    assign add_cnt_1ms = 1'b1;//??????????
    assign end_cnt_1ms = add_cnt_1ms && cnt_1ms == TIME_1MS - 1;
    
//****************************************************************
//--seg_sel
//****************************************************************
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            sel <= 4'b1_110;//?????��???????????��??????
        end 
        else if(end_cnt_1ms)begin 
            sel <= {sel[2:0],sel[3]};//???????
        end 
    end

//****************************************************************
//--disp_data
//****************************************************************
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            disp_data <= 'd0;
            point_n_r <= 1'b1;
        end 
        else begin 
            case (sel)
                4'b1_110 : begin disp_data <= din[3:0]  ; point_n_r <= point_n[0]; end//???��??????????????
                4'b1_101 : begin disp_data <= din[7:4]  ; point_n_r <= point_n[1]; end
                4'b1_011 : begin disp_data <= din[11:8] ; point_n_r <= point_n[2]; end
                4'b0_111 : begin disp_data <= din[15:12]; point_n_r <= point_n[3]; end
              
                default: disp_data <= 'd0;
            endcase
        end 
    end

//****************************************************************
//--seg_dig
//****************************************************************
    always @(*)begin 
        case (disp_data)
            0 :  dig = {point_n_r,NUM_0};
            1 :  dig = {point_n_r,NUM_1};
            2 :  dig = {point_n_r,NUM_2};
            3 :  dig = {point_n_r,NUM_3};
            4 :  dig = {point_n_r,NUM_4};
            5 :  dig = {point_n_r,NUM_5};
            6 :  dig = {point_n_r,NUM_6};
            7 :  dig = {point_n_r,NUM_7};
            8 :  dig = {point_n_r,NUM_8};
            9 :  dig = {point_n_r,NUM_9};
            10 : dig = {point_n_r,A    };
            11 : dig = {point_n_r,B    };
            12 : dig = {point_n_r,C    };
            13 : dig = {point_n_r,CROSS};
            14 : dig = {point_n_r,OFF  };
            15 : dig = {point_n_r,F    };
            default: dig = 8'hff;
        endcase
    end


endmodule


6.串口驱动

module uart_top_blue( 
    input            sys_clk  ,   //�ⲿ50MHzʱ��
    input            sys_rst_n,   //ϵ�ⲿ��λ�źţ�����Ч
    
    //UART�˿�   
    input            uart_rxd ,   //UART���ն˿�
    output           uart_txd ,    //UART���Ͷ˿�
    input               uart_tx_en,    //UART���������ź�
    output wire         uart_rx_done,    //UART���������ź�  
    output wire         uart_tx_done,    //UART���������ź�  
    
         
    input        [7:0]  uart_tx_data,    //UART��������     
    output wire  [7:0]  uart_rx_data    //UART��������         
    );

//parameter define
parameter CLK_FREQ = 50000000;    //����ϵͳʱ��Ƶ��
parameter UART_BPS = 9600  ;    //���崮�ڲ�����

//wire define
//wire         uart_rx_done;    //UART���������ź�
//wire  [7:0]  uart_rx_data;    //UART��������

//*****************************************************
//**                    main code
//*****************************************************

//���ڽ���ģ��
uart_rx_blue #(
    .CLK_FREQ  (CLK_FREQ),
    .UART_BPS  (UART_BPS)
    )    
    u_uart_rx_blue(
    .clk           (sys_clk     ),
    .rst_n         (sys_rst_n   ),
    .uart_rxd      (uart_rxd    ),
    .uart_rx_done  (uart_rx_done),
    .uart_rx_data  (uart_rx_data)
    );


uart_tx_blue #(
    .CLK_FREQ  (CLK_FREQ),
    .UART_BPS  (UART_BPS)
    )    
    u_uart_tx_blue(
    .clk          (sys_clk     ),
    .rst_n        (sys_rst_n   ),
    .uart_tx_en   (uart_tx_en),
    .uart_tx_data (uart_tx_data),
    .uart_tx_done (uart_tx_done),
    .uart_txd     (uart_txd    ),
    .uart_tx_busy (            )
    );
    
endmodule



module uart_rx_blue(
    input               clk         ,  //ϵͳʱ��
    input               rst_n       ,  //ϵͳ��λ������Ч

    input               uart_rxd    ,  //UART���ն˿�
    output  reg         uart_rx_done,  //UART���������ź�
    output  reg  [7:0]  uart_rx_data  //UART���յ�������
    
    );

//parameter define
parameter CLK_FREQ = 100000000;               //ϵͳʱ��Ƶ��
parameter UART_BPS = 115200  ;               //���ڲ�����
localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS; //Ϊ�õ�ָ�������ʣ���ϵͳʱ�Ӽ���BPS_CNT��

//reg define
reg          uart_rxd_d0;
reg          uart_rxd_d1;
reg          uart_rxd_d2;
reg          rx_flag    ;  //���չ��̱�־�ź�
reg  [3:0 ]  rx_cnt     ;  //�������ݼ�����
reg  [15:0]  baud_cnt   ;  //�����ʼ�����
reg  [7:0 ]  rx_data_t  ;  //�������ݼĴ���

//wire define
wire        start_en;

//*****************************************************
//**                    main code
//*****************************************************
//�������ն˿��½���(��ʼλ)���õ�һ��ʱ�����ڵ������ź�
assign start_en = uart_rxd_d2 & (~uart_rxd_d1) & (~rx_flag);

//�����첽�źŵ�ͬ������
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        uart_rxd_d0 <= 1'b0;
        uart_rxd_d1 <= 1'b0;
        uart_rxd_d2 <= 1'b0;
    end
    else begin
        uart_rxd_d0 <= uart_rxd;
        uart_rxd_d1 <= uart_rxd_d0;
        uart_rxd_d2 <= uart_rxd_d1;
    end
end

//�����ձ�־��ֵ
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) 
        rx_flag <= 1'b0;
    else if(start_en)    //���⵽��ʼλ
        rx_flag <= 1'b1; //���չ����У���־�ź�rx_flag���
    //��ֹͣλһ����ʱ�򣬼����չ��̽�������־�ź�rx_flag���
    else if((rx_cnt == 4'd9) && (baud_cnt == BAUD_CNT_MAX/2 - 1'b1))
        rx_flag <= 1'b0;
    else
        rx_flag <= rx_flag;
end        

//�����ʵļ�������ֵ
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) 
        baud_cnt <= 16'd0;
    else if(rx_flag) begin     //���ڽ��չ���ʱ�������ʼ�������baud_cnt������ѭ������
        if(baud_cnt < BAUD_CNT_MAX - 1'b1)
            baud_cnt <= baud_cnt + 16'b1;
        else 
            baud_cnt <= 16'd0; //�����ﵽһ�����������ں�����
    end    
    else
        baud_cnt <= 16'd0;     //���չ��̽���ʱ����������
end

//�Խ������ݼ�������rx_cnt�����и�ֵ
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) 
        rx_cnt <= 4'd0;
    else if(rx_flag) begin                  //���ڽ��չ���ʱrx_cnt�Ž��м���
        if(baud_cnt == BAUD_CNT_MAX - 1'b1) //�������ʼ�����������һ������������ʱ
            rx_cnt <= rx_cnt + 1'b1;        //�������ݼ�������1
        else
            rx_cnt <= rx_cnt;
    end
    else
        rx_cnt <= 4'd0;                     //���չ��̽���ʱ����������
end        

//����rx_cnt��Ĵ�rxd�˿ڵ�����
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) 
        rx_data_t <= 8'b0;
    else if(rx_flag) begin                           //ϵͳ���ڽ��չ���ʱ
        if(baud_cnt == BAUD_CNT_MAX/2 - 1'b1) begin  //�ж�baud_cnt�Ƿ�����������λ���м�
           case(rx_cnt)
               4'd1 : rx_data_t[0] <= uart_rxd_d2;   //�Ĵ����ݵ�����λ
               4'd2 : rx_data_t[1] <= uart_rxd_d2;
               4'd3 : rx_data_t[2] <= uart_rxd_d2;
               4'd4 : rx_data_t[3] <= uart_rxd_d2;
               4'd5 : rx_data_t[4] <= uart_rxd_d2;
               4'd6 : rx_data_t[5] <= uart_rxd_d2;
               4'd7 : rx_data_t[6] <= uart_rxd_d2;
               4'd8 : rx_data_t[7] <= uart_rxd_d2;   //�Ĵ����ݵĸߵ�λ
               default : ;
            endcase  
        end
        else
            rx_data_t <= rx_data_t;
    end
    else
        rx_data_t <= 8'b0;
end        

//�����������źźͽ��յ������ݸ�ֵ
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        uart_rx_done <= 1'b0;
        uart_rx_data <= 8'b0;
    end
    //���������ݼ�����������ֹͣλ����baud_cnt������ֹͣλ���м�ʱ
    else if(rx_cnt == 4'd9 && baud_cnt == BAUD_CNT_MAX/2 - 1'b1) begin
        uart_rx_done <= 1'b1     ;  //��߽��������ź�
        uart_rx_data <= rx_data_t;  //����UART���յ������ݽ��и�ֵ
    end    
    else begin
        uart_rx_done <= 1'b0;
        uart_rx_data <= uart_rx_data;
    end
end

endmodule


module uart_tx_blue(
    input               clk         , //ϵͳʱ��
    input               rst_n       , //ϵͳ��λ������Ч
    input               uart_tx_en  , //UART�ķ���ʹ��
    input     [7:0]     uart_tx_data, //UARTҪ���͵�����
    output  reg         uart_txd    , //UART���Ͷ˿�
    output  reg  [3:0]  tx_cnt      ,  //�������ݼ�����
    output  reg  [15:0] baud_cnt    ,  //�����ʼ�����
    output  reg         uart_tx_done,
    output  reg         uart_tx_busy  //����æ״̬�ź�
    );

//parameter define
parameter CLK_FREQ = 100000000;               //ϵͳʱ��Ƶ��
parameter UART_BPS = 115200  ;               //���ڲ�����
localparam BAUD_CNT_MAX = CLK_FREQ/UART_BPS; //Ϊ�õ�ָ�������ʣ���ϵͳʱ�Ӽ���BPS_CNT��

//reg define
reg  [7:0]  tx_data_t;  //�������ݼĴ���
//�����ʵļ�������ֵ
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) 
        uart_tx_done<=1'b0;
    else if(tx_cnt == 4'd9 && baud_cnt == BAUD_CNT_MAX - 1) begin
       uart_tx_done<=1'b1;
    end    
    else
        uart_tx_done<=1'b0;     //���͹��̽���ʱ����������
end


//*****************************************************
//**                    main code
//*****************************************************

//��uart_tx_enΪ��ʱ���Ĵ������IJ������ݣ������BUSY�ź�
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        tx_data_t <= 8'b0;
        uart_tx_busy <= 1'b0;
    end
    //����ʹ��ʱ���Ĵ�Ҫ���͵����ݣ������BUSY�ź�
    else if(uart_tx_en) begin
        tx_data_t <= uart_tx_data;
        uart_tx_busy <= 1'b1;
    end
    //��������ֹͣλ����ʱ��ֹͣ���͹���
    else if(tx_cnt == 4'd9 && baud_cnt == BAUD_CNT_MAX - 1) begin
        tx_data_t <= 8'b0;     //���շ������ݼĴ���
        uart_tx_busy <= 1'b0;  //�����BUSY�ź�
    end
    else begin
        tx_data_t <= tx_data_t;
        uart_tx_busy <= uart_tx_busy;
    end
end

//�����ʵļ�������ֵ
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) 
        baud_cnt <= 16'd0;
    else if(uart_tx_en)  
        baud_cnt <= 16'd0;      
    //�����ڷ��͹���ʱ�������ʼ�������baud_cnt������ѭ������
    else if(uart_tx_busy) begin
        if(baud_cnt < BAUD_CNT_MAX - 1'b1)
            baud_cnt <= baud_cnt + 16'b1;
        else 
            baud_cnt <= 16'd0; //�����ﵽһ�����������ں�����
    end    
    else
        baud_cnt <= 16'd0;     //���͹��̽���ʱ����������
end

//tx_cnt���и�ֵ
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) 
        tx_cnt <= 4'd0;
    else if(uart_tx_en)  
        tx_cnt <= 16'd0;         
    else if(uart_tx_busy) begin             //���ڷ��͹���ʱtx_cnt�Ž��м���
        if(baud_cnt == BAUD_CNT_MAX - 1'b1) //�������ʼ�����������һ������������ʱ
            tx_cnt <= tx_cnt + 1'b1;        //�������ݼ�������1
        else
            tx_cnt <= tx_cnt;
    end
    else
        tx_cnt <= 4'd0;                     //���͹��̽���ʱ����������
end

//����tx_cnt���uart���Ͷ˿ڸ�ֵ
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) 
        uart_txd <= 1'b1;
    else if(uart_tx_busy) begin
        case(tx_cnt) 
            4'd0 : uart_txd <= 1'b0        ; //��ʼλ
            4'd1 : uart_txd <= tx_data_t[0]; //����λ����λ
            4'd2 : uart_txd <= tx_data_t[1];
            4'd3 : uart_txd <= tx_data_t[2];
            4'd4 : uart_txd <= tx_data_t[3];
            4'd5 : uart_txd <= tx_data_t[4];
            4'd6 : uart_txd <= tx_data_t[5];
            4'd7 : uart_txd <= tx_data_t[6];
            4'd8 : uart_txd <= tx_data_t[7]; //����λ����λ
            4'd9 : uart_txd <= 1'b1        ; //ֹͣλ
            default : uart_txd <= 1'b1;
        endcase
    end
    else
        uart_txd <= 1'b1;                    //����ʱ���Ͷ˿�Ϊ�ߵ�ƽ
end

endmodule

7.顶层模块

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/20 09:30:52
// Design Name: 
// Module Name: top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module top(
      input                     sys_clk  ,  
      input                     rst_n,   
		input                     save_key,
		input                     read_key,
		input                     change_key,
      input                     Echo,   
      output    wire            Trig_signal,
		input            		     uart_rxd1 ,   
      output           		     uart_txd1 ,
      output	wire	[3:0]	  sel,
      output	wire	[7:0]	  dig,
		output	wire			  sim_start,
		output   wire          Beep

    );
  //seg signal
  wire [15:0] display_data;
  wire [15:0] Distance;
  wire [3:0] data_3;
  wire [3:0] data_2;
  wire [3:0] data_4;
  
  wire            uart_tx_en1; 
  wire            uart_rx_done1; 
  wire            uart_tx_done1; 
  wire  [7:0]     uart_tx_data1; 
  wire  [7:0]     uart_rx_data1; 
  
  wire  [15:0]		data_out;
  assign Beep=(Distance<16'd500)?1'b0:1'b1;
  HC_SR04 u_HC_SR04(
    .sys_clk(sys_clk)		,
    .rst_n(rst_n)	,
    .Echo(Echo)	,
    .Distance(Distance)	,
	 .sim_start(sim_start),
    .Trig_signal(Trig_signal)	
    );
  
  display_data u_display_data(
    .sys_clk(sys_clk)		,
    .rst_n(rst_n)	,
	 .Distance(Distance)		,
	 .data_out(data_out)		,
	 .change_key(change_key)		,
	 .data_3(data_3)		,
	 .data_2(data_2)		,
	 .data_4(data_4)		,
    .display_data(display_data)	

    );
	 
	 ram	u_ram (
	.address ( 5'd1 ),
	.clock ( sys_clk ),
	.data ( Distance ),
	.rden ( read_key ),
	.wren ( save_key ),
	.q ( data_out )
	);
	 

	Bluetooth_data u_Bluetooth_data(
	 .clk(sys_clk),   
    .rst_n(rst_n),   
	 
	 .data_3(data_3)		,
	 .data_2(data_2)		,
	 .data_4(data_4)		,
	 
	 .uart_rx_done  (uart_rx_done1),
    .uart_rx_data  (uart_rx_data1),
    .uart_tx_en   (uart_tx_en1),
    .uart_tx_data (uart_tx_data1),
    .uart_tx_done (uart_tx_done1)   
    );
	 
	 uart_top_blue u_uart_top_blue(
    .sys_clk(sys_clk)  ,   
    .sys_rst_n(rst_n),   
    
    .uart_rx_done  (uart_rx_done1),
    .uart_rx_data  (uart_rx_data1),
    .uart_tx_en   (uart_tx_en1),
    .uart_tx_data (uart_tx_data1),
    .uart_tx_done (uart_tx_done1),
    
    .uart_rxd(uart_rxd1) ,  
    .uart_txd(uart_txd1)    
    );
  
    seg_ctrl u_seg_ctrl( 
    .clk(sys_clk)		,
    .rst_n(rst_n)	,
    .din(display_data),
    .point_n(4'b1011) ,
    .sel(sel)	,
    .dig(dig)  
);	


    
    
endmodule

8.RAM ip核

在这里插入图片描述

仿真相关截图

在这里插入图片描述
仿真没有按键消抖,测距时间间隔缩短一点,其他正常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2405736.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在Windows下利用LoongArch-toolchain交叉编译Qt

文章目录 0.交叉编译的必要性1.下载交叉编译工具链1.1.直接在Windows下使用mingw&#xff08;不使用虚拟机&#xff09;编译&#xff08;还没成功&#xff0c;无法编译&#xff09;1.2.在虚拟机中的Ubuntu中进行交叉编译 2.下载qt源码3.编译Qt3.1.创建loongarch64的mkspec3.2.创…

AIRIOT无人机安防解决方案

随着无人机技术的飞速发展和广泛应用&#xff0c;其在安防领域的价值日益凸显&#xff0c;从关键设施巡检、大型活动安保到边境巡防、应急救援&#xff0c;无人机正成为立体化安防体系不可或缺的“空中哨兵”。然而&#xff0c;无人机安防应用蓬勃发展的同时&#xff0c;其自身…

华为OD机考 - 水仙花数 Ⅰ(2025B卷 100分)

import java.util.*; public static Integer get(int count,int c){if(count<3||count>7){return -1;}//存储每位数的最高位……最低位int[] arr new int[count];List<Integer> res new ArrayList<>();for(int i(int) Math.pow(10,count-1);i<(int) Math…

php apache构建 Web 服务器

虚拟机配置流程winsever2016配置Apache、Mysql、php_windows server 2016配置web服务器-CSDN博客 PHP 和 Apache 通过 ​​模块化协作​​ 共同构建 Web 服务器&#xff0c;以下是它们的交互机制和工作流程&#xff1a; ​​一、核心组件分工​​ 组件角色​​Apache​​Web …

打通印染车间“神经末梢”:DeviceNet转Ethernet/IP连接机器人的高效方案

在印染行业自动化升级中&#xff0c;设备联网需求迫切。老旧印染设备多采用Devicenet协议&#xff0c;而新型工业机器人普遍支持Ethernet/IP协议&#xff0c;协议不兼容导致数据交互困难&#xff0c;设备协同效率低、生产监控滞后&#xff0c;成了行业数字化转型的阻碍。本文将…

2025-06-02-IP 地址规划及案例分析

IP 地址规划及案例分析 参考资料 Plan for IP addressing - Cloud Adoption Frameworkwww.cnblogs.comimage-hosting/articles at master jonsam-ng/image-hosting 概述 在网络通信中&#xff0c;MAC 地址与 IP 地址分别位于 OSI 模型的数据链路层和网络层&#xff0c;二者协…

AUTOSAR实战教程--开放式通用DoIP刷写工具OpenOTA开发计划

目录 软件概述 安装与运行 界面说明 3.1 功能区划分 3.2 状态显示 基本操作流程 4.1 DoIP连接配置 4.2 服务配置&#xff08;刷写流程&#xff09; 4.3 执行操作 4.4 保存配置 4.5 加载配置 功能详解 5.1 核心功能模块 诊断服务配置 通信设置 文件下载 工具功…

AI赋能的浏览器自动化:Playwright MCP安装配置与实操案例

以下是对Playwright MCP的简单介绍&#xff1a; Playwright MCP 是一个基于 Playwright 的 MCP 工具&#xff0c;提供浏览器自动化功能不要求视觉模型支持&#xff0c;普通的文本大语言模型就可以通过结构化数据与网页交互支持多种浏览器操作&#xff0c;包括截图、点击、拖动…

【技术笔记】MSYS2 指定 Python 版本安装方案

#工作记录 MSYS2 指定 Python 版本安装 一、前置条件 安装指定版本需要在干净的 MSYS2 环境中执行&#xff0c;为保证工具链的兼容性&#xff0c;若已安装 Python&#xff0c;需先卸载 Python 及与该版本深度绑定的工具链。具体操作如下&#xff1a; 卸载 Python&#xff1a…

《校园生活平台从 0 到 1 的搭建》第一篇:创建项目与构建目录结构

在本系列第一篇中&#xff0c;我们将从项目初始化开始&#xff0c;搭建基本的目录结构&#xff0c;并完成四个主页面的创建与 TabBar 设置。 &#xff08;tip&#xff1a;你可能会觉得有点 ai 化&#xff0c;因为这个文案是我自己写了一遍文案之后让 ai 去优化输出的&#xff0…

1 Studying《蓝牙核心规范5.3》

目录 [Vol 0][Part B 蓝牙规范要求] 3 定义 3.1 蓝牙产品类型 4 核心配置 4.1 基本速率核心配置 4.2 增强型数据速率核心配置 4.4 低功耗核心配置 4.5 基本速率和低功耗结合的核心配置 4.6 主机控制器接口核心配置 [Vol 1][Part A 架构]1 概述 1.1 BR/EDR操作概述 …

STM32+MPU6050传感器

#创作灵感## 在嵌入式系统开发中&#xff0c;STM32F103C8T6单片机与MPU6050传感器的组合因其高性能、低功耗以及丰富的功能而备受青睐。本文将简单介绍如何在Keil 5开发环境中实现STM32F103C8T6与MPU6050的连接和基本数据采集&#xff0c;带你快速入门智能硬件开发。 一、硬件…

26考研——数据的表示和运算_整数和实数的表示(2)

408答疑 文章目录 二、整数和实数的表示1、整数的表示1.1、无符号整数的表示1.2、有符号整数的表示1.3、C 语言中的整数类型及类型转换1.3.1、C 语言中的整型数据类型1.3.2、有符号数和无符号数的转换1.3.3、不同字长整数之间的转换 2、实数的表示2.1、浮点数的相关概念2.2、浮…

关于智能体API参考接口

关于智能体在Flask的源码&#xff1a;请求体(在payload里的是请求体)、请求头&#xff08;在headers里的i局势请求头&#xff09;。 我的例子&#xff1a; 我的疑问&#xff1a;为什么没按Coze官方API文档格式&#xff0c;在Apifox里发POST请求却能收到回复&#xff1f; 1. 你…

直角坐标系和斜角坐标系

前情概要 笛卡尔坐标系是直角坐标系和斜角坐标系的统称。为什么会有这两种坐标系呢&#xff0c;教材中为什么最后只用直角坐标系呢&#xff1f;我们这样解释&#xff1a; 研究一维空间中的向量时&#xff0c;由于一维空间中的向量有无数条&#xff0c;如果我们选定一条作为基…

vmware 设置 dns

vmware 设置 dns 常用的 DNS&#xff08;Domain Name System&#xff09;服务器地址可以帮助你更快、更安全地解析域名。以下是一些国内外常用的公共 DNS 服务&#xff1a; 国内常用 DNS 阿里云 DNS IPv4: 223.5.5.5、223.6.6.6IPv6: 2400:3200::1、2400:3200:baba::1特点&am…

基于单片机的病房呼叫系统(源码+仿真)

该系统由以 STM32F4 为平台的监控终端以及以 CC2530 为平台的无线传感网组成。系统上电后自动完成 ZigBee 网络的组建、终端节点的加入&#xff0c;病人可利用便携式的病人终端发出呼叫求助请求信息、节点在线信息以及对护士的服务评价信息等&#xff0c;这些信息通过路由节点发…

基于微信小程序的睡眠宝系统源码数据库文档

摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;睡眠宝系统被用户普遍使用&#xff0c;为方便用户能够可以…

VibePlayer

源代码地址&#xff1a; VibePlayer: VibePlayer是一款功能强大的Android音乐播放器应用&#xff0c;专为音乐爱好者设计&#xff0c;提供了丰富的音乐播放和管理功能。 用户需求 VibePlayer是一款功能强大的Android音乐播放器应用&#xff0c;专为音乐爱好者设计&#xff0…

【汇编逆向系列】三、函数调用包含单个参数之float类型-xmm0寄存器,sub,rep,stos,movss,mulss,addss指令

一、汇编代码 single_float_param:0000000000000060: F3 0F 11 44 24 08 movss dword ptr [rsp8],xmm00000000000000066: 57 push rdi0000000000000067: 48 83 EC 10 sub rsp,10h000000000000006B: 48 8B FC mov …