DHT11 ??
- DATA 핀에 PullUp 저항이 포함된 모델


- 서미스터(thermistor)란 저항기의 일종으로, 온도에 따라 물질의 저항이 변화하는 성질을 이용한 전기적 장치이다. 열가변저항기라고도 하며, 주로 회로의 전류가 일정 이상으로 오르는 것을 방지하거나, 회로의 온도를 감지하는 센서로써 이용된다. 서미스터는 주로 폴리머나 세라믹 소재로 제작되며, 섭씨 영하 90도에서 130도 사이에서 높은 정확도로 온도를 측정할 수 있다. 이러한 점에서 순수한 금속을 사용하여 고온의 온도를 측정하는 저항 온도계와는 차이를 보인다
데이터 통신 1-wired 통신
- 1개의 신호로 출력과 입력을 모두 사용하는 방식입니다.



MCU에서 start신호를 DHT11을 보냈을때, 데이터 선은 사용되지 않을때는 high_level voltage를 유지합니다. 하지만 MCU와 DHT11 사이의 통신이 시작되면 MCU는 데이터선의 신호레벨을 High에서 Low로 설정합니다. 이 과정은 최소 18ms가 소요되어야만 MCU의 신호를 DHT11이 감지하며 그후 MCU는 전압을 끌어올려 DHT11의 응답을 20~40us 기다립니다.
DHT11이 start신호를 감지하면, low-level voltage의 응답신호를 80us 동안 전송합니다.(즉, 데이터 선이 low-level voltage일때는 DHT11이 응답 신호를 보내고 있다는 것을 의미한다). 이 후 DHT11은 데이터 선의 신호 레벨을 low에서 high로 설정하고 데이터 전송을 위해 80us 동안 해당 상태를 유지합니다. DHT11이 MCU로 데이터를 전송할 때, 모든 데이터 비트는 50us의 low-level voltage에서 시작하고 다음 high-level voltage의 길이에 따라 데이터 비트가 0인지 1인지 결정합니다. 이 데이터를 40비트 받고 나면 idle상태로 전환됩니다. 그리고 다음 데이터를 받기위해서는 데이터 시트로는 10초 정도 대기하고 새로운 데이터를 받아야한다고 나와있지만 3초 정도만 대기하고 데이터를 받아도 괜찮다!
코드 및 기능설명

- 우리는
us가 필요하기때문에 100주기를 이용해서 Basys-3의 10ns주기를 1us로 사용해주기 위함이다! 그리고 us를 카운트하기 위해 count_microsec,count_microsec_enable(enable이 1이되어야만 카운트를 샐 수있도록 CL을 설계.)을 reg로 선언했다.

clk을 상승엣지 하강엣지 다르게 둔 이유 : state는 기본적으로 idle 일 것이다. 그러면 상승엣지에서 먼저 state를 확인하고 S_IDLE 이라면 아래 작성한 코드대로 진행이 되면서 next_state가 S_LOW_18MS가 되면서 하강엣지에서 state 에 next_state가 할당되면서 위와같은 과정을 반복한다.
dht11은 S_LOW_18MS에서만 0을 출력한다. 나머지 state에서는 High Impedence가 출력되어여한다. S_LOW_18MS에서 MCU가 start신호를 내보낸다 이 때문에 dht11_bufferr가 0이된다. 왜? dht11은 시작신호를 받아야하기 때문에! 이부분에서만 신호를 받기 때문에 나머지 부분에서 는 출력을 하이임피던스로 한다!
s_idle에서 입력을 받아야하기 때문에 출력을 끊어줘야한다(출력을 High 임피던스로!) 
dht11_buffer가 하이임피던스가 되는 시점이 위의 사진과 다르다. 데이터시트의 논리대로 보면 S_HIGH_20US 시점에서 dht11_buffer의 출력이 하이임피던스가 되는것이 맞지만 어차피 S_LOW_18MS에서만 dht11_buffer가 출력이 0 이되니까 위처럼 선언해도 상관은 없다! 하지만 이 사진처럼 하는것이 데이터 시트의 논리대로 작성한 코드이다.
- 센서의 40비트 데이터를 한비트씩 받아오는 과정입니다.
S_WAIT_POSEDGE는 DHT11이 LOW인 상태입니다. 반대로 S_WAIT_NEGEDGE는 DHT11이 HIGH인 상태일 것입니다. S_WAIT_POSEDGE 상태라면 DHT11이 High상태일 때 us를 측정하여 1인지 0이지 판별합니다. 그러기위해서는 DHT11이 Low에서 50us를 기다려야하는데 우리는 이를 dht_posedge(원사이클 펄스)로 판별해 dht11이 High로 변한다면 read_state = S_WAIT_NEGEDGE 로 read_state를 변경하고 us 카운트를 멈춰줍니다. 그리고 S_WAIT_NEGEDGE 상태일때 만약 dht_negedge, 즉 dht11이 Low로 떨어지기 전까지 count_microsec_enable = 1; 로 하여 dht11이 1일때 us를 측정합니다. 그리고 dht_negedge 이 1이 될때 count_microsec 를 측정하여 만약 45이하라면 temp_data에 0을 하위비트에 넣고 좌쉬프트를 진행합니다. 만약 45이상이라면 1을 하위비트에 넣고 좌쉬프트합니다. 그리고 data_count를 하나씩 늘려가면서 40 보다 크다면 data_count를 0으로 초기화하고 state를 S_IDLE로 변경하고 temp_data의 저장된 값을 출력포트에 선언하고 출력합니다.
testBench

