NEXYS4_DDR迪芝伦XC7A100TCSG324-1型,DS18B20测温(野火)

0. 注意

典型的 DS18B20 电路的 inout 端口需要一个 4.7k 上拉电阻
在这里插入图片描述

1. DS18B20简介

1.1 DS18B20特性

在这里插入图片描述

1.2 DS18B20引脚

在这里插入图片描述

1.3 DS18B20内部结构图

在这里插入图片描述

1.4 DS18B20的高速缓存器

在这里插入图片描述

1.4 DS18B20的温度寄存器

共16位,5位S表示符号位
红色的9-12表示精度为9-12时的有效位;精度为9时,后三位无效,默认精度为12位,即16位全部有效
在这里插入图片描述

举例:
+125℃ 0000_0111_1101_0000 12位精度
0000_0为符号位,0表示正数
111_1101_0000B = 2000
2000*0.0625 = 125

1.5 DS18B20的时序

1.5.1 初始化时序

在这里插入图片描述

1.5.2 写时序

在这里插入图片描述

1.5.3 读时序

在这里插入图片描述

2. 系统框图

在这里插入图片描述

3. 状态转移图

在这里插入图片描述

4. 时序图

4.1 生成clk_us信号

在这里插入图片描述

4.2 INIT - WR_CMD的时序

在这里插入图片描述

在这里插入图片描述

4.3 WAIT - INIT_AGAIN - RD_CMD的时序

在这里插入图片描述

在这里插入图片描述

4.4 RD_TEMP - INIT的时序

在这里插入图片描述

在这里插入图片描述

5. 设计文件

5.1 ds18b20.v

`timescale  1ns/1ns
module  ds18b20
(
    input   wire            sys_clk     ,
    input   wire            sys_rst_n   ,
    inout   wire            dq          ,
    
    output  wire     [7:0]   sel         , //数码管位选信号
    output  wire     [7:0]   seg           //数码管段选信号
);

wire    [19:0]  data_out;

ds18b20_ctrl    ds18b20_ctrl_inst
(
    .sys_clk     (sys_clk  ),
    .sys_rst_n   (sys_rst_n),
    .dq          (dq       ),
                  
    .data_out    (data_out )
);

seg_dynamic
#(
    .CNT_MAX(17'd99_999)
)
seg_dynamic_inst
(
    .sys_clk     (sys_clk  ),
    .sys_rst_n   (sys_rst_n),
    .data        (data_out ),

    .sel         (sel      ),
    .seg         (seg      ) 
);

endmodule

5.2 ds18b20_ctrl.v

`timescale  1ns/1ns
module  ds18b20_ctrl
(
    input   wire            sys_clk     ,
    input   wire            sys_rst_n   ,
    inout   wire            dq          ,
    
    output  wire    [19:0]  data_out    ,
);

parameter   INIT       = 6'b000_001,
            WR_CMD     = 6'b000_010,
            WAIT       = 6'b000_100,
            INIT_AGAIN = 6'b001_000,
            RD_CMD     = 6'b010_000,
            RD_TEMP    = 6'b100_000;

parameter   WAIT_MAX = 20'd750_000; 

parameter   WR_CC_44 = 16'h44_cc,
            WR_CC_BE = 16'hbe_cc;

reg                 clk_us      ;
reg     [5:0]       cnt         ;
reg     [5:0]       state       ;
reg     [19:0]      cnt_us      ;
reg                 flag        ;
reg     [3:0]       bit_cnt     ;
reg     [15:0]      data_temp   ;
reg     [19:0]      data        ;
reg                 dq_en       ;
reg                 dq_out      ;


