Harman 세미콘 아카데미/Verilog

2024.7.2 [Verilog]11 - 키패드, 습도센서

U_Pong 2024. 7. 2. 19:22

2024.7.2 수업날

오늘은 키패드, 습도센서를 Basys3 보드에 연결하여 결과를 관찰해보자


< 키패드 >

이번에 사용할 키패드는 4x4의 키패드이다.

아래 사진과 같이 16개의 버튼이 있으며, 버튼을 사용하여 문자, 기호를 표현하는 기능을 가졌다.

 

 

본격적으로 Basys3 보드에 연결하기 전에 임피던스에 대해 알아야한다.

전류를 잘 흐르지 못하게 하는 저항이 주파수에 따라 달라지는 저항값을 임피던스라고 한다.

 

임피던스에는 하이(HIGH) 임피던스가 있다. 

하나의 신호선에 복수의 출력 소자를 연결하는 경우에는 신호를 출력할 소자와 수신할 소자만 연결되어 있어야한다.

만약 회로 제어를 잘못하여 복수의 출력 회로가 동시에 접속되면, 소자가 파괴될 수 있다.

이런 위험을 방지하기 위해 출력하지 말아야 할 소자는 전기적으로 절연 상태이어야 한다.

이 상태에서 버튼을 누르면 3V3, 접지가 동시에 접속되어 소자가 망가질 수 있다.

 

출력 신호선에서 전기적으로 절연된 상태를 하이 임피던스라고 한다.

어떤 입력 단자에 연결된 모든 출력 단자가 동시에 하이 임피던스 상태가 되면 전기적으로 입력 단자에 아무것도 연결되지 않는 상태와 동일해지므로 소자 파괴의 위험이 생긴다. 그래서 풀업 또는 풀다운 저항을 하는 것이 일반적이다.

- 풀업 저항: 전원선에 높은 저항을 연결한 경우

 

- 풀 다운 저항: 접지선에 높은 저항을 연결한 경우

 

풀업, 풀다운된 입력단자는 출력 단자가 연결되지 않는 상태에도 풀업이나 풀다운에의해 전원 전압이나 접지 전압이 유지된다.

 

다음으로 키패드 데이터시트를 확인해보자.

키패드는 4개의 입력선, 4개의 출력선이 버튼을 통해 연결되어 있다.

 

 

