純記錄

module IOT_Bridge(

                output [7:0] seg,

                output [3:0] dig,

                output reg [3:0] led,

                input clock,

                input [3:0] sw,

                inout dht22_sda

        );

               

        // variables of clocks

        wire ck1Mhz;

        wire ck1KHz;   

        wire ck1Hz;     

        CLK_1MHZ  clk_1MHz(clock, ck1Mhz);

        CLK_1KHZ  clk_1KHz(clock, ck1Khz);

        CLK_1HZ   clk_1Hz(clock, ck1Hz);

       

        // variables of 7-seg LED

   wire [3:0] D3;

   wire [3:0] D2;

   wire [3:0] D1;

   wire [3:0] D0;

   wire [15:0] number;  // number to display

       

   BIN2BCD bin2bcd(number, D3, D2, D1, D0);

   Seg7    seg7(seg, dig, ck1Khz, D3, D2, D1, D0);   

               

        //DHT22 variables

        reg dht22_reset;

        reg dht22_get;

        reg dht22_select; //1=humidity, 0=temperature

        wire  [39:0] dht22_data;

        DHT22 dht22(ck1Mhz, dht22_reset, dht22_get, dht22_sda, dht22_data);

       

        assign number[15:0] = dht22_select ? dht22_data[39:24]:dht22_data[23:8];

       

        // clock

        reg [9:0] clock_counter;

       

        // initial

        initial

        begin

                dht22_reset = 0;

                dht22_get = 1;

                dht22_select = 1;

                clock_counter = 0;

                led[3:0]= 4'b1111; //LED off

        end         

       

        // select to show humidity or temperture

        always @ (posedge sw[0])

        begin      

                dht22_select = ~dht22_select;               

        end

               

        always @ (posedge ck1Khz)

        begin                              

                if (dht22_reset==0)

                        begin

                                dht22_reset = 1;

                                dht22_get = 0; //start to read DHT22

                        end

               

                led[3] = dht22_get;

                clock_counter = clock_counter + 1'b1;

                if(clock_counter==10'd1000)

                        begin

                                clock_counter = 0; 

                                dht22_reset = 0;

                        end

                if(clock_counter==10'd10) 

                        begin                      

                                dht22_get = 1; //stop read DHT22

                        end                 

        end                 

       

endmodule

 

/*

        DHT22.v : read DHT22 data

       

       

        source: https://github.com/evrinoma/AM2302

        Modify: Ghosty Guo

          Date: 2019/06/10

*/

module DHT22(

        input wire clk,

        input wire reset,

        input wire get,

        inout sda,

        output reg [39:0] outdata

);

 

reg lastSda       = 0;

reg wdata       = 0;

reg rw              = 1;

 

reg [39:0] data;

reg [9:0] address;

 

reg [3:0] state;

reg [9:0] count;

 

reg [3:0] trace;

reg [9:0] countTrace;

 

localparam STATE_IDLE                          = 0;

localparam STATE_START                        = 1;

localparam STATE_RELEASE                   = 2;

localparam STATE_RESPONSE_LOW      = 3;

localparam STATE_RESPONSE_HIGH     = 4;

localparam STATE_DATA_LOW                        = 5;

localparam STATE_DATA_HIGH                       = 6;

localparam STATE_STOP                                = 7;

localparam STATE_HALT                                 = 8;

 

localparam DELAY_HALT                                = 2;

 

assign sda = (rw)? 1'bz : wdata;

 

initial

begin

        outdata[39:0] = 40'd0;

end

       

always@(posedge clk)

begin

        if (!reset)

                begin

                        state <= STATE_IDLE;

                        rw            <= 1;

                        count <= 10'd0;

                        address <= 10'd39;

                        data <= 40'd0;

                        lastSda     <= 0;

                end

        else

                begin

                        case (state)

                                STATE_IDLE : begin //0

                                        if (!get)

                                                state <= STATE_START;

                                        else

                                                state <= STATE_IDLE;

                                        rw            <= 1;

                                        count       <= 10'd0;

                                        address <= 10'd39;

                                end

                                STATE_START : begin //1        

                                        if (count == 1000) //1ms

                                                begin

                                                        state <= STATE_RELEASE;

                                                        count <= 10'd0;

                                                end

                                        else

                                                begin

                                                        state <= STATE_START;

                                                        count <= count + 10'd1;

                                                end

                                        wdata <= 0;

                                        rw            <= 0;                       

                                end

                                STATE_RELEASE : begin //2

                                        if (count == 30) //30us

                                                begin

                                                        state <= STATE_RESPONSE_LOW;

                                                        count <= 10'd0;

                                                        rw            <= 1;

                                                end

                                        else

                                                begin

                                                        state <= STATE_RELEASE;

                                                        count <= count + 10'd1;

                                                        rw            <= 0;

                                                end

                                        wdata <= 1;

                                end

                                STATE_RESPONSE_LOW : begin //3

                                        if (trace != STATE_HALT )

                                                begin

                                                        if (count == 40)        //80us/2

                                                                begin

                                                                        if (sda && !lastSda)

                                                                                begin

                                                                                        state <= STATE_RESPONSE_HIGH;

                                                                                        count <= 10'd0;

                                                                                end                                                         

                                                                        else

                                                                                begin

                                                                                        state <= STATE_RESPONSE_LOW;                                                   

                                                                                end

                                                                end

                                                        else

                                                                begin

                                                                        count <= count + 10'd1;

                                                                end 

                                                        rw                    <= 1;       

                                                        lastSda     <= sda;

                                                end

                                        else

                                                begin

                                                        state <= STATE_IDLE;

                                                end

                                end

                                STATE_RESPONSE_HIGH : begin //4

                                        if (trace != STATE_HALT )

                                                begin

                                                        if (count == 40)        //80us/2

                                                                begin

                                                                        if (!sda && lastSda)

                                                                                begin

                                                                                        state <= STATE_DATA_LOW;

                                                                                        count <= 10'd0;

                                                                                end                                                         

                                                                        else

                                                                                begin

                                                                                        state <= STATE_RESPONSE_HIGH;                                                 

                                                                                end

                                                                end

                                                        else

                                                                begin

                                                                        count <= count + 10'd1;

                                                                end 

                                                        rw                    <= 1;       

                                                        lastSda     <= sda;

                                                end

                                        else

                                                begin

                                                        state <= STATE_IDLE;

                                                end

                                end

                                STATE_DATA_LOW : begin //5

                                        if (trace != STATE_HALT )

                                                begin

                                                        if (sda)

                                                                begin

                                                                        state <= STATE_DATA_HIGH;

                                                                end

                                                        else

                                                                begin

                                                                        state <= STATE_DATA_LOW;

                                                                end

                                                        rw            <= 1;       

                                                end

                                        else

                                                begin

                                                        state <= STATE_IDLE;

                                                end 

                                end

                                STATE_DATA_HIGH : begin //6

                                        if (trace != STATE_HALT )

                                                begin

                                                        if (sda)

                                                                begin

                                                                        count <= count + 10'd1;

                                                                        state <= STATE_DATA_HIGH;

                                                                end

                                                        else

                                                                begin

                                                                        if (count < 30)

                                                                                begin

                                                                                        data[address] = 1'b0;

                                                                                end

                                                                        else

                                                                                begin

                                                                                        data[address] = 1'b1;

                                                                                end

                                                                        if (address)

                                                                                begin

                                                                                        address = address - 10'd1;

                                                                                        state <= STATE_DATA_LOW;

                                                                                        count <= 10'd0;

                                                                                end

                                                                        else

                                                                                begin

                                                                                        // get all 40 bits

                                                                                        address <= 10'd39;

                                                                                        state <= STATE_STOP;

                                                                                        outdata[39:0] <= data[39:0];

                                                                                end

                                                                end

                                                        rw            <= 1;       

                                                end

                                        else

                                                begin

                                                        state <= STATE_IDLE;

                                                end

                                end

                                STATE_STOP : begin //7

                                        if (trace != STATE_HALT )

                                        begin

                                                if (sda)

                                                        begin

                                                                state <= STATE_IDLE;

                                                        end

                                                else

                                                        begin

                                                                state <= STATE_STOP;

                                                        end

                                                rw            <= 1;       

                                                end

                                        else

                                         begin

                                                state <= STATE_IDLE;              

                                         end

                                end

                        endcase

                end

end

 

 

always@(posedge clk)

begin

        if (!reset)

                begin

                        trace <= STATE_IDLE;

                        countTrace      <= 10'd0;

                end

        else

                begin              

                        case (trace)

                                STATE_IDLE, STATE_START,STATE_RELEASE : begin //0, 1, 2

                                                trace <= state;

                                                countTrace      <= 10'd0;                                

                                end                         

                                STATE_RESPONSE_LOW,STATE_RESPONSE_HIGH,STATE_DATA_LOW,STATE_DATA_HIGH,STATE_STOP : begin //3, 4, 5, 6, 7

                                        if (state == trace)

                                                if (countTrace > 85 ) //85us - max time for Responce period

                                                        begin

                                                                trace <= STATE_HALT;

                                                                countTrace      <= 10'd0;

                                                        end

                                                else

                                                        begin                              

                                                                countTrace <= countTrace + 10'd1;

                                                        end

                                        else

                                                begin

                                                        trace <= state;

                                                        countTrace      <= 10'd0;

                                                end

                                end

                                STATE_HALT : begin //8

                                        if (countTrace == DELAY_HALT)

                                                begin

                                                        trace <= STATE_IDLE;

                                                        countTrace      <= 10'd0;                                

                                                end

                                        else

                                                begin

                                                        countTrace <= countTrace + 10'd1;

                                                end

                                end

                        endcase

                end         

end

 

 

endmodule

 

 

module CLK_1KHZ(

                input clk_in,

                output reg clk_out

        );

       

       

        reg [14:0] clk_count;

       

       

        // initial

        initial

        begin

                clk_count = 0;

                clk_out = 0;

        end 

 

       

        // clock counts

        always @ (posedge clk_in)

        begin

                clk_count = clk_count + 1'b1;

                if(clk_count==25000) //50Mhz

                begin

                        clk_count = 0; 

                        clk_out = ~clk_out;

                end

        end

endmodule

 

 

module CLK_1MHZ(

                input clk_in,

                output reg clk_out

        );

       

       

        reg [4:0] clk_count;

       

       

        // initial

        initial

        begin

                clk_count = 0;

                clk_out = 0;

        end 

 

       

        // clock counts

        always @ (posedge clk_in)

        begin

                clk_count = clk_count + 1'b1;

                if(clk_count==25) //50Mhz

                begin

                        clk_count = 0; 

                        clk_out = ~clk_out;

                end

        end

endmodule

 

module CLK_1MHZ(

                input clk_in,

                output reg clk_out

        );

       

       

        reg [4:0] clk_count;

       

       

        // initial

        initial

        begin

                clk_count = 0;

                clk_out = 0;

        end 

 

       

        // clock counts

        always @ (posedge clk_in)

        begin

                clk_count = clk_count + 1'b1;

                if(clk_count==25) //50Mhz

                begin

                        clk_count = 0; 

                        clk_out = ~clk_out;

                end

        end

endmodule

 

 

/*

        Bin2BCD: Convert binary to 4 BCDs       

        ref: http://alex9ufoexploer.blogspot.com/2013/12/binary-to-bcd-conversion-algorithm.html

*/

 

module BIN2BCD(

        input [15:0] binary,

        output reg [3:0] BCD3,

        output reg [3:0] BCD2,

        output reg [3:0] BCD1,

        output reg [3:0] BCD0

        );

       

        integer i;

        always@(binary)

        begin

                BCD3 = 4'd0;

                BCD2 = 4'd0;

                BCD1 = 4'd0;

                BCD0 = 4'd0;

                for (i=14; i>=0; i=i-1)

                begin

                        if (BCD3>=4'd5)

                                BCD3 = BCD3 + 4'd3;

                        if (BCD2>=4'd5)

                                BCD2 = BCD2 + 4'd3;

                        if (BCD1>=4'd5)

                                BCD1 = BCD1 + 4'd3;

                        if (BCD0>=4'd5)

                                BCD0 = BCD0 + 4'd3;

                               

                        BCD3 = BCD3 << 1;

                        BCD3[0] = BCD2[3];

                        BCD2 = BCD2 << 1;

                        BCD2[0] = BCD1[3];

                        BCD1 = BCD1 << 1;

                        BCD1[0] = BCD0[3];

                        BCD0 = BCD0 << 1;

                        BCD0[0] = binary[i];

                end

        end

 

endmodule

 

arrow
arrow
    文章標籤
    Verilog
    全站熱搜

    ghostyguo 發表在 痞客邦 留言(1) 人氣()