tri1 : 풀업달린 입력 (시뮬레이션 할 때만 사용가능하다.) 풀업, 풀다운이 달려있으면 inout으로 선언한 모듈을 시뮬레이션에서 시뮬레이션을 할때 tri1(풀업), tri0(풀다운)을 사용해주면 된다
dht11_data가 참이 될때까지 기다린다.
시뮬레이션 결과
- 전체적이 시뮬레이션 결과입니다. 다음 코드로 인해 30ms 이전까지는
data_buffer가 High임피던스를 출력합니다. 30ms 이후에는 다음 상태로 넘어가게됩니다.

if(count_microsec < 22'd20_000)begin 다음 코드로 인해서 20ms 동안 data_buffer의 출력을 0으로 하여 dht11이 start신호를 받는다. 
if(count_microsec > 22'd20)begin 이후 20us 동안 기다리면서 dht11의 이 하강엣지가 나올때 다음상태(S_LOW_80US)로 넘어갑니다. 
- start신호를 감지하면
Low-level전압의 응답신호를 80us동안 전송합니다 이후 상승엣지가 발생하면 다음상태(S_HIGH_80US)로 넘어갑니다. 
S_HIGH_80US 에서 READ_DATA상태로 넘어오게됩니다(LOW,HIGH 80us를 지난 다음부터 40비트의 데이터를 받습니다.). 그러면 dht11_data가 High가 지속되는 시간에 따라서 0(dht11_data = 29us ※테스트벤치에서 작성한 내용대로) ,1(dht11_data = 70us)의 데이터를 입력받습니다. 데이터를 한비트씩 입력받을때 중간에 Low상태인 시간은 50us입니다. 
- 이후
10ns 이후 data_buffer를 0으로 하고 wr_en을 0으로 합니다. 이러면 처음에 설정한 humidity_data와 temperature_data의 40bit의 값을 받아서 humidity[7:0], temperature[7:0]에 저장이되어서 값이 나오는 모습을 확인할 수 있습니다. 
오실로스코프 실습


- 이렇게
20us 로 받으면 하강엣지가 20us동안 못들어오게되는데 이렇게 되면 오실로스코프 상에서 dht11의 40비트 데이터중에서 1bit을 못받아서 39bit만 들어온다 그렇기 때문에 답장의 사진처럼 22'd3으로 변경하고 40bit를 다 받도록 변경

- dht11_data 값을 16진수로 FND에 표현이되는 문제를 10진수로 변경해줍니다.

bcd 16bit를 4개씩 나눠서 이 4개의 비트가 5이상이면 4개의 비트에 +3을 한다. 그리고 입력으로 들어오는 bin을 한비트식 좌쉬프트 하면서 진행한다. 4비트씩 보면 어차피 최하위 비트는 bin의 한비트가 들어오기 때문에 상위 3비트만 보고 이것이 5이상이면 +3을하여 저장한다.
DHT11 - 오류 검출기
check_sum은 습도의 정수부 8비트, 소수부 8비트, 온도의 정수부 8비트, 소수부 8비트를 더한것이 check_sum이다 이 결과는 datasheet상에서 당연한 결과이기 때문에 이를 if문으로 설계하여 오류가 발생하면 값이 나오지 않기때문에 이를 오류검출기로서의 역할을 수행 할 수 있도록 설계하였습니다.


- 안정성있는 설계를 위해 만약 들어와야할 신호들이 들어오지 않게되는 경우의 상황을 위해서 설계한 코드입니다. 이는 만약
S_HIGH_20US 이후 하강엣지가 발생되어야 다음상태로 넘어가는데 만약 하강엣지가 들어오지 못할경우 즉. DHT11이 MCU의 신호를 감지하여 MCU가 HIGH인 상태에서 DHT11의 Start신호를 감지하여 Low신호를 보내야하는데 이 과정에 문제가 생기면 하강엣지가 발생하지 않게되면서 시간이 10ms가 지나면 다시 IDLE상태로 돌아가도록 설계한 것입니다. 이는 아래 S_LOW_80US, S_HIGH_80US에도 똑같이 설계하여 안정성을 높였습니다!