keypad_cntr_FSM 소스코드
////////////////////////////////////////////////////2024.7.2
///////////// 키패드 컨트롤러, 링카운터와 유사, 1ms에 한번씩 읽음(채터링 때문)
module keypad_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 SCAN_0 = 5'b00001;          // 열 0을 스캔하는 상태
	parameter SCAN_1 = 5'b00010;          // 열 1을 스캔하는 상태
	parameter SCAN_2 = 5'b00100;          // 열 2를 스캔하는 상태
	parameter SCAN_3 = 5'b01000;          // 열 3을 스캔하는 상태
	parameter KEY_PROCESS = 5'b10000;     // 키 입력을 처리하는 상태
    
    reg [4:0] state, next_state; // 현재 상태와 다음 상태를 저장하는 레지스터

	// 조합회로 블록: clk 신호를 직접적으로 받지 않으며, 상태 전환을 처리
	always @* begin
    	case(state) // 현재 상태에 따라 다음 상태를 결정
        	SCAN_0: begin
            	if(row == 0) next_state = SCAN_1; // 행 값이 0이면 다음 상태로 전환
            	else next_state = KEY_PROCESS; // 그렇지 않으면 키 처리 상태로 전환
        	end
        
        	SCAN_1: begin
            	if(row == 0) next_state = SCAN_2; // 행 값이 0이면 다음 상태로 전환
            	else next_state = KEY_PROCESS; // 그렇지 않으면 키 처리 상태로 전환
        	end 
        
        	SCAN_2: begin
            	if(row == 0) next_state = SCAN_3; // 행 값이 0이면 다음 상태로 전환
            	else next_state = KEY_PROCESS; // 그렇지 않으면 키 처리 상태로 전환
        	end 
        
        	SCAN_3: begin
            	if(row == 0) next_state = SCAN_0; // 행 값이 0이면 다음 상태로 전환
            	else next_state = KEY_PROCESS; // 그렇지 않으면 키 처리 상태로 전환
        	end
        
        	KEY_PROCESS: begin
            	if(row == 0) next_state = SCAN_0; // 행 값이 0이면 스캔 상태로 초기화
            	else next_state = KEY_PROCESS; // 그렇지 않으면 키 처리 상태 유지
        	end      
   	 	endcase
	end
    
    	wire clk_8msec_n, clk_8msec_p; // 8밀리초 클럭의 하강 및 상승 에지 신호
    
	// 상태 레지스터의 동작을 정의하는 블록
	always @(posedge clk or posedge reset_p) begin
    	if(reset_p) state = SCAN_0; // 리셋 시 상태를 SCAN_0으로 초기화
    	else if(clk_8msec_p) state = next_state; // 8밀리초 클럭 상승 에지 시 다음 상태로 전환
	end

	// 클럭 분주기: 8밀리초 클럭을 생성하기 위해 클럭을 분주
	reg [19:0] clk_div;
	always @(posedge clk) clk_div = clk_div + 1; // 클럭 신호에 따라 분주기 증가

	// 에지 검출기 인스턴스
	edge_detector_n ed(
    	.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) begin
        	col = 4'b0001;      // 리셋 시 열 신호 초기화
        	key_value = 0;      // 리셋 시 키 값 초기화
        	key_valid = 0;      // 리셋 시 키 유효성 초기화
    	end
    	else if(clk_8msec_n) begin // 8밀리초 클럭의 하강 에지 시 동작
        	case(state)
            	SCAN_0: begin 
                	col = 4'b0001; // 열 0 스캔
                	key_valid = 0; // 키 유효성 초기화
            	end
                
            	SCAN_1: begin 
                col = 4'b0010; // 열 1 스캔
                key_valid = 0; // 키 유효성 초기화
            	end   
                
            	SCAN_2: begin 
                	col = 4'b0100; // 열 2 스캔
                	key_valid = 0; // 키 유효성 초기화
            	end   
                
            	SCAN_3: begin 
                	col = 4'b1000; // 열 3 스캔
                	key_valid = 0; // 키 유효성 초기화
            	end       
            	KEY_PROCESS: begin
                	key_valid = 1; // 키 유효성 설정
                	case({col, row})
                    	8'b0001_0001: key_value = 4'h0; // 키 0
                    	8'b0001_0010: key_value = 4'h1; // 키 1
                    	8'b0001_0100: key_value = 4'h2; // 키 2
                    	8'b0001_1000: key_value = 4'h3; // 키 3

                    	8'b0010_0001: key_value = 4'h4; // 키 4
                    	8'b0010_0010: key_value = 4'h5; // 키 5
                    	8'b0010_0100: key_value = 4'h6; // 키 6
                    	8'b0010_1000: key_value = 4'h7; // 키 7

                    	8'b0100_0001: key_value = 4'h8; // 키 8
                    	8'b0100_0010: key_value = 4'h9; // 키 9
                    	8'b0100_0100: key_value = 4'hA; // 키 A
                    	8'b0100_1000: key_value = 4'hb; // 키 B

                    	8'b1000_0001: key_value = 4'hC; // 키 C
                    	8'b1000_0010: key_value = 4'hd; // 키 D
                    	8'b1000_0100: key_value = 4'hE; // 키 E
                    	8'b1000_1000: key_value = 4'hF; // 키 F
                	endcase
            	end
        	endcase
    	end
	end
    
endmodule

이 소스코드에서는 키패드 입력을 처리하는 상태 기계(FSM)을 사용하였다.

 

FSM과 링카운터는 모두 디지털 회로에서 상태를 관리하는 방법이지만, 둘은 차이가 있다.

FSM은 현재 상태와 입력 신호에 따라 다음 상태로 전이한다. 그리고 일반적으로 상태 전이는 클럭 신호에 의해 동기화된다.

링카운터는 시프트 레지스터의 일종으로, 하나의 1비트가 링 형태로 순환하는 구조이다. 그리고 정해진 순서대로 상태가 순환한다.

 

keypad_cntr_FSM의 상태도를 예시로 들어보자.

key_valid가 1이 되지마자(key_process에 값이 들어왔을 때) key_pross에서 머무르고,

key_valid가 0이 되면 0001에서부터 시작해서 kv=0(파란색 화살표)를 따라 순서대로 진행된다.

