FPGA project : dht11 温湿度传感器

没有硬件,过几天上板测试。

module dht11(
    input       wire        sys_clk     ,
    input       wire        sys_rst_n   ,
    input       wire        key         ,

    inout       wire        dht11       ,

    output      wire        ds          ,
    output      wire        oe          ,
    output      wire        shcp        ,
    output      wire        stcp          
);

    // 例化连线
    wire                    key_out_w ;
    wire        [19:00]     data_w    ;
    wire                    sign_w    ;
    wire        [ 5: 0]     point_w   ;
    wire                    en_w      ;
key_filter key_filter_insert(
    .sys_clk                ( sys_clk   ) ,
    .sys_rst_n              ( sys_rst_n ) ,
    .key_in                 ( key       ) ,

    .key_out                ( key_out_w )         
);

dht11_ctrl dht11_ctrl_insert(
    .sys_clk                ( sys_clk    ) ,
    .sys_rst_n              ( sys_rst_n  ) ,
    .key_flag               ( key_out_w  ) ,
    .dht11                  ( dht11      ) ,

    .data_out               ( data_w     ) ,
    .sign                   ( sign_w     )  
);

seg_595_dynamic seg_595_dynamic_insert(
    .sys_clk                ( sys_clk    ) ,
    .sys_rst_n              ( sys_rst_n  ) ,
    .data                   ( data_w     ) ,        
    .point                  ( point_w    ) ,
    .sign                   ( sign_w     ) ,        
    .seg_en                 ( en_w       ) ,

    .ds                     ( ds         ) ,
    .oe                     ( oe         ) ,
    .shcp                   ( shcp       ) ,
    .stcp                   ( stcp       )    
);

endmodule

