Verilog/Verilog 실습

Verilog HC-SR04 초음파센서 제어

오버헤드프레스 2023. 5. 16. 17:39

 

 

 

초음파 센서

 

HC-SR04는 40kHz의 초음파 송신부와 수신부로 구성되어있다.

 

모듈 스펙

입력 전원 : 5v

측정 거리 : 2cm ~ 4m

측정 각도 범위 : 15°

트리거 입력 신호 : 10us

 

 

작동원리

1. 모듈의 Trig에 10 us의 High Pulse를 준다.

2.  40KHz의 8개 sonic burst 발생. [1번 과정을 거쳐야만 발생]

3. 에코는 초음파 발신 직후 HIGH level이 되고, 물체를 감지하면 LOW level이 된다.

-> 에코 펄스는 즉, 초음파가 장애물을 만나 다시 에코로 돌아올때까지의 왕복 시간을 나타낸다,

4. 거리 에코 High Pulse 시간(왕복시간) 소리의 속도(340m/s) / 2 

-> 왕복이므로 2로 나누어 주어야한다. 

 

 

초음파센서 TOP 모듈 코드

 

`timescale 1ns / 1ps



module ultrasonic_1_top(
input clk,
        input btn,
        input echo,
        output t,
        output [7:0] led,
        output [3:0] com_an,
        output [6:0] seg
        );
    
    wire reset_n;
    wire [15:0] bcd_echo;
    wire clk_160ns, clk_2560ns, clk_40us, debounced_btn;
    wire [11:0] echo_value;
    wire [11:0] echo_cm;
    
    assign echo_cm = echo_value/58;

    
    clock_divider cd_16(.clk(clk), .sel(3), .clk_out(clk_160ns));  //160ns
    clock_divider cd_256(.clk(clk_160ns), .sel(3), .clk_out(clk_2560ns));  //2560ns
    clock_divider cd_4096(.clk(clk_2560ns), .sel(3), .clk_out(clk_40us));  //40us
    
    ultrasonic_1 uccc(.clk(clk), .reset_n(reset_n), .echo(echo), .t(t), .echo_value(echo_value), .led(led));
    
    D_flip_flop_posedge dff(.D(btn), .E(clk_40us), .Q(debounced_btn));
    
    assign reset_n = ~debounced_btn;
    
    
    bin_to_dec btd_humi   (.bin(echo_cm), .bcd(bcd_echo));

    FND_4digit_switcher fnd(
    .value_1(bcd_echo [3:0]), 
    .value_10(bcd_echo[7:4]), 
    .value_100(bcd_echo[11:8]), 
    .value_1000(bcd_echo[15:12]),
    .clk(clk),
    .com_an(com_an),
    .seg(seg)
    );
    
    
endmodule

 

 

 

초음파센서 코드

 

`timescale 1ns / 1ps


module ultrasonic_1(
    input clk, 
    input reset_n, 
    input echo,
    output reg t,
    output reg  [11:0] echo_value, 
    output reg [7:0] led
    );

parameter TRIG_WAIT = 3'b000;

parameter TRIG_PULSE = 3'b001;
parameter ECHO_PULSE = 3'b010;


wire echo_p, echo_n;
reg [2:0] state = TRIG_WAIT, next_state = TRIG_WAIT;
reg [21:0] cnt_usec; 
reg cnt_usec_e = 0;

clock_usec u(.clk(clk), .reset_n(1), .clk_usec(clk_usec));

edge_detect usec(.clk(clk_usec), .cp_in(echo), .reset_n(1), .p_edge(echo_p), .n_edge(echo_n));

always @(negedge clk_usec or negedge reset_n)begin
        if(!reset_n)begin  cnt_usec = 0;end
        else if (cnt_usec_e) begin cnt_usec = cnt_usec + 1;end
        else begin cnt_usec = 0; end
    end


always @(negedge clk_usec or negedge reset_n)begin
        if (!reset_n)begin  state = TRIG_WAIT; end
        else begin
            state = next_state;
            case (state)
                TRIG_WAIT : begin  cnt_usec_e = 1;
                    if (cnt_usec < 100000)begin
                        cnt_usec_e = 1;
                        t = 0;
                        led[0] = 1;
                    end
                    else begin
                        next_state = TRIG_PULSE ;
                        cnt_usec_e = 0;
                    end
                end
                TRIG_PULSE : begin cnt_usec_e = 1;
                    led[1] = 1;
                    if (cnt_usec <= 15)begin
                        cnt_usec_e = 1;
                        t = 1;
                    end

                    else begin
                        t = 0;
                        cnt_usec_e = 0;
                        next_state = ECHO_PULSE;
                    end
                end
                
                ECHO_PULSE: begin
                    led[2] = 1;
                        if(echo_p) begin
                            led[3] = 1;
                            cnt_usec_e = 1;
                        end
                        else if(echo_n) begin
                            cnt_usec_e = 0;
                            echo_value = cnt_usec[11:0];
                            next_state = TRIG_WAIT;
                        end
end
                default : next_state = TRIG_WAIT;
                endcase
                end
                end
endmodule

 

 

테스터 벤치 코드

`timescale 1ns / 1ps

module ultrasonic_tb2();
    reg clk;
    reg echo;
    reg reset_n;
    wire t;
    wire [11:0] echo_value;
    ultrasonic_1 DUT(.clk(clk), .reset_n(reset_n), .echo(echo), .t(t), .echo_value(echo_value));
    initial begin clk = 0; reset_n = 1; echo = 0; end 
    always #5 clk = ~clk;
    initial begin 
    #100000000
    #20000  echo = 1;
    #1000000 echo = 0;
    #100020000 echo = 1;
    #2000000 echo = 0;
    #98000000 
    $finish;
    end
    
endmodule

 

 

시뮬레이션

 

 

초음파센서 결과

 

초음파센서 결과