module am2303(dhtio, clk, dhtData, dataReady, state); inout dhtio; input clk; output [39:0]dhtData; output dataReady; output state; reg dht_oe; reg dhtin, ds1, ds2; reg [7:0] state = 8'd0; reg [31:0] count = 0; reg [39:0] dataBits = 40'd0; reg [7:0] bitCount = 8'd40; reg dataReady; assign dhtio = dht_oe ? 1'b0 : 1'bZ; always @(posedge clk) begin ds2 <= ds1; ds1 <= dhtio; dhtin <= ds2; end always @(posedge clk) begin // Fail safe, resets the count and the state if we stall too long at any stage. if(count > 32'h4F0000) begin count <= 32'h0; state <= 8'h00; end case (state) 8'h00: begin // count to 1fbd00 (one second at 2.08 MHz) then move to next state; if(count < 32'h1fbd00) begin count <= count + 1; end else begin count <= 0; state <= 8'h01; end end 8'h01: begin // send an output pulse lasting a count of 00004ff; // This is the 'start' signal to the device, and is our only output to it. if( count < 32'h00004ff ) begin count <= count + 1; dht_oe <= 1'b1; end else begin count <= 0; dht_oe <= 1'b0; state <= 8'h02; end end 8'h02: begin // wait for our signal to achieve MARK AFTER START, allowing the bus to float high again. if (dhtin) begin count <= 0; state <= 8'h03; // MARK ACHIEVED, end else count <= count +1; end 8'h03: begin // wait for our signal to achieve SPACE AFTER MARK. if (~dhtin) begin count <= 0; state <= 8'h04; // SPACE ACHIEVED, end else count <= count +1; end 8'h04: begin // wait for bus to float high again, this is the last part of the ACK for our START command. if(dhtin) begin count <= 0; state <= 8'h05; dataReady <= 1'b0; dataBits <= 0; bitCount <= 0; end else begin count <= count +1; end end // What follows is 40 bits of data. (8 Bytes) // each bit has a short low pulse, followed by a high pulse of 28uS for '0' or 60 us for '1' // so we loop from state 5 onwards, 40 times. 8'h05: begin // as soon as we go low, rotate dataBits and move up-state to wait for high if (~dhtin) begin // we are the leading LOW of every bit. dataBits <= {dataBits[38:0],1'b0}; bitCount <= bitCount + 1'b1; count <= 0; state <= 8'h06; end else count <= count +1; end 8'h06: begin if (dhtin) begin // wait here while 0, then move to state 7 as soon as we go high. state <= 8'h07; count <= 0; end else count <= count +1; end 8'h07: begin // count how long we are high if (dhtin) begin count <= count +1; end else begin state <= 8'h08; end end 8'h08: begin // we have gone low. Use the count to see if we received a long (1) or short (0) count. if (count > 100) begin count <= 0; dataBits <= dataBits | 1'b1; state <= 8'h09; end else begin count <= 0; state <= 8'h09; end end 8'h09: begin if(bitCount < 40) begin state <= 8'h05; end else begin dataReady <= 1'b1; state <= 8'h0a; end end 8'h0a: begin // wait till we go high again, end of transmission if(dhtin) begin state <= 8'h00; count <= 0; end else count <= count +1; end default: begin count <= 0; state <= 8'h00; end endcase end endmodule