7/22 키패드, FSM, 온습도 센서

정유석·2024년 7월 22일

교육 - 베릴로그

목록 보기
13/28

키패드

포트를 절약하기 위해 선 줄이기, 각각 하면 16개 필요하지만 8개의 포트로 동작포트로 동작

버튼 pdt 고려
상승엣지에서 col, row 둘다 읽으면 input(row)을 제대로 읽을 수 없다, 8ms주기의 클락에서 하이레벨 로우레벨 각각 4ms이다 따라서 col이든 row든 하나는 상승엣지 하나는 하강엣지로 하면 제대로 읽을 수 있다.

키패드 컨트롤 모듈 생성

module key_pad_cntr(
    input clk, reset_p,
    input [3:0] row,
    output reg [3:0] col,
    output reg [3:0] key_value,
    output reg key_valid);
    //채터링 방지를 위해 한 버튼당 8ms
    reg [19:0] clk_div; //분주를 위해 20번 비트 사용 
    always @(posedge clk) clk_div = clk_div + 1;
    wire clk_8msec_p, clk_8msec_n;
    edge_detector_p ed_btn(.clk(clk), .reset_p(reset_p),
        .cp(clk_div[19]), .n_edge(clk_8msec_n), .p_edge(clk_8msec_p));
        
    always @(posedge clk or posedge reset_p)begin
        if(reset_p) col=4'b0001;          //링카운터가 계속돌아 다시 버튼을 누른 행으로 돌아오면 엣지 2번발생
        else if(clk_8msec_p && !key_valid)begin //따라서 버튼이 눌렸을때는 링카운터 멈춤
            case(col)
                4'b0001: col = 4'b0010;
                4'b0010: col = 4'b0100;
                4'b0100: col = 4'b1000;
                4'b1000: col = 4'b0001;
                default: col = 4'b0001;
            endcase
        end
    end
    
    always @(posedge clk or posedge reset_p)begin
        if(reset_p)begin
            key_value = 0;
            key_valid = 0; //키가 눌렸을때를 알려주는 값
        end
        else begin
            if(clk_8msec_n)begin //버튼 pdt고려하여 버튼의 n엣지에서 읽음
                if(row)begin
                    key_valid = 1;
                    case({col, row})
                        8'b0001_0001: key_value = 4'h0;
                        8'b0001_0010: key_value = 4'h1;
                        8'b0001_0100: key_value = 4'h2;
                        8'b0001_1000: key_value = 4'h3;
                        
                        8'b0010_0001: key_value = 4'h4;
                        8'b0010_0010: key_value = 4'h5;
                        8'b0010_0100: key_value = 4'h6;
                        8'b0010_1000: key_value = 4'h7;
                        
                        8'b0100_0001: key_value = 4'h8;
                        8'b0100_0010: key_value = 4'h9;
                        8'b0100_0100: key_value = 4'ha;
                        8'b0100_1000: key_value = 4'hb;
                        
                        8'b1000_0001: key_value = 4'hc;
                        8'b1000_0010: key_value = 4'hd;
                        8'b1000_0100: key_value = 4'he;
                        8'b1000_1000: key_value = 4'hf;
                    endcase
                end
                else begin
                    key_valid = 0;
                    //key_vlaue = 0; // 버튼을 떼면 다시 0으로 초기화
                end
            end    
        end
    end        
endmodule

키패드 동작 모듈