module dht11_ctrl (
    input               wire            sys_clk     ,
    input               wire            sys_rst_n   ,
    input               wire            key_flag    ,
    inout               wire            dht11       ,

    output              reg  [19:0]     data_out    ,
    output              reg             sign  
);

    // reg signal define
    // 产生us时钟
    reg             clk_us      ;
    reg     [4:0]   cnt_clk_us  ;
    // 内部信号(用于产生状态转移条件与输出信号)
    reg     [19:0]  cnt_us      ;
    reg     [ 6:0]  cnt_low     ;
    reg             dht11_reg1  ;
    reg             dht11_reg2  ;
    wire            dht11_fall  ;
    wire            dht11_rise  ;
    reg    [ 5:0]   bit_cnt     ;
    reg    [39:0]   data_temp   ;
    reg    [31:0]   data        ;
    reg             data_flag   ;
    // 三态输出
    reg             dht11_en    ;
    wire            dht11_out   ;
    // [4:0]   cnt_clk_us  ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_clk_us <= 5'd0 ;
        end else begin
            if(cnt_clk_us == 5'd24) begin
                cnt_clk_us <= 5'd0 ;
            end else begin
                cnt_clk_us <= cnt_clk_us + 1'b1 ;
            end
        end
    end
    //         clk_us      ;
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            clk_us <= 1'b0 ;
        end else begin
            if(cnt_clk_us == 5'd24) begin
                clk_us <= ~clk_us ;
            end else begin
                clk_us <= clk_us ;
            end
        end
    end

    // reg signal define
    // 在clk_us时钟域下
    // 状态机 三段式写法(现态与次态描述)(状态转移条件描述)(输出信号描述)
    localparam   WAIT_1S = 6'b000_001 ,
                 START   = 6'b000_010 ,
                 DELAY_1 = 6'b000_100 ,
                 REPLAY  = 6'b001_000 ,
                 DELAY_2 = 6'b010_000 ,
                 RD_DATA = 6'b100_000 ;
    reg     [5:0]   state_c  ;
    reg     [5:0]   state_n  ;
    wire            WAIT_1StoSTART   ;
    wire            STARTtoDELAY_1   ;
    wire            DELAY_1toREPLAY  ;
    wire            REPLAYtoDELAY_2  ;
    wire            REPLAYtoSTART    ;
    wire            DELAY_2toRD_DATA ;
    wire            DELAY_2toSTART   ;
    always @(posedge clk_us or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            state_c <= 6'd0 ;
        end else begin
            state_c <= state_n ;
        end
    end
    always @(*) begin
        case (state_c)
        WAIT_1S:begin
                    if(WAIT_1StoSTART) begin 
                        state_n <= START ;
                    end else begin
                        state_n <= WAIT_1S ;
                    end
                end
        START  :begin
                    if(STARTtoDELAY_1) begin
                        state_n <= DELAY_1 ;
                    end else begin
                        state_n <= START ;
                    end
                end
        DELAY_1:begin
                    if(DELAY_1toREPLAY) begin
                        state_n <= REPLAY ;
                    end else begin
                        state_n <= DELAY_1 ;
                    end
                end
        REPLAY :begin
                    if(REPLAYtoDELAY_2) begin 
                        state_n <= DELAY_2 ;
                    end else begin
                        if(REPLAYtoSTART) begin
                            state_n <= START ;
                        end else begin
                            state_n <= REPLAY ;
                        end
                    end
                end
        DELAY_2:begin
                    if(DELAY_2toRD_DATA) begin 
                        state_n <= RD_DATA ;
                    end else begin
                        state_n <= DELAY_2 ;
                    end
                end
        RD_DATA:begin
                    if(DELAY_2toSTART) begin
                        state_n <= START ;
                    end else begin
                        state_n <= RD_DATA ;
                    end
                end
        default: state_n <= START ;
        endcase
    end
    // 状态机第二段描述
    assign      WAIT_1StoSTART  =  (state_c == WAIT_1S && cnt_us == 20'd999_999) ? 1'b1 : 1'b0 ;
    assign      STARTtoDELAY_1  =  (state_c == START && cnt_us == 20'd17_999) ? 1'b1 : 1'b0 ;
    assign      DELAY_1toREPLAY =  (state_c == DELAY_1 && cnt_us == 20'd10) ? 1'b1 : 1'b0 ;
    assign      REPLAYtoDELAY_2 =  (state_c == REPLAY && dht11_rise == 1'b1 && cnt_low <= 7'd85 && cnt_low >= 7'd81) ? 1'b1 : 1'b0;
    assign      REPLAYtoSTART   =  (state_c == REPLAY && dht11_rise == 1'b1 && (cnt_us >= 20'd100 || cnt_us <= 20'd70)) ? 1'b1 : 1'b0 ;
    assign      DELAY_2toRD_DATA=  (state_c == DELAY_2 && dht11_fall == 1'b1 && cnt_us >= 20'd85 && cnt_us <= 20'd88) ? 1'b1 : 1'b0 ;
    assign      DELAY_2toSTART  =  (state_c == RD_DATA && bit_cnt == 6'd40 && dht11_rise == 1'b1) ? 1'b1 : 1'b0 ;

    // // 内部信号(用于产生状态转移条件与输出信号)
    // reg     [19:0]  cnt_us      ;
    always @(posedge clk_us or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_us <= 20'd0 ;
        end else begin
            if((state_c == WAIT_1S && cnt_us == 20'd999_999) 
                || (state_c == START && cnt_us == 20'd17_999) 
                || (state_c == DELAY_1 && cnt_us == 20'd10) 
                || (state_c == REPLAY && dht11_rise == 1'b1)
                || (state_c == DELAY_2 && dht11_fall == 1'b1)
                || (state_c == RD_DATA && (dht11_fall || dht11_rise)))begin // 记得最后加大括号
                cnt_us <= 20'd0 ;
            end else begin
                cnt_us <= cnt_us + 1'b1 ;
            end
        end
    end
    // reg     [ 6:0]  cnt_low     ;
    always @(posedge clk_us or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            cnt_low <= 7'd0 ;
        end else begin
            if(state_c == REPLAY && dht11_reg1 == 1'b0) begin
                cnt_low <= cnt_low + 1'b1 ;
            end else begin
                cnt_low <= 7'd0 ;
            end
        end
    end
    // reg             dht11_reg1  ;
    // reg             dht11_reg2  ;
    always @(posedge clk_us or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            dht11_reg1 <= 1'b1 ;
            dht11_reg2 <= 1'b1 ;
        end else begin
            dht11_reg1 <= dht11 ;
            dht11_reg2 <= dht11_reg1 ;
        end
    end
    // wire            dht11_fall  ;
    // wire            dht11_rise  ;
    assign dht11_fall = ~dht11_reg1 &&  dht11_reg2 ;
    assign dht11_rise =  dht11_reg1 && ~dht11_reg2 ;
    // reg    [ 5:0]   bit_cnt     ;
    always @(posedge clk_us or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            bit_cnt <= 6'd0 ;
        end else begin
            if(dht11_rise && bit_cnt == 6'd40 ) begin
                bit_cnt <= 6'd0 ;
            end else begin
                if(state_c == RD_DATA && dht11_fall) begin
                    bit_cnt <= bit_cnt + 1'b1 ;
                end else begin
                    bit_cnt <= bit_cnt ;
                end
            end
        end
    end
    // reg    [39:0]   data_temp   ;
    always @(posedge clk_us or negedge sys_rst_n) begin 
        if(~sys_rst_n) begin
            data_temp <= 40'd0 ;
        end else begin
            if(state_c == RD_DATA && dht11_fall && bit_cnt <= 39) begin
                if(cnt_us >= 20'd50) begin // 也可以是68
                    data_temp[39 - bit_cnt] <= 1'b1 ;
                end else begin
                    data_temp[39 - bit_cnt] <= 1'b0 ;
                end
            end else begin
                data_temp <= data_temp ;
            end
        end
    end
    // reg    [31:0]   data        ;
    always @(posedge clk_us or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            data <= 32'd0 ;
        end else begin
            if(data_temp[7:0] == (data_temp[15:8] + data_temp[23:16] + data_temp[31:24] + data_temp[39:32])) begin
                data <=  data_temp[39:8] ;
            end else begin
                data <= data ;
            end
        end
    end
    // reg             data_flag   ; sys_clk时钟域下
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            data_flag <= 1'b0 ;
        end else begin
            if(key_flag) begin
                data_flag <= ~data_flag ;
            end else begin
                data_flag <=  data_flag ;
            end
        end
    end

    // // 三态输出
    // wire            dht11_out   ;
    assign dht11 = (dht11_en == 1'b1) ? dht11_out : 1'bz ;
    assign dht11_out = 1'b0 ;
    // reg            dht11_en    ;
    always @(posedge clk_us or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            dht11_en <= 1'd0 ;
        end else begin
            if(state_c == START) begin
                dht11_en <= 1'b1 ;
            end else begin
                dht11_en <= 1'b0 ;
            end
        end
    end

    // output signal
    //     reg  [19:0]     data_out    ,
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            data_out <= 20'd0 ;
        end else begin
            if(data_flag == 1'b0) begin // 显示湿度
                data_out <= data[31:24] * 16'd10 ;
            end else begin
                data_out <= data[15:8] * 16'd10 + data[3:0] ;
            end
        end
    end 
    // reg             sign  
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(~sys_rst_n) begin
            sign <= 1'b0 ;
        end else begin
            if(key_flag == 1'b1 && data[7] == 1'b1) begin
                sign <= 1'b1 ;
            end else begin
                sign <= 1'b0 ;
            end
        end
    end
endmodule

其他模块都是之前的,就不发了。

相关推荐
DS小龙哥8 小时前
基于Zynq FPGA的雷龙SD NAND存储芯片性能测试
fpga开发·sd nand·雷龙·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
上理考研周导师18 小时前
第二章 虚拟仪器及其构成原理
fpga开发
FPGA技术实战19 小时前
《探索Zynq MPSoC》学习笔记(二)
fpga开发·mpsoc
bigbig猩猩1 天前
FPGA(现场可编程门阵列)的时序分析
fpga开发
Terasic友晶科技1 天前
第2篇 使用Intel FPGA Monitor Program创建基于ARM处理器的汇编或C语言工程<二>
fpga开发·汇编语言和c语言
码农阿豪1 天前
基于Zynq FPGA对雷龙SD NAND的测试
fpga开发·sd nand·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
江山如画,佳人北望1 天前
EDA技术简介
fpga开发
淘晶驰AK2 天前
电子设计竞赛准备经历分享
嵌入式硬件·fpga开发
最好有梦想~2 天前
FPGA时序分析和约束学习笔记(4、IO传输模型)
笔记·学习·fpga开发