assign  dq = (dq_en == 1'b1) ? dq_out : 1'bz;

assign  data_out = (data * 625) / 10;

//cnt,计数50次,实现1us
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt <= 6'd0;
    else    if(cnt == 6'd49)
        cnt <= 6'd0;
    else
        cnt <= cnt + 1'b1;
//clk_us,1us的时钟
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        clk_us <= 1'b0;
    else    if(cnt == 6'd49)
        clk_us <= ~clk_us;
    else
        clk_us <= clk_us;
//cnt_us,1us 时钟计数器,用于状态跳转
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_us <= 20'd0;
    else    if(((state == INIT || state == INIT_AGAIN) && (cnt_us == 20'd999)) 
                || ((state == WR_CMD || state == RD_CMD || state == RD_TEMP) && (cnt_us == 20'd64))
                || ((state == WAIT && cnt_us == WAIT_MAX)))
        cnt_us <= 20'd0;
    else
        cnt_us <= cnt_us + 1'b1;
//bit_cnt,bit 计数器,写 1bit 或读 1bit 加 1,一次写完之后清零
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        bit_cnt <= 4'd0;
    else    if((state == WR_CMD || state == RD_CMD || state == RD_TEMP)
                && (bit_cnt == 4'd15) && (cnt_us == 20'd64))
        bit_cnt <= 4'd0;
    else    if((state == WR_CMD || state == RD_CMD || state == RD_TEMP)
                && (cnt_us == 20'd64))
        bit_cnt <= bit_cnt + 1'b1;
//flag
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        flag <= 1'b0;
    else    if((state == INIT || state == INIT_AGAIN) && (cnt_us == 20'd570) && (dq == 1'b0))
        flag <= 1'b1;
    //else    if((state == INIT || state == INIT_AGAIN) && (cnt_us == 20'd999))
    else    if(cnt_us == 20'd999)
        flag <= 1'b0;
    else
        flag <= flag;
//state????
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        state <= INIT;
    else
        case(state)
            INIT       :
                if(cnt_us == 20'd999 && flag == 1'b1)
                    state <= WR_CMD;
                else
                    state <= INIT;
            WR_CMD     :
                if(bit_cnt == 4'd15 && cnt_us == 20'd64)
                    state <= WAIT;
                else
                    state <= WR_CMD;
            WAIT       :
                if(cnt_us == WAIT_MAX)
                    state <= INIT_AGAIN;
                else
                    state <= WAIT;
            INIT_AGAIN :
                if(cnt_us == 20'd999 && flag == 1'b1)
                    state <= RD_CMD;
                else
                    state <= INIT_AGAIN;
            RD_CMD     :
                if(bit_cnt == 4'd15 && cnt_us == 20'd64)
                    state <= RD_TEMP;
                else
                    state <= RD_CMD;
            RD_TEMP    :
                if(bit_cnt == 4'd15 && cnt_us == 20'd64)
                    state <= INIT;
                else
                    state <= RD_TEMP;
            default:state <= INIT;
        endcase
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        begin
        dq_en  <= 1'b0;
        dq_out <= 1'b0;
        end
    else
        case(state)
            INIT       :
                if(cnt_us < 20'd499) 
                    begin
                        dq_en  <= 1'b1;
                        dq_out <= 1'b0;
                    end
                else
                    begin
                        dq_en  <= 1'b0;
                        dq_out <= 1'b0;
                    end
            WR_CMD     :
                if(cnt_us > 20'd62) 
                    begin
                        dq_en  <= 1'b0;
                        dq_out <= 1'b0;
                    end
                else    if(cnt_us <= 20'd1)
                    begin
                        dq_en  <= 1'b1;
                        dq_out <= 1'b0;
                    end
                else    if(WR_CC_44[bit_cnt] == 1'b0)
                    begin
                        dq_en  <= 1'b1;
                        dq_out <= 1'b0;
                    end
                else    if(WR_CC_44[bit_cnt] == 1'b1)
                    begin
                        dq_en  <= 1'b0;
                        dq_out <= 1'b0;
                    end
            WAIT       :
                begin
                    dq_en  <= 1'b1;
                    dq_out <= 1'b1;
                end
            INIT_AGAIN :
                if(cnt_us < 20'd499) 
                    begin
                        dq_en  <= 1'b1;
                        dq_out <= 1'b0;
                    end
                else
                    begin
                        dq_en  <= 1'b0;
                        dq_out <= 1'b0;
                    end
            RD_CMD     :
                if(cnt_us > 20'd62) 
                    begin
                        dq_en  <= 1'b0;
                        dq_out <= 1'b0;
                    end
                else    if(cnt_us <= 20'd1)
                    begin
                        dq_en  <= 1'b1;
                        dq_out <= 1'b0;
                    end
                else    if(WR_CC_BE[bit_cnt] == 1'b0)
                    begin
                        dq_en  <= 1'b1;
                        dq_out <= 1'b0;
                    end
                else    if(WR_CC_BE[bit_cnt] == 1'b1)
                    begin
                        dq_en  <= 1'b0;
                        dq_out <= 1'b0;
                    end
            RD_TEMP    :
                if(cnt_us <= 1) 
                    begin
                        dq_en  <= 1'b1;
                        dq_out <= 1'b0;
                    end
                else
                    begin
                        dq_en  <= 1'b0;
                        dq_out <= 1'b0;
                    end
            default:
                begin
                    dq_en  <= 1'b0;
                    dq_out <= 1'b0;
                end
        endcase

//data_temp
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_temp <= 16'b0;
    else    if((state == RD_TEMP) && (cnt_us == 20'd13))
        data_temp <= {dq,data_temp[15:1]};
    else    
        data_temp <= data_temp;
//data
always@(posedge clk_us or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data <= 20'd1;
    else    if((state == RD_TEMP) && (bit_cnt == 4'd15) && (cnt_us == 20'd60)
                && (data_temp[15] == 1'b0))
        data <= data_temp[10:0];
    else    if((state == RD_TEMP) && (bit_cnt == 4'd15) && (cnt_us == 20'd60)
                && (data_temp[15] == 1'b1))
        data <= ~data_temp[10:0] + 1;

endmodule

5.3 seg_dynamic.v

module  seg_dynamic
#(
    parameter   CNT_MAX =   17'd99_999
)
(
    input   wire            sys_clk     ,
    input   wire            sys_rst_n   ,
    input   wire    [26:0]  data        ,

    output  reg     [7:0]   sel         ,
    output  reg     [7:0]   seg          
);



wire     [3:0]   in          ;
wire     [3:0]   ten         ;
wire     [3:0]   hun         ;
wire     [3:0]   tho         ;
wire     [3:0]   ten_tho     ;
wire     [3:0]   hun_tho     ;
wire     [3:0]   mil         ;
wire     [3:0]   must        ;


reg     [3:0]   seg_data    ;
reg     [2:0]   cnt_sel     ;

reg     [16:0]  cnt_1ms     ;
reg             flag_1ms    ;

//cnt_1ms:1ms循环计数
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_1ms <=  17'd0;
    else    if(cnt_1ms == CNT_MAX)
        cnt_1ms <=  17'd0;
    else
        cnt_1ms <=  cnt_1ms + 1'b1;

//flag_1ms:1ms标志信号
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        flag_1ms    <=  1'b0;
    else    if(cnt_1ms == CNT_MAX - 1'b1)
        flag_1ms    <=  1'b1;
    else
        flag_1ms    <=  1'b0;

//cnt_sel:从0到7循环数,用于选择当前显示的数码管
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_sel <=  3'd0;
    else    if((cnt_sel == 3'd7) && (flag_1ms == 1'b1))
        cnt_sel <=  3'd0;
    else    if(flag_1ms == 1'b1)
        cnt_sel <=  cnt_sel + 1'b1;
    else
        cnt_sel <=  cnt_sel;


always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        seg_data <= 8'b0000_0011;
    else
        begin
            case(cnt_sel)
                3'd0: seg_data <= in     ;
                3'd1: seg_data <= ten    ;
                3'd2: seg_data <= hun    ;
                3'd3: seg_data <= tho    ;
                3'd4: seg_data <= ten_tho;
                3'd5: seg_data <= hun_tho;
                3'd6: seg_data <= mil    ;
                3'd7: seg_data <= must   ;
            endcase
        end

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        sel <= 8'b0111_1111;
    else    if(flag_1ms == 1'b1)
        begin
            case(cnt_sel)
                3'd0: sel <= 8'b1111_1110;
                3'd1: sel <= 8'b1111_1101;
                3'd2: sel <= 8'b1111_1011;
                3'd3: sel <= 8'b1111_0111;
                3'd4: sel <= 8'b1110_1111;
                3'd5: sel <= 8'b1101_1111;
                3'd6: sel <= 8'b1011_1111;
                3'd7: sel <= 8'b0111_1111;
            endcase
        end


always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        seg <= 8'b0000_0011;
    else    if(flag_1ms == 1'b1)
        begin
            case(seg_data)
                4'd0: seg <= 8'b0000_0011;
                4'd1: seg <= 8'b1001_1111;
                4'd2: seg <= 8'b0010_0101;
                4'd3: seg <= 8'b0000_1101;
                4'd4: seg <= 8'b1001_1001;
                4'd5: seg <= 8'b0100_1001;
                4'd6: seg <= 8'b0100_0001;
                4'd7: seg <= 8'b0001_1111;
                4'd8: seg <= 8'b0000_0001;
                4'd9: seg <= 8'b0000_1001;
            endcase
        end
    else
        seg <= seg;



bcd_8421    bcd_8421_inst
(
    .sys_clk    (sys_clk  ),
    .sys_rst_n  (sys_rst_n),
    .data       (data     ),

    .in         (in       ), //个
    .ten        (ten      ), //十
    .hun        (hun      ), //百
    .tho        (tho      ), //千
    .ten_tho    (ten_tho  ), //万
    .hun_tho    (hun_tho  ), //十万
    .mil        (mil      ), //百万
    .must       (must     )  //千万
);


endmodule

5.4 bcd_8421.v

module  bcd_8421
(
    input   wire            sys_clk     ,
    input   wire            sys_rst_n   ,
    input   wire    [26:0]  data        ,
    
    output  reg     [3:0]   in          , //个
    output  reg     [3:0]   ten         , //十
    output  reg     [3:0]   hun         , //百
    output  reg     [3:0]   tho         , //千
    output  reg     [3:0]   ten_tho     , //万
    output  reg     [3:0]   hun_tho     , //十万
    output  reg     [3:0]   mil         , //百万
    output  reg     [3:0]   must          //千万

);

reg     [4:0]   cnt_shift   ;
reg     [58:0]  data_shift  ;
reg             shift_flag  ;


always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_shift <= 5'd0;
    else    if((cnt_shift == 5'd28) && (shift_flag == 1'b1))
        cnt_shift <= 5'd0;
    else    if(shift_flag == 1'b1)
        cnt_shift <= cnt_shift + 1'b1;
    else
        cnt_shift <= cnt_shift;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data_shift <= 59'd0;
    else    if(cnt_shift == 5'd0)
        data_shift <= {32'b0,data};
    else    if((cnt_shift <= 5'd27) && (shift_flag == 1'b0))
        begin
            data_shift[30:27] <= (data_shift[30:27] > 4) ? (data_shift[30:27] + 2'd3) : (data_shift[30:27]);
            data_shift[34:31] <= (data_shift[34:31] > 4) ? (data_shift[34:31] + 2'd3) : (data_shift[34:31]);
            data_shift[38:35] <= (data_shift[38:35] > 4) ? (data_shift[38:35] + 2'd3) : (data_shift[38:35]);
            data_shift[42:39] <= (data_shift[42:39] > 4) ? (data_shift[42:39] + 2'd3) : (data_shift[42:39]);
            data_shift[46:43] <= (data_shift[46:43] > 4) ? (data_shift[46:43] + 2'd3) : (data_shift[46:43]);
            data_shift[50:47] <= (data_shift[50:47] > 4) ? (data_shift[50:47] + 2'd3) : (data_shift[50:47]);
            data_shift[54:51] <= (data_shift[54:51] > 4) ? (data_shift[54:51] + 2'd3) : (data_shift[54:51]);
            data_shift[58:55] <= (data_shift[58:55] > 4) ? (data_shift[58:55] + 2'd3) : (data_shift[58:55]);
        end
    else    if((cnt_shift <= 5'd27) && (shift_flag == 1'b1))    
        data_shift <= data_shift << 1;
    else
        data_shift <= data_shift;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        shift_flag <= 1'b0;
    else
        shift_flag <= ~shift_flag;


always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        begin
            in      <= 4'b0;
            ten     <= 4'b0;
            hun     <= 4'b0;
            tho     <= 4'b0;
            ten_tho <= 4'b0;
            hun_tho <= 4'b0;
            mil     <= 4'b0;
            must    <= 4'b0;
        end
    else    if(cnt_shift == 5'd28)
        begin
            in      <= data_shift[30:27];
            ten     <= data_shift[34:31];
            hun     <= data_shift[38:35];
            tho     <= data_shift[42:39];
            ten_tho <= data_shift[46:43];
            hun_tho <= data_shift[50:47];
            mil     <= data_shift[54:51];
            must    <= data_shift[58:55];
        end

endmodule

6. NEXYS4_DDR迪芝伦XC7A100TCSG324-1型的原理图与管脚绑定

直接选择 JA4 端口,即 G17作为 inout 引脚
在这里插入图片描述

ds18b20.xdc


set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports sys_rst_n]

set_property IOSTANDARD LVCMOS33 [get_ports dq]

set_property IOSTANDARD LVCMOS33 [get_ports {seg[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg[0]}]

set_property IOSTANDARD LVCMOS33 [get_ports {sel[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {sel[0]}]

set_property PACKAGE_PIN E3   [get_ports sys_clk]
set_property PACKAGE_PIN J15  [get_ports sys_rst_n]

set_property PACKAGE_PIN G17  [get_ports dq]


set_property PACKAGE_PIN J17 [get_ports {sel[0]}]
set_property PACKAGE_PIN J18 [get_ports {sel[1]}]
set_property PACKAGE_PIN T9  [get_ports {sel[2]}]
set_property PACKAGE_PIN J14 [get_ports {sel[3]}]
set_property PACKAGE_PIN P14 [get_ports {sel[4]}]
set_property PACKAGE_PIN T14 [get_ports {sel[5]}]
set_property PACKAGE_PIN K2  [get_ports {sel[6]}]
set_property PACKAGE_PIN U13 [get_ports {sel[7]}]

set_property PACKAGE_PIN H15 [get_ports {seg[0]}]
set_property PACKAGE_PIN L18 [get_ports {seg[1]}]
set_property PACKAGE_PIN T11 [get_ports {seg[2]}]
set_property PACKAGE_PIN P15 [get_ports {seg[3]}]
set_property PACKAGE_PIN K13 [get_ports {seg[4]}]
set_property PACKAGE_PIN K16 [get_ports {seg[5]}]
set_property PACKAGE_PIN R10 [get_ports {seg[6]}]
set_property PACKAGE_PIN T10 [get_ports {seg[7]}]











  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值