module keypad_test_top(
    input clk, reset_p,
    input [3:0] row,
    output [3:0] col,
    output  [3:0] com,
    output [7:0] seg_7,
    output led_key_valid
);

    wire [3:0] key_value;
    key_pad_cntr(.clk(clk), .reset_p(reset_p),
    .row(row), .col(col),
    .key_value(key_value),
    .key_valid(led_key_valid));
    
    fnd_cntr fnd (.clk(clk), .reset_p(reset_p), 
        .value({12'b0, key_value}), .com(com), .seg_7(seg_7));

endmodule

XDC

#Pmod Header JB
set_property -dict { PACKAGE_PIN A14   IOSTANDARD LVCMOS33 } [get_ports {col[0]}];#Sch name = JB1
set_property -dict { PACKAGE_PIN A16   IOSTANDARD LVCMOS33 } [get_ports {col[1]}];#Sch name = JB2
set_property -dict { PACKAGE_PIN B15   IOSTANDARD LVCMOS33 } [get_ports {col[2]}];#Sch name = JB3
set_property -dict { PACKAGE_PIN B16   IOSTANDARD LVCMOS33 } [get_ports {col[3]}];#Sch name = JB4
set_property -dict { PACKAGE_PIN A15   IOSTANDARD LVCMOS33 PULLDOWN TRUE} [get_ports {row[0]}];#Sch name = JB7
set_property -dict { PACKAGE_PIN A17   IOSTANDARD LVCMOS33 PULLDOWN TRUE} [get_ports {row[1]}];#Sch name = JB8
set_property -dict { PACKAGE_PIN C15   IOSTANDARD LVCMOS33 PULLDOWN TRUE} [get_ports {row[2]}];#Sch name = JB9
set_property -dict { PACKAGE_PIN C16   IOSTANDARD LVCMOS33 PULLDOWN TRUE} [get_ports {row[3]}];#Sch name = JB10

LED XDC

set_property -dict { PACKAGE_PIN E19   IOSTANDARD LVCMOS33 } [get_ports {led_key_valid}]

기존의 링카운터와는 다르게 key_valid==1이면 링카운터 멈춤

FSM

FSM은 유한한 수의 상태를 가지며, 입력에 따라 상태 간 전이가 일어나는 추상적인 기계입니다.

키패드 컨트롤 모듈 생성(FSM 동작)

module key_pad_cntr_FSM(
    input clk, reset_p,
    input [3:0] row,
    output reg [3:0] col,
    output reg [3:0] key_value,
    output reg key_valid);
    
    reg [19:0] clk_div; //분주를 위해 20번 비트 사용 
    always @(posedge clk) clk_div = clk_div + 1;
    wire clk_8msec;
    edge_detector_p ed_btn(.clk(clk), .reset_p(reset_p),
        .cp(clk_div[19]), .p_edge(clk_8msec));
        
    reg [3:0] state, next_state;
    //FSM 동작
    always @(posedge clk or posedge reset_p)begin
        if(reset_p) state = 4'b0001;
        else if(clk_8msec) state = next_state;
    end
    
    always @* begin //와일드카드:case, if등 조건문에 사용되는 변수들과 우변에있는 변수들
        case(state)
            4'b0001: begin
                if(row == 0) next_state = 4'b0010; //key_valid==1이면 바뀌지않고 (else)현상태 유지
                else next_state = 4'b0001;
            end
            4'b0010: begin
                if(row == 0) next_state = 4'b0100;
                else next_state = 4'b0010;
            end
            4'b0100: begin
                if(row == 0) next_state = 4'b1000;
                else next_state = 4'b0100;
            end
            4'b1000: begin
                if(row == 0) next_state = 4'b0001;
                else next_state = 4'b1000;
            end
            default: next_state = 4'b0001;
        endcase
    end
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p)begin
            key_value = 0;
            key_valid = 0;
            col = 0;
        end
        else if(clk_8msec)begin
            if(row)begin
                    key_valid = 1;
                    case({col, row})
                        8'b0001_0001: key_value = 4'h0;
                        8'b0001_0010: key_value = 4'h1;
                        8'b0001_0100: key_value = 4'h2;
                        8'b0001_1000: key_value = 4'h3;
                        
                        8'b0010_0001: key_value = 4'h4;
                        8'b0010_0010: key_value = 4'h5;
                        8'b0010_0100: key_value = 4'h6;
                        8'b0010_1000: key_value = 4'h7;
                        
                        8'b0100_0001: key_value = 4'h8;
                        8'b0100_0010: key_value = 4'h9;
                        8'b0100_0100: key_value = 4'ha;
                        8'b0100_1000: key_value = 4'hb;
                        
                        8'b1000_0001: key_value = 4'hc;
                        8'b1000_0010: key_value = 4'hd;
                        8'b1000_0100: key_value = 4'he;
                        8'b1000_1000: key_value = 4'hf;
                    endcase
            end
            else key_valid = 0;
        end
        else begin            
            case(state)
                4'b0001:col = 4'b0001;
                4'b0010:col = 4'b0010;
                4'b0100:col = 4'b0100;
                4'b1000:col = 4'b1000;
            endcase
        end
    end        
endmodule

FSM

module key_pad_cntr_FSM(
    input clk, reset_p,
    input [3:0] row,
    output reg [3:0] col,
    output reg [3:0] key_value,
    output reg key_valid);
    
    parameter SCAN0 = 5'b00001;
    parameter SCAN1 = 5'b00010;
    parameter SCAN2 = 5'b00100;
    parameter SCAN3 = 5'b01000;
    parameter KEY_PROCESS = 5'b10000;
    
    reg [19:0] clk_div; //분주를 위해 20번 비트 사용 
    always @(posedge clk) clk_div = clk_div + 1;
    wire clk_8msec;
    edge_detector_p ed_btn(.clk(clk), .reset_p(reset_p),
        .cp(clk_div[19]), .p_edge(clk_8msec));
        
    reg [4:0] state, next_state;
    //FSM 동작
    always @(posedge clk or posedge reset_p)begin
        if(reset_p) state = SCAN0;
        else if(clk_8msec) state = next_state;
    end
    
    always @* begin //뭐든 입력이 변하면 동작하라
        case(state)
            SCAN0: begin
                if(row == 0) next_state = SCAN1; //key_valid==1이면 바뀌지않고 (else)현상태 유지
                else next_state = KEY_PROCESS;
            end
            SCAN1: begin
                if(row == 0) next_state = SCAN2;
                else next_state = KEY_PROCESS;
            end
            SCAN2: begin
                if(row == 0) next_state = SCAN3;
                else next_state = KEY_PROCESS;
            end
            SCAN3: begin
                if(row == 0) next_state = SCAN3;
                else next_state = KEY_PROCESS;
            end
            default: state = SCAN0;
        endcase
    end
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p)begin
            key_value = 0;
            key_valid = 0;
            col = 0;
        end
        else begin
            case(state)
                SCAN0:begin col = 4'b0001; key_valid = 0; end
                SCAN1:begin col = 4'b0010; key_valid = 0; end
                SCAN2:begin col = 4'b0100; key_valid = 0; end
                SCAN3:begin col = 4'b1000; key_valid = 0; end
                KEY_PROCESS: begin
                    key_valid = 1;
                    case({col, row})
                        8'b0001_0001: key_value = 4'h0;
                        8'b0001_0010: key_value = 4'h1;
                        8'b0001_0100: key_value = 4'h2;
                        8'b0001_1000: key_value = 4'h3;
                        
                        8'b0010_0001: key_value = 4'h4;
                        8'b0010_0010: key_value = 4'h5;
                        8'b0010_0100: key_value = 4'h6;
                        8'b0010_1000: key_value = 4'h7;
                        
                        8'b0100_0001: key_value = 4'h8;
                        8'b0100_0010: key_value = 4'h9;
                        8'b0100_0100: key_value = 4'ha;
                        8'b0100_1000: key_value = 4'hb;
                        
                        8'b1000_0001: key_value = 4'hc;
                        8'b1000_0010: key_value = 4'hd;
                        8'b1000_0100: key_value = 4'he;
                        8'b1000_1000: key_value = 4'hf;
                    endcase
                    end
//        else if(clk_8msec)begin
//            if(row)begin
//                    key_valid = 1;
//                    case({col, row})
//                        8'b0001_0001: key_value = 4'h0;
//                        8'b0001_0010: key_value = 4'h1;
//                        8'b0001_0100: key_value = 4'h2;
//                        8'b0001_1000: key_value = 4'h3;
                        
//                        8'b0010_0001: key_value = 4'h4;
//                        8'b0010_0010: key_value = 4'h5;
//                        8'b0010_0100: key_value = 4'h6;
//                        8'b0010_1000: key_value = 4'h7;
                        
//                        8'b0100_0001: key_value = 4'h8;
//                        8'b0100_0010: key_value = 4'h9;
//                        8'b0100_0100: key_value = 4'ha;
//                        8'b0100_1000: key_value = 4'hb;
                        
//                        8'b1000_0001: key_value = 4'hc;
//                        8'b1000_0010: key_value = 4'hd;
//                        8'b1000_0100: key_value = 4'he;
//                        8'b1000_1000: key_value = 4'hf;
//                    endcase
//            end
//            else key_valid = 0;
//        end
//        else begin            
//            case(state)
//                4'b0001:col = 4'b0001;
//                4'b0010:col = 4'b0010;
//                4'b0100:col = 4'b0100;
//                4'b1000:col = 4'b1000;
//            endcase
//        end
            endcase
        end
    end        
endmodule

동작 코드

module keypad_test_top(
    input clk, reset_p,
    input [3:0] row,
    output [3:0] col,
    output  [3:0] com,
    output [7:0] seg_7,
    output led_key_valid
);

    wire [3:0] key_value;
    key_pad_cntr_FSM(.clk(clk), .reset_p(reset_p),
    .row(row), .col(col),
    .key_value(key_value),
    .key_valid(led_key_valid));
    
    fnd_cntr fnd (.clk(clk), .reset_p(reset_p), 
        .value({12'b0, key_value}), .com(com), .seg_7(seg_7));

endmodule

FSM 수정

 module key_pad_cntr_FSM (
    input clk, reset_p,
    input [3:0] row,
    output reg [3:0] col,
    output reg [3:0] key_value,
    output reg key_valid );
    
    parameter SCAN0 =            5'b00001;
    parameter SCAN1 =            5'b00010;
    parameter SCAN2 =            5'b00100;
    parameter SCAN3 =            5'b01000;
    parameter KEY_PROCESS =   5'b10000;
 
     // chattering 현사을 방지하기 위해 8ms delay_time을 갖고 button 값을 받겠다.
    reg [19:0] clk_div;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) clk_div = 0;
        else  clk_div = clk_div + 1;
    end
    
    // Get One Cycle Pulse of Button.
    // clk_8msec : Positive edge (버튼이 눌렸을 때를 감지)
    wire clk_8msec;
    edge_detector_p ed_0(.clk(clk), .reset_p(reset_p), .cp(clk_div[19]), .p_edge(clk_8msec));
 
 
    // 8ms 마다 state 값을 nex_state 입력받는다.
    reg [4:0] state, next_state;
    
    // D- Flip Flop 
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) state = SCAN0;
        else if(clk_8msec) state = next_state;
    end
    
    // state 값에 따라 변화하기 때문에 조합 회로이다.
    // row == 0 이면 다음 행으로 이동하고, 
    // row == 1 이면 현재 행에서 유지한다. 
    // row == 0 키 입력이 없음을 의미
    // row == 1 이면 키 입력이 있음을 의미 
    always @(*) begin
        case (state)
            SCAN0:  begin
                if(row == 0) next_state = SCAN1;
                else next_state = KEY_PROCESS;
            end 
            
            SCAN1:  begin
                if(row == 0) next_state = SCAN2;
                else next_state = KEY_PROCESS;
            end 
            
            SCAN2:  begin
                if(row == 0) next_state = SCAN3;
                else next_state = KEY_PROCESS;
            end 
            
            SCAN3:  begin
                if(row == 0) next_state = SCAN0;
                else next_state = KEY_PROCESS;
            end 
            
            KEY_PROCESS:  begin
                if(row == 0) next_state = SCAN0;
                else next_state = KEY_PROCESS;
            end 
            
            default : next_state = SCAN0;
        endcase
    end
    
    // 
//    always @(posedge clk or posedge reset_p) begin
//        if(reset_p) begin
//            key_value = 0;
//            key_valid = 0;
//            col = 0;
//        end
//        else if(clk_8msec) begin
//             if(row)  begin 
//                     key_valid = 1;  
//                     case({col, row})
//                        8'b0001_0001 : key_value = 4'h0;
//                        8'b0001_0010 : key_value = 4'h1;
//                        8'b0001_0100 : key_value = 4'h2;
//                        8'b0001_1000 : key_value = 4'h3;
                        
//                        8'b0010_0001 : key_value = 4'h4;
//                        8'b0010_0010 : key_value = 4'h5;
//                        8'b0010_0100 : key_value = 4'h6;
//                        8'b0010_1000 : key_value = 4'h7;
                        
//                        8'b0100_0001 : key_value = 4'h8;
//                        8'b0100_0010 : key_value = 4'h9;
//                        8'b0100_0100 : key_value = 4'ha;
//                        8'b0100_1000 : key_value = 4'hb;
                        
//                        8'b1000_0001 : key_value = 4'hc;
//                        8'b1000_0010 : key_value = 4'hd;
//                        8'b1000_0100 : key_value = 4'he;
//                        8'b1000_1000 : key_value = 4'hf;
                        
//                        default : key_value = key_value;
//                     endcase
//                end
//                else key_valid = 0;       
//        end
//        case(state)
//                4'b0001 : col = 4'b0001;
//                4'b0010 : col = 4'b0010;
//                4'b0100 : col = 4'b0100;
//                4'b1000 : col = 4'b1000;     
//        endcase
//    end

 always @(posedge clk or posedge reset_p) begin
        if(reset_p) begin
            key_value = 0;
            key_valid = 0;
            col = 0;
        end
        else begin
             case(state) 
                    SCAN0 : begin col = 4'b0001; key_valid = 0; end
                    SCAN1 : begin col = 4'b0010; key_valid = 0; end
                    SCAN2 : begin col = 4'b0100; key_valid = 0; end
                    SCAN3 : begin col = 4'b1000; key_valid = 0; end
                    KEY_PROCESS : begin
                            key_valid = 1;  
                            case({col, row})
                                     8'b0001_0001 : key_value = 4'h0;
                                     8'b0001_0010 : key_value = 4'h1;
                                     8'b0001_0100 : key_value = 4'h2;
                                     8'b0001_1000 : key_value = 4'h3;
                        
                                      8'b0010_0001 : key_value = 4'h4;
                                      8'b0010_0010 : key_value = 4'h5;
                                      8'b0010_0100 : key_value = 4'h6;
                                      8'b0010_1000 : key_value = 4'h7;
                        
                                      8'b0100_0001 : key_value = 4'h8;
                                      8'b0100_0010 : key_value = 4'h9;
                                      8'b0100_0100 : key_value = 4'ha;
                                      8'b0100_1000 : key_value = 4'hb;
                        
                                      8'b1000_0001 : key_value = 4'hc;
                                      8'b1000_0010 : key_value = 4'hd;
                                      8'b1000_0100 : key_value = 4'he;
                                      8'b1000_1000 : key_value = 4'hf;
                        
                                    default : key_value = key_value;
                     endcase
                    end
             endcase
        end
    end
    
 endmodule

상승엣지 하강엣지 추가

module key_pad_cntr_FSM (
   input clk, reset_p,
   input [3:0] row,
   output reg [3:0] col,
   output reg [3:0] key_value,
   output reg key_valid );
   
   parameter SCAN0 =            5'b00001;
   parameter SCAN1 =            5'b00010;
   parameter SCAN2 =            5'b00100;
   parameter SCAN3 =            5'b01000;
   parameter KEY_PROCESS =   5'b10000;

    // chattering 현사을 방지하기 위해 8ms delay_time을 갖고 button 값을 받겠다.
   reg [19:0] clk_div;
   always @(posedge clk or posedge reset_p) begin
       if(reset_p) clk_div = 0;
       else  clk_div = clk_div + 1;
   end
   
   // Get One Cycle Pulse of Button.
   // clk_8msec : Positive edge (버튼이 눌렸을 때를 감지)
   wire clk_8msec;
   edge_detector_p ed_0(.clk(clk), .reset_p(reset_p), 
       .cp(clk_div[19]), .p_edge(clk_8msec_p), .n_edge(clk_8msec_n));


   // 8ms 마다 state 값을 nex_state 입력받는다.
   reg [4:0] state, next_state;
   
   // D- Flip Flop 
   always @(posedge clk or posedge reset_p) begin
       if(reset_p) state = SCAN0;
       else if(clk_8msec_n) state = next_state; //하강엣지로 변경
   end
   
   // state 값에 따라 변화하기 때문에 조합 회로이다.
   // row == 0 이면 다음 행으로 이동하고, 
   // row == 1 이면 현재 행에서 유지한다. 
   // row == 0 키 입력이 없음을 의미
   // row == 1 이면 키 입력이 있음을 의미 
   always @(*) begin
       case (state)
           SCAN0:  begin
               if(row == 0) next_state = SCAN1;
               else next_state = KEY_PROCESS;
           end 
           
           SCAN1:  begin
               if(row == 0) next_state = SCAN2;
               else next_state = KEY_PROCESS;
           end 
           
           SCAN2:  begin
               if(row == 0) next_state = SCAN3;
               else next_state = KEY_PROCESS;
           end 
           
           SCAN3:  begin
               if(row == 0) next_state = SCAN0;
               else next_state = KEY_PROCESS;
           end 
           
           KEY_PROCESS:  begin
               if(row == 0) next_state = SCAN0;
               else next_state = KEY_PROCESS;
           end 
           
           default : next_state = SCAN0;
       endcase
   end
   
   // 
//    always @(posedge clk or posedge reset_p) begin
//        if(reset_p) begin
//            key_value = 0;
//            key_valid = 0;
//            col = 0;
//        end
//        else if(clk_8msec) begin
//             if(row)  begin 
//                     key_valid = 1;  
//                     case({col, row})
//                        8'b0001_0001 : key_value = 4'h0;
//                        8'b0001_0010 : key_value = 4'h1;
//                        8'b0001_0100 : key_value = 4'h2;
//                        8'b0001_1000 : key_value = 4'h3;
                       
//                        8'b0010_0001 : key_value = 4'h4;
//                        8'b0010_0010 : key_value = 4'h5;
//                        8'b0010_0100 : key_value = 4'h6;
//                        8'b0010_1000 : key_value = 4'h7;
                       
//                        8'b0100_0001 : key_value = 4'h8;
//                        8'b0100_0010 : key_value = 4'h9;
//                        8'b0100_0100 : key_value = 4'ha;
//                        8'b0100_1000 : key_value = 4'hb;
                       
//                        8'b1000_0001 : key_value = 4'hc;
//                        8'b1000_0010 : key_value = 4'hd;
//                        8'b1000_0100 : key_value = 4'he;
//                        8'b1000_1000 : key_value = 4'hf;
                       
//                        default : key_value = key_value;
//                     endcase
//                end
//                else key_valid = 0;       
//        end
//        case(state)
//                4'b0001 : col = 4'b0001;
//                4'b0010 : col = 4'b0010;
//                4'b0100 : col = 4'b0100;
//                4'b1000 : col = 4'b1000;     
//        endcase
//    end

always @(posedge clk or posedge reset_p) begin
       if(reset_p) begin
           key_value = 0;
           key_valid = 0;
           col = 0;
       end
       else if(clk_8msec_p)begin //상승엣지로 변경
            case(state) 
                   SCAN0 : begin col = 4'b0001; key_valid = 0; end
                   SCAN1 : begin col = 4'b0010; key_valid = 0; end
                   SCAN2 : begin col = 4'b0100; key_valid = 0; end
                   SCAN3 : begin col = 4'b1000; key_valid = 0; end
                   KEY_PROCESS : begin
                           key_valid = 1;  
                           case({col, row})
                                8'b0001_0001 : key_value = 4'h7; //계산기 키패드 배열로 변경
                                8'b0001_0010 : key_value = 4'h8;
                                8'b0001_0100 : key_value = 4'h9;
                                8'b0001_1000 : key_value = 4'hA;
                       
                                 8'b0010_0001 : key_value = 4'h4;
                                 8'b0010_0010 : key_value = 4'h5;
                                 8'b0010_0100 : key_value = 4'h6;
                                 8'b0010_1000 : key_value = 4'hb;
                   
                                 8'b0100_0001 : key_value = 4'h1;
                                 8'b0100_0010 : key_value = 4'h2;
                                 8'b0100_0100 : key_value = 4'h3;
                                 8'b0100_1000 : key_value = 4'hE;
                   
                                 8'b1000_0001 : key_value = 4'hC;
                                 8'b1000_0010 : key_value = 4'h0;
                                 8'b1000_0100 : key_value = 4'hF;
                                 8'b1000_1000 : key_value = 4'hd;
//                                     8'b0001_0001 : key_value = 4'h0;
//                                     8'b0001_0010 : key_value = 4'h1;
//                                     8'b0001_0100 : key_value = 4'h2;
//                                     8'b0001_1000 : key_value = 4'h3;
                       
//                                      8'b0010_0001 : key_value = 4'h4;
//                                      8'b0010_0010 : key_value = 4'h5;
//                                      8'b0010_0100 : key_value = 4'h6;
//                                      8'b0010_1000 : key_value = 4'h7;
                       
//                                      8'b0100_0001 : key_value = 4'h8;
//                                      8'b0100_0010 : key_value = 4'h9;
//                                      8'b0100_0100 : key_value = 4'ha;
//                                      8'b0100_1000 : key_value = 4'hb;
                       
//                                      8'b1000_0001 : key_value = 4'hc;
//                                      8'b1000_0010 : key_value = 4'hd;
//                                      8'b1000_0100 : key_value = 4'he;
//                                      8'b1000_1000 : key_value = 4'hf;
                       
                                   default : key_value = key_value;
                    endcase
                   end
            endcase
       end
   end
   
endmodule

버튼 누르면 카운트 증가

module keypad_test_top(
   input clk, reset_p,
   input [3:0] row,
   output [3:0] col,
   output  [3:0] com,
   output [7:0] seg_7,
   output led_key_valid
);

   wire [3:0] key_value;
   wire key_valid;
   key_pad_cntr_FSM(.clk(clk), .reset_p(reset_p),
       .row(row), .col(col),
       .key_value(key_value),
       .key_valid(led_key_valid));
   assign led_key_valid = key_valid;
   
   wire key_valid_p;
    edge_detector_p ed(.clk(clk), .reset_p(reset_p), 
       .cp(key_valid), .p_edge(key_valid_p));
       
   reg [15:0] key_count;
   always @(posedge clk or posedge reset_p)begin
       if(reset_p)key_count = 0;
       else if(key_valid_p)begin
           key_count = key_count + 1;
       end
   end
   
   fnd_cntr fnd (.clk(clk), .reset_p(reset_p), 
       .value(key_count), .com(com), .seg_7(seg_7));

endmodule

버튼 마다 다른 역할 부여

module keypad_test_top(
    input clk, reset_p,
    input [3:0] row,
    output [3:0] col,
    output  [3:0] com,
    output [7:0] seg_7,
    output led_key_valid
);

    wire [3:0] key_value;
    wire key_valid;
    key_pad_cntr_FSM(.clk(clk), .reset_p(reset_p),
        .row(row), .col(col),
        .key_value(key_value),
        .key_valid(led_key_valid));
    assign led_key_valid = key_valid;
    
    wire key_valid_p;
     edge_detector_p ed(.clk(clk), .reset_p(reset_p), 
        .cp(key_valid), .p_edge(key_valid_p));
        
    reg [15:0] key_count;
    always @(posedge clk or posedge reset_p)begin
        if(reset_p)key_count = 0;
        else if(key_valid_p)begin
            if(key_value == 1)key_count = key_count + 1;
            else if(key_value == 2)key_count = key_count - 1;
            else if(key_value == 3)key_count = key_count + 2;
        end
    end
    
    fnd_cntr fnd (.clk(clk), .reset_p(reset_p), 
        .value(key_count), .com(com), .seg_7(seg_7));

endmodule

온습도 센서


풀업저항 필요

풀업저항이 달려있는 센서

DHT11 데이터시트 참조

전체적인 통신 과정


첫 구간 : 약속된 프로토콜에 의한 시간만큼 0과1을 보내 통신 확인

0과1을 보내는데 약속된 시간동안 1을 보내면서 한 비트에 해당하는 신호가 0인지 1인지 정함

이것을 40비트동안 반복한뒤 신호를 임피던스 상태로 끊음, 하나의 데이터선을 공유하기 때문

profile
개인 기록공간

0개의 댓글