즉, FSM은 어떤 특정 조건에 따라 머무르기도 하고, 되돌아가기도하는 왔다갔다하는 것이다.

 

 

이제 test_top에 keypad_cntr_FSM과 연결한 소스코드를 만들어보자.

key_pad_test_top 소스코드
/////////////////////////////////////////////////// 2024.7.2
///////////////////// 키패드 컨트롤러
module key_pad_test_top(
       input clk, reset_p,
       input [3:0] row,
       output [3:0] col,
       output [3:0] com,
       output [7:0] seg_7);
       
      wire [3:0] key_value; 
      wire key_valid;   
      keypad_cntr_FSM keypad(clk, reset_p, row, col, key_value, key_valid);
      
      wire[15:0] value;
      assign value = {12'b0, key_value};              //1의 자리 fnd에만 결과 출력, 다 출력하고 싶으면 key_value를 선언하면 됨
      fnd_4digit_cntr fnd(clk, reset_p, value, seg_7, com);

      
endmodule

fnd 컨트롤러에 출력하고자 하는 값이 출력되는지 보기 위해 하단에 추가하였다.

 

.xdc 파일에서는 Basys3 보드의 JC 부분에 키패드를 연결하기 때문에 아래와 같이 수정한다.

JC1~JC4까지는 풀다운을 적어준다.

 

이제 Basys3과 4x4 키패드를 연결한다.

JC에는 맨 아래가 3V3, 아래에서 두번째가 GND이기 때문에 순서에 주의한다.

.xdc파일에서 JC1~JC4, JC7~JC10 을 모두 사용한다고 했으니 총 8개의 포트를 사용한다. 

 

키패드에는 C1~C4, R1~R4 번의 핀이 있다.

.xdc에서 row0~row3은 Basys3의 JC1~JC4로 설정했으므로 키패드의 R1~R4번과 연결하고,

col0~col3은 Basys3의 JC7~JC10으로 설정했으므로 키패드의 C1~C4번과 연결한다.

 

그러면 아래와 같이 키패드의 S1, S5, S9, S13, S2, S6, S10, S14, S3, S7, S11, S15, S4, S78, S12, S16 버튼 순서대로 fnd에 숫자가 증가하는 것을 확인할 수 있다.

키패드와 Basys3 보드에 선을 어떻게 연결하느냐에 따라 fnd에 출력되는 숫자는 달라질 수 있다.

예를 들어 S13 버튼을 누르면 나의 Basys3 보드를 기준으로 3이 출력되는데, 다른 사람의 Basys3 보드로는 d가 출력될 수도 있는 것이다.

key_pad_test_top 결과

 

 

키패드라고 하면 계산기에서도 키패드를 확인해볼 수 있다.

이번에는 아래와 같은 위치의 버튼을 눌렀을 때, 해당하는 숫자가 출력되도록 소스코드를 만들어보자.

c는 초기화라는 의미이며, 사칙연산과 등호는 각각 빨간 알파벳으로 fnd에 출력되도록 한다.

 

calculator_keypad_cntr_FSM 소스코드
///////////// 키패드 컨트롤러, 링카운터와 유사, 1ms에 한번씩 읽음(채터링 때문)
module calculator_keypad_cntr_FSM(
      input clk, reset_p,
      input [3:0] row, 
      output reg [3:0] col,                     // always안에서 쓰이면 reg 변수로 써야함
      output reg [3:0] key_value,            //0~15까지 필요--> 2^4=16
      output reg key_valid);
      
      //상수 선언, 대문자로 적는다, 상수는 한번 선언하면 중복해서 선언할 수 없음
      parameter SCAN_0               = 5'b00001;
      parameter SCAN_1               = 5'b00010;
      parameter SCAN_2               = 5'b00100;
      parameter SCAN_3               = 5'b01000;
      parameter KEY_PROCESS    = 5'b10000;
      
      reg [4:0] state, next_state;
      
      always @* begin         //조합회로, clk를 직접적으로 받지 않음, 상태의 처리를 작성
            case(state)
                  SCAN_0: begin
                        if(row == 0) next_state = SCAN_1;
                        else next_state = KEY_PROCESS;
                  end
                  
                  SCAN_1: begin
                        if(row == 0) next_state = SCAN_2;
                        else next_state = KEY_PROCESS;
                  end 
                  
                  SCAN_2: begin
                        if(row == 0) next_state = SCAN_3;
                        else next_state = KEY_PROCESS;
                  end 
                  
                  SCAN_3: begin
                        if(row == 0) next_state = SCAN_0;
                        else next_state = KEY_PROCESS;
                  end
                  
                  KEY_PROCESS: begin
                        if(row == 0) next_state = SCAN_0;
                        else next_state = KEY_PROCESS;
                  end      
            endcase
      end
      
      wire clk_8msec_n, clk_8msec_p;                  // 실제 상태천이가 일어나는 곳은 여기
      always @(posedge clk or posedge reset_p) begin
            if(reset_p) state = SCAN_0;
            else if(clk_8msec_p) state = next_state;
      end
      
      
      reg [19:0] clk_div;
      always @(posedge clk) clk_div = clk_div + 1;
      
      //
      edge_detector_n ed(
            .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)begin
                  col = 4'b0001;
                  key_value = 0;
                  key_valid  = 0;
            end
            else if(clk_8msec_n)begin
                  case(state)
                        SCAN_0: begin col = 4'b0001; key_valid = 0; end
                        SCAN_1: begin col = 4'b0010; key_valid = 0; end   
                        SCAN_2: begin col = 4'b0100; key_valid = 0; end   
                        SCAN_3: begin col = 4'b1000; key_valid = 0; end       
                        KEY_PROCESS: begin
                              key_valid = 1;
                              case({col, row})
                                    8'b0001_0001: key_value = 4'h7;     //7
                                    8'b0001_0010: key_value = 4'h4;     //4
                                    8'b0001_0100: key_value = 4'h1;     //1
                                    8'b0001_1000: key_value = 4'hC;     //C
                        
                                    8'b0010_0001: key_value = 4'h8;     //8
                                    8'b0010_0010: key_value = 4'h5;     //그대로, 5
                                    8'b0010_0100: key_value = 4'h2;     //2
                                    8'b0010_1000: key_value = 4'h0;     //0
                        
                                    8'b0100_0001: key_value = 4'h9;     //9
                                    8'b0100_0010: key_value = 4'h6;     //6
                                    8'b0100_0100: key_value = 4'h3;     //3
                                    8'b0100_1000: key_value = 4'hF;     //F
                        
                                    8'b1000_0001: key_value = 4'ha;     //a
                                    8'b1000_0010: key_value = 4'hb;     //b
                                    8'b1000_0100: key_value = 4'hE;     //그대로, E
                                    8'b1000_1000: key_value = 4'hd;     //d     
                              endcase
                        end
                  endcase
            end
      end

endmodule

keypad_cntr_FSM에서 각 버튼에 해당하는 4x4 키패드의 숫자와 문자의 위치를 기억하고,

위에서 만들고자 하던 계산기 키패드의 숫자와 사칙연산의 위치로 수정해주기만 하면 된다.

 

cal_key_pad_test_top 소스코드
///////////////////////////////////////////// 계산기 키패드 컨트롤러+led
module cal_key_pad_test_top(
       input clk, reset_p,
       input [3:0] row,
       output [3:0] col,
       output [3:0] com,
       output [7:0] seg_7,
       output key_valid);
       
      wire [3:0] key_value;
      calculator_keypad_cntr_FSM keypad(clk, reset_p, row, col, key_value, key_valid);
      
      wire[15:0] value;
      assign value = {12'b0, key_value};              //1의 자리 fnd에만 결과 출력, 다 출력하고 싶으면 key_value를 선언하면 됨
      fnd_4digit_cntr fnd(clk, reset_p, value, seg_7, com);

      
endmodule

Basys3 보드에 결과를 확인해보기 위해서 cal_key_pad_test_top 소스코드를 만들었다.

마찬가지로 fnd 컨트롤러에 출력하고자 하는 값이 출력되는지 보기 위해 하단에 추가하였다.

이번에는 키패드의 버튼을 누를 때마다 led가 켜지도록 하는 기능도 추가하였다.

 

led가 켜지도록 하기 위하여 .xdc 파일에 아래와 같이 수정한다.

 

Basys3 보드와 연결하여 원하는 위치에 숫자, 문자를 출력하는 계산기 키패드가 나타나는 것을 확인할 수 있다.

cal_key_pad_test_top 결과

 

 

< 습도 센서 >

dht11이라는 습도 센서란 습도를 측정해주는 센서이다.

 

아래의 파일은 dht11의 데이터시트와 관련된 설명이 담긴 파일이다.

DHT11.PDF
1.44MB

 

 

습도센서에는 아래와 같이 vdd에 5K저항이 연결되어있다.

이는 키패드에서도 말했던 풀업저항 구조이다.

 

아래의 표는 다음과 같은 의미를 나타낸다.

1. Measurement Range

- 습도: 20%~90& RH

- 온도: 0~50도 → 센서가 측정할 수 있는 습도 및 온도의 범위를 나타낸다.

2. Humidity Accuracy: 습도를 측정할 때 ±5% 정도의 오차가 있을 수 있음을 나타낸다.

3. Resolution: 측정값의 최소 변화 단위를 나타낸다. 여기서는 습도와 온도 모두 정수 단위로 표현된다는 것을 의미한다.

4. Package: DHT11 센서의 패키지가 4핀 싱글 로우(단일 행) 형태임을 나타낸다.

 

1. Data Single-Bus(한 개의 데이터 핀을 사용) Free 상태: 초기 상태에서 데이터 핀은 High 상태

2. MCU 시작 신호 전송:

    - MCU가 Single-Bus 신호를 Low 상태로 바꾼다.

    - 이 상태를 최소 18ms 동안 유지하여 DHT11이 신호를 감지할 수 있도록 한다.

3. MCU 대기 및 응답 확인:

    - MCU는 다시 신호를 High로 올리고, DHT11의 응답을 기다린다.

    - DHT11은 약 20~40us(마이크로초) 후에 응답 신호를 보낸다.

4. DHT11 응답 신호

    - DHT11은 Low 상태로 약 80us 동안 신호를 유지한다.

    - 이후 다시 High 상태로 바뀌며, 데이터 전송이 시작된다.

5. 데이터 전송 준비

    - DHT11은 데이터를 MCU로 보내기 위해 준비한다.

검은 선은 MCU가 제어시는 신호 상태, 회색 선은 DHT11 센서가 응답 신호 및 데이터를 보내는 상태

 

 

 

dht11_cntr 소스코드
//////////////////////////////////////////////// 습도센서 컨트롤러
module dht11_cntr(
      input clk, reset_p,
      inout dht11_data,             // 데이터 선, input는 레지스터를 지정해 줄 수 없다.
      output reg [7:0] humidity, temperature);
      
      parameter S_IDLE = 6'b00_0001;
      parameter S_LOW_18MS = 6'b00_0010;
      parameter S_HIGH_20US = 6'b00_0100;
      parameter S_LOW_80US = 6'b00_1000;
      parameter S_HIGH_80US = 6'b01_0000;
      parameter S_READ_DATA = 6'b10_0000;
      
      parameter S_WAIT_PEDGE = 2'b01;
      parameter S_WAIT_NEDGE = 2'b10;
      
      reg [21:0] count_usec;
      wire clk_usec;
      reg count_usec_e;
      clock_div_100 us_clk(.clk(clk), .reset_p(reset_p), .clk_div_100(clk_usec));
      
      always @(negedge clk or posedge reset_p) begin
            if(reset_p) count_usec = 0;
            else if(clk_usec && count_usec_e)count_usec = count_usec + 1;
            else if(count_usec_e == 0)count_usec = 0;
      end
      
      wire dht_pedge, dht_nedge;
      edge_detector_n ed(
            .clk(clk), .reset_p(reset_p), .cp(dht11_data), 
            .p_edge(dht_pedge), .n_edge(dht_nedge));   
      
      reg [5:0] state, next_state;
      reg [1:0] read_state;
      
      always @(negedge clk or posedge reset_p) begin
            if(reset_p)state = S_IDLE;
            else state = next_state;
      end
      
      reg [39:0] temp_data;
      reg [5:0] data_count;
      reg dht11_buffer;
      
      assign dht11_data = dht11_buffer;               // 임피던스는 끊는 것, 읽을 때는 dht11_buffer에서 임피던스를 출력을 하고 읽어야함
      
      always @(posedge clk or posedge reset_p) begin
            if(reset_p) begin
                  count_usec_e = 0;
                  next_state = S_IDLE;
                  read_state = S_WAIT_PEDGE;
                  data_count = 0;
                  dht11_buffer = 'bz;
            end
            else begin
                  case(state)
                        S_IDLE: begin     
                              if(count_usec < 22'd3_000_000)begin       //3초 기다림-->3,000,000us
                                    count_usec_e = 1;
                                    dht11_buffer = 'bz;
                              end
                              else begin
                                    next_state = S_LOW_18MS;
                                    count_usec_e = 0;
                              end
                        end
                        
                        S_LOW_18MS: begin
                              if(count_usec < 22'd18_000)begin       // 18ms
                                    dht11_buffer = 0;
                                    count_usec_e = 1;
                              end
                              else begin
                                    next_state = S_HIGH_20US;
                                    count_usec_e = 0;
                                    dht11_buffer = 'bz;
                              end
                        end      
                        
                        S_HIGH_20US: begin
                              if(count_usec < 22'd20)begin       // 20us
                                    dht11_buffer = 'bz;
                                    count_usec_e = 1;
                              end
                              else begin
                                    if(dht_nedge)begin
                                          next_state = S_LOW_80US;
                                          count_usec_e = 0;
                                    end      
                              end
                        end
                        
                        S_LOW_80US: begin
                              if(dht_pedge) begin
                                    next_state = S_HIGH_80US;
                              end
                        end
                        
                        S_HIGH_80US: begin
                              if(dht_nedge) begin
                                    next_state = S_READ_DATA;
                              end
                        end
                        
                        S_READ_DATA: begin
                              case(read_state)
                                    S_WAIT_PEDGE: begin
                                          if(dht_pedge)read_state = S_WAIT_NEDGE;
                                          count_usec_e = 0;
                                    end
                                    
                                    S_WAIT_NEDGE: begin
                                          if(dht_nedge)begin
                                                if(count_usec < 45)begin
                                                      temp_data = {temp_data[38:0], 1'b0};            //쉬프트
                                                end
                                                else begin
                                                      temp_data = {temp_data[38:0], 1'b1};            //쉬프트
                                                end
                                                data_count = data_count + 1;
                                                read_state = S_WAIT_PEDGE;
                                          end
                                          else count_usec_e = 1;
                                    end
                              endcase
                              if(data_count >= 40)begin
                                    data_count = 0;
                                    next_state = S_IDLE;
                                    humidity = temp_data[39:32];              //31~24까지는 소수부, 의미 없어서 뺌
                                    temperature = temp_data[23:16];
                              end
                        end
                        default: next_state = S_IDLE;
                  endcase
            end
      end
      
      

endmodule

 

상태도 설명 어쩌고

 

3,000,000us(3s)는 2진수로 나타내면 총 22비트가 필요하여 소스코드에 22비트로 표현하였다.

 

dht11_test_top 소스코드
/////////////////////////////////////// 습도센서
module dht11_test_top(
      input clk, reset_p,
      inout dht11_data,
      output [3:0] com,
      output [7:0] seg_7);
      
      wire [7:0] humidity, temperature;
      dht11_cntr dht11(clk, reset_p, dht11_data, humidity, temperature);
      
      wire[15:0] value;
      assign value = {humidity, temperature};              
      fnd_4digit_cntr fnd(clk, reset_p, value, seg_7, com);

endmodule

Basys3 보드에 결과를 확인해보기 위해서 dht11_test_top 소스코드를 만들었다.

마찬가지로 fnd 컨트롤러에 출력하고자 하는 값이 출력되는지 보기 위해 하단에 추가하였다.

 

습도센서를 Basys3 보드에 연결하기 위해 JB 포트를 사용한다.

때문에 아래와 같이 .xdc 파일을 수정한다.

 

습도 센서와 Basys3 보드의 JB 포트에 연결하려면 주의가 필요하다.

꼭 아래와 같이 gnd, 3v3에 순서를 헷갈리지 않도록 하여 연결해야한다.

그렇지 않으면 습도센서에는 연기가 나오며 더 이상 쓸 수 없게된다.

또한, 신호출력에는 .xdc 파일에 JB1로 설정하였으므로 JB1에 연결하면된다.

 

그런데, Basys3 보드의 fnd에는 아무것도 출력되지 않는다.

소스코드에는 오류가 뜨지 않는데도 말이다. 왜일까? 자세한 이유는 내일 알아보기로 한다.


키패드, 습도센서