7/25 초음파 센서, PDT

정유석·2024년 7월 25일

교육 - 베릴로그

목록 보기
16/28

추가적임 초음파 센서 코드

다른 사람 꺼

컨트롤 모듈

module HC_SR04_cntr (
    input clk, reset_p, 
    input hc_sr04_echo,
    output reg hc_sr04_trig,
    output reg [21:0] distance,
    output [7:0] led_debug);
    
    // For Test
    assign led_debug[3:0] = state;
    
    // Define state 
    parameter S_IDLE                      = 4'b0001;
    parameter S_10US_TTL               = 4'b0010;
    parameter S_WAIT_PEDGE           = 4'b0100;
    parameter S_CALC_DIST             = 4'b1000;
    
    // Define state, next_state value.
    reg [3:0] state, next_state;
    
    // 언제 next_state를 state 변수에 넣는가?
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) state = S_IDLE;
        else state = next_state;
    end
    
    // get 10us negative one cycle pulse
    wire clk_usec;
    clock_div_100   usec_clk( .clk(clk), .reset_p(reset_p), .clk_div_100_nedge(clk_usec));     // 1us
    
    // making usec counter.
    reg [21:0] counter_usec;
    reg counter_usec_en;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) begin counter_usec = 0;
        end else if(clk_usec && counter_usec_en) counter_usec = counter_usec + 1;
        else if(!counter_usec_en) counter_usec = 0;
    end
    
    
    // hc_sr04_data의 Negative edge, Positive edge 얻기.
    wire hc_sr04_echo_n_edge, hc_sr04_echo_p_edge;
    edge_detector_p edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(hc_sr04_echo), .n_edge(hc_sr04_echo_n_edge), .p_edge(hc_sr04_echo_p_edge));
    
    // 상태 천이도에 따른 case문 정의
    // 각 상태에 따른 동작 정의
    always @(negedge clk or posedge reset_p) begin
        if(reset_p) begin
            next_state = S_IDLE;
            counter_usec_en = 0;  
        end else begin
            case(state)
                S_IDLE : begin        
                    if(counter_usec < 22'd3_000_000) begin
                        counter_usec_en = 1;  
                        hc_sr04_trig = 0;
                    end
                    else begin
                        counter_usec_en = 0;
                        next_state = S_10US_TTL;
                    end
                end
                
                
                
                S_10US_TTL : begin
                    if(counter_usec < 22'd10) begin
                        counter_usec_en = 1;
                        hc_sr04_trig = 1;
                    end
                    else begin
                        hc_sr04_trig = 0;
                        counter_usec_en = 0;
                        next_state = S_WAIT_PEDGE;
                    end
                end
                
                
                
                S_WAIT_PEDGE :  
                    if(hc_sr04_echo_p_edge) begin
                         next_state = S_CALC_DIST;    
                         counter_usec_en = 1;
                    end     
                
                
                
                S_CALC_DIST : begin          
                     if(hc_sr04_echo_n_edge) begin
                                distance = counter_usec / 58;
                                counter_usec_en = 0;
                                next_state = S_IDLE;
                      end
                      else next_state = S_CALC_DIST;
                end
            endcase
        end
    end
    
endmodule

동작 모듈

module HC_SR04_top (
    input clk, reset_p, 
    input hc_sr04_echo,
    output hc_sr04_trig,
    output [3:0] com,
    output [7:0] seg_7, led_debug) ;

    wire [21:0] distance_cm;
    HC_SR04_cntr HC_SR04_cntr_0(.clk(clk), .reset_p(reset_p), .hc_sr04_echo(hc_sr04_echo), .hc_sr04_trig(hc_sr04_trig), .distance(distance_cm),  .led_debug(led_debug)); 

     wire [11:0] distance_cm_bcd;
    bin_to_dec bcd_humi(.bin(distance_cm[11:0]),  .bcd(distance_cm_bcd));

    fnd_cntr fnd (.clk(clk), .reset_p(reset_p), .value(distance_cm_bcd), .com(com), .seg_7(seg_7));
endmodule

PDT

요구시간, 여유시간 = 슬랙시간, 베릴로그 WNS 주의 슬랙시간 표시 슬랙시간이 (-)이면 요구 시간보다 처리 시간이 더 긴것

WNS (Worst Negative Slack):

의미: WNS는 디지털 회로의 각 경로에서 가장 부정적인(즉, 가장 작은) 슬랙을 나타냅니다.
정의: 슬랙(slack)은 신호가 도착해야 하는 시간과 실제 도착하는 시간 사이의 차이를 의미합니다. WNS는 모든 경로 중 가장 작은 슬랙을 의미하며, 이는 해당 경로에서 신호가 가장 긴 시간 동안 지연될 수 있는 한계를 보여줍니다.
의미: WNS가 음수인 경우, 해당 경로의 신호는 지정된 도착 시간 내에 도달하지 못할 수 있습니다. 따라서 WNS를 최소화하여 회로의 신뢰성을 보장하는 것이 중요합니다.
TNS (Total Negative Slack):

의미: TNS는 전체 디지털 회로에서 모든 경로의 WNS를 합산한 값입니다.
정의: 모든 경로의 WNS 값을 더하여 구한 TNS는 디지털 회로 전체의 타이밍적 여유를 나타냅니다. TNS가 양수인 경우, 전체 회로는 동작 가능한 시간 여유를 가지고 있음을 나타내며, 음수인 경우에는 회로 전체에서 어떤 경로가 동작에 불안정성을 초래할 수 있음을 나타냅니다.
WHS (Worst Hold Slack):

의미: WHS는 각 회로 경로에서 가장 부정적인(즉, 가장 작은) 홀드 슬랙을 나타냅니다.
정의: 홀드 슬랙(hold slack)은 레지스터에서의 데이터가 유효한 시간 동안의 여유를 의미합니다. 따라서 WHS는 데이터가 유효하지 않을 수 있는 한계를 보여줍니다.
THS (Total Hold Slack):

의미: THS는 전체 디지털 회로에서 모든 경로의 WHS를 합산한 값입니다.
정의: 모든 경로의 WHS 값을 더하여 구한 THS는 디지털 회로 전체의 데이터가 유효하지 않을 수 있는 시간 여유를 나타냅니다. THS가 양수인 경우, 전체 회로는 안정적으로 동작할 수 있음을 나타내며, 음수인 경우에는 데이터 무결성 문제가 발생할 가능성이 있음을 나타냅니다.

코드 수정

나눗셈은 계산시간이 오래걸려 요구시간이 많이걸려 나눗셈을 안쓰는 코드로 수정
요구 시간을 줄이거나 클락을 늘리거나
나눗셈을 사용하지 않게하여 요구시간을 줄여본다

module HC_SR04_cntr (
    input clk, reset_p, 
    input hc_sr04_echo,
    output reg hc_sr04_trig,
    output reg [21:0] distance,
    output [7:0] led_debug);
    
    // For Test
    assign led_debug[3:0] = state;
    
    // Define state 
    parameter S_IDLE                      = 4'b0001;
    parameter S_10US_TTL               = 4'b0010;
    parameter S_WAIT_PEDGE           = 4'b0100;
    parameter S_CALC_DIST             = 4'b1000;
    
    // Define state, next_state value.
    reg [3:0] state, next_state;
    reg [1:0] echo_time;
    
    // 언제 next_state를 state 변수에 넣는가?
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) state = S_IDLE;
        else state = next_state;
    end
    
    // get 10us negative one cycle pulse
    wire clk_usec;
    clock_div_100   usec_clk( .clk(clk), .reset_p(reset_p), .clk_div_100_nedge(clk_usec));     // 1us
    
    // making usec counter.
    reg [21:0] counter_usec;
    reg counter_usec_en;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) begin counter_usec = 0;
        end else if(clk_usec && counter_usec_en) counter_usec = counter_usec + 1;
        else if(!counter_usec_en) counter_usec = 0;
    end
    
    
    // hc_sr04_data의 Negative edge, Positive edge 얻기.
    wire hc_sr04_echo_n_edge, hc_sr04_echo_p_edge;
    edge_detector_p edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(hc_sr04_echo), .n_edge(hc_sr04_echo_n_edge), .p_edge(hc_sr04_echo_p_edge));
    
    // 상태 천이도에 따른 case문 정의
    // 각 상태에 따른 동작 정의
    always @(negedge clk or posedge reset_p) begin
        if(reset_p) begin
            next_state = S_IDLE;
            counter_usec_en = 0;  
        end else begin
            case(state)
                S_IDLE : begin        
                    if(counter_usec < 22'd3_000_000) begin
                        counter_usec_en = 1;  
                        hc_sr04_trig = 0;
                    end
                    else begin
                        counter_usec_en = 0;
                        next_state = S_10US_TTL;
                    end
                end
                
                
                
                S_10US_TTL : begin
                    if(counter_usec < 22'd10) begin
                        counter_usec_en = 1;
                        hc_sr04_trig = 1;
                    end
                    else begin
                        hc_sr04_trig = 0;
                        counter_usec_en = 0;
                        next_state = S_WAIT_PEDGE;
                    end
                end
                
                
                
                S_WAIT_PEDGE :  
                    if(hc_sr04_echo_p_edge) begin
                         next_state = S_CALC_DIST;    
                         counter_usec_en = 1;
                    end     
                
                
                
                S_CALC_DIST : begin          
                     if(hc_sr04_echo_n_edge) begin
                                echo_time = counter_usec;
                                counter_usec_en = 0;
                                next_state = S_IDLE;
                      end
                      else next_state = S_CALC_DIST;
                end
            endcase
        end
    end
    
    always @(posedge clk or posedge reset_p)begin
        if(reset_p) distance = 0;
        else begin
            if(echo_time < 174) distance = 2;
            else if (echo_time < 232) distance = 3;
            else if (echo_time < 290) distance = 4;
            else if (echo_time < 348) distance = 5;
            else if (echo_time < 406) distance = 6;
            else if (echo_time < 464) distance = 7;
            else if (echo_time < 522) distance = 8;
            else if (echo_time < 580) distance = 9;
            else if (echo_time < 638) distance = 10;
            else if (echo_time < 696) distance = 11;
            else if (echo_time < 754) distance = 12;
            else if (echo_time < 812) distance = 13;
            else if (echo_time < 870) distance = 14;
            else if (echo_time < 928) distance = 15;
            else if (echo_time < 986) distance = 16;
            else distance = 17;
        end
    end
    
endmodule  


현재 보드의 lut은 6개의 신호선으로 32경우의수 선택가능
32경우가 넘어서면 lut을 더 사용해야함, 이때 lut을 2개 이상 사용하게 되면 2개의 lut중 하나를 선택하기 위한 또 다른 lut이 필요하게 됨. 따라서 적은 경우의 수인경우 if-else문이나 case문을 사용하는것이 slack을 더 확보할수있겠지만 경우의 수가 늘어날수록 slack이 확연히 줄어든다.

클락을 조절

데이터의 클락의 앞뒤 여유시간

셋타임, 홀드타임


요구시간 - 도달시간 = 슬랙(여유시간)

클락 조절

  module HC_SR04_cntr (
    input clk, reset_p, 
    input hc_sr04_echo,
    output reg hc_sr04_trig,
    output reg [21:0] distance,
    output [7:0] led_debug);
    
    // For Test
    assign led_debug[3:0] = state;
    
    // Define state 
    parameter S_IDLE                      = 4'b0001;
    parameter S_10US_TTL               = 4'b0010;
    parameter S_WAIT_PEDGE           = 4'b0100;
    parameter S_CALC_DIST             = 4'b1000;
    
    // Define state, next_state value.
    reg [3:0] state, next_state;
    reg [1:0] echo_time;
    
    // 언제 next_state를 state 변수에 넣는가?
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) state = S_IDLE;
        else state = next_state;
    end
    
    // get 10us negative one cycle pulse
    wire clk_usec;
    clock_div_100   usec_clk( .clk(clk), .reset_p(reset_p), .clk_div_100_nedge(clk_usec));     // 1us
    
    reg cnt_e;
    wire [11:0] cm;
    sr04_div_58(.clk(clk), .reset_p(reset_p), 
        .clk_usec(clk_usec), .cnt_e(cnt_e), .cm(cm));
    
    // making usec counter.
    reg [21:0] counter_usec;
    reg counter_usec_en;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) begin counter_usec = 0;
        end else if(clk_usec && counter_usec_en) counter_usec = counter_usec + 1;
        else if(!counter_usec_en) counter_usec = 0;
    end
    
    
    // hc_sr04_data의 Negative edge, Positive edge 얻기.
    wire hc_sr04_echo_n_edge, hc_sr04_echo_p_edge;
    edge_detector_p edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(hc_sr04_echo), .n_edge(hc_sr04_echo_n_edge), .p_edge(hc_sr04_echo_p_edge));
    
    // 상태 천이도에 따른 case문 정의
    // 각 상태에 따른 동작 정의
    always @(negedge clk or posedge reset_p) begin
        if(reset_p) begin
            next_state = S_IDLE;
            counter_usec_en = 0;
            cnt_e = 0;  
        end else begin
            case(state)
                S_IDLE : begin        
                    if(counter_usec < 22'd3_000_000) begin
                        counter_usec_en = 1;  
                        hc_sr04_trig = 0;
                    end
                    else begin
                        counter_usec_en = 0;
                        next_state = S_10US_TTL;
                    end
                end
                
                
                
                S_10US_TTL : begin
                    if(counter_usec < 22'd10) begin
                        counter_usec_en = 1;
                        hc_sr04_trig = 1;
                    end
                    else begin
                        hc_sr04_trig = 0;
                        counter_usec_en = 0;
                        next_state = S_WAIT_PEDGE;
                    end
                end
                
                
                
                S_WAIT_PEDGE :  
                    if(hc_sr04_echo_p_edge) begin
                         next_state = S_CALC_DIST;    
                         cnt_e = 1;
                    end     
                
                
                
                S_CALC_DIST : begin          
                     if(hc_sr04_echo_n_edge) begin
                                distance = cm;
                                cnt_e = 0;
                                next_state = S_IDLE;
                      end
                      else next_state = S_CALC_DIST;
                end
            endcase
        end
    end
    
//    always @(posedge clk or posedge reset_p)begin
//        if(reset_p) distance = 0;
//        else begin
//            if(echo_time < 174) distance = 2;
//            else if (echo_time < 232) distance = 3;
//            else if (echo_time < 290) distance = 4;
//            else if (echo_time < 348) distance = 5;
//            else if (echo_time < 406) distance = 6;
//            else if (echo_time < 464) distance = 7;
//            else if (echo_time < 522) distance = 8;
//            else if (echo_time < 580) distance = 9;
//            else if (echo_time < 638) distance = 10;
//            else if (echo_time < 696) distance = 11;
//            else if (echo_time < 754) distance = 12;
//            else if (echo_time < 812) distance = 13;
//            else if (echo_time < 870) distance = 14;
//            else if (echo_time < 928) distance = 15;
//            else if (echo_time < 986) distance = 16;
//            else if (echo_time < 1044) distance = 17;
//            else if (echo_time < 1102) distance = 18;
//            else if (echo_time < 1160) distance = 19;
//            else if (echo_time < 1218) distance = 20;
//            else if (echo_time < 1276) distance = 21;
//            else if (echo_time < 1334) distance = 22;
//            else if (echo_time < 1392) distance = 23;
//            else if (echo_time < 1450) distance = 24;
//            else if (echo_time < 1508) distance = 25;
//            else if (echo_time < 1566) distance = 26;
//            else if (echo_time < 1624) distance = 27;
//            else if (echo_time < 1682) distance = 28;
//            else if (echo_time < 1740) distance = 29;
//            else if (echo_time < 1798) distance = 30;
//            else if (echo_time < 1856) distance = 31;
//            else if (echo_time < 1914) distance = 32;
//            else if (echo_time < 1972) distance = 33;
//            else if (echo_time < 2030) distance = 34;
//            else distance = 35;
//        end
//    end
    
endmodule 

58분주 생성

module sr04_div_58(
    input clk, reset_p,
    input clk_usec, cnt_e,
    output reg [11:0] cm);
    
    reg [5:0] cnt;
    
    always @(negedge clk or posedge reset_p)begin
        if(reset_p)begin
            cnt = 0;
            cm = 0;
        end
        else if(clk_usec)begin
            if(cnt_e)begin
                if(cnt >= 57)begin
                    cnt = 0;
                    cm = cm + 1;
                end
                else cnt = cnt + 1;
            end       
        end
        else if(!cnt_e)begin
            cnt = 0; 
            cm = 0;
    end
    end
    
endmodule

profile
개인 기록공간

0개의 댓글