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

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

相关推荐
北城笑笑4 小时前
FPGA 14 ,硬件开发板分类详解,FPGA开发板与普通开发板烧录的区别
fpga开发·fpga
2202_754421544 小时前
一个计算频率的模块
驱动开发·fpga开发
小灰灰的FPGA5 小时前
低速接口项目之串口Uart开发(七)——如何在FPGA项目中实现自适应波特率串口功能
fpga开发
fei_sun1 天前
【Verilog】第一章作业
fpga开发·verilog
深圳市雷龙发展有限公司longsto1 天前
基于FPGA(现场可编程门阵列)的SD NAND图片显示系统是一个复杂的项目,它涉及硬件设计、FPGA编程、SD卡接口、NAND闪存控制以及图像显示等多个方面
fpga开发
9527华安1 天前
FPGA实现PCIE3.0视频采集转10G万兆UDP网络输出,基于XDMA+GTH架构,提供工程源码和技术支持
网络·fpga开发·udp·音视频·xdma·pcie3.0·万兆网
able陈1 天前
为什么verilog中递归函数需要定义为automatic?
fpga开发
fei_sun1 天前
【Verilog】第二章作业
fpga开发·verilog
碎碎思1 天前
如何使用 Vivado 从源码构建 Infinite-ISP FPGA 项目
fpga开发·接口隔离原则
江山如画,佳人北望1 天前
fpga-状态机的设计及应用
fpga开发