一、DS18B20简介
1.DS18B20模块
1.1 序列号
1.2 高速暂存器
0,1字节温度数据;2字节温度报警高位,3字节,温度报警低位;4字节配置寄存器;5,6,7字节设备内部使用(保留位);8字节,CRC循环校验位。
1.2.1 温度传感器
DS18B20的核心模块是温度传感器,温度传感器用户可配置9,10,11,12位(分别对应的温度精度为0.5,0.25,0.125,0.0625),温度测量和AD转换命令[44h]。
温度数据以16位符号扩展的二进制补码形式存储在温度寄存器中。符号位(S)表示温度是正还是负:对于正数S = 0,对于负数S = 1;温度数据帧格式如下:
供电方式的确定,命令Skip ROM [CCh],确定是VDD还是寄生电源供电。
1.2.2 配置寄存器
通过R1和R0设置温度测量分辨率;其余位给设备内部使用,不能覆盖
1.2.3 CRC循环校验
高8位为CRC校验位
2.通信协议:1-wire/单总线
二、DS18B20命令
1.ROM指令
1.1 SKIP ROM [CCh] 跳出ROM
当总线上只有一个DS18B20时,可以不发送64bit数据,以节省时间,读指令(Read Scratchpad [BEh])会默认跟随跳出指令(SKIP ROM [CCh])发出。
2.DS18B20功能指令
三、DS18B20时序
1.初始化时隙
总线拉低480us -> 延时等待60us -> 采样存在脉冲(为1表示初始化失败跳回idle,为0表示初始化结束,开始配置ROM)
2.读写时隙
2.1 写时隙
主设备通过写时隙将命令写入 DS18B20 中,写时隙有两种情况:写“1”和写“0”时 隙。主设备通过写 1 时隙来向 DS18B20 中写入逻辑 1,通过写 0 时隙来向 DS18B20 中写入 逻辑 0。当主设备将总线从高电平拉至低电平时,启动写时隙,所有的写时隙持续时间最 少为 60us,每个写时隙间的恢复时间最少为 1us。 当总线(DQ)拉低后,DS18B20 在 15us 至 60us 之间对总线进行采样,如果采的 DQ 为高电平则发生写 1,如果为低电平则发生写 0,如上图所示(图中的总线控制器即为主设备)。 如果要产生写 1 时隙,必须先将总线拉至逻辑低电平然后释放总线,允许总线在写 隙开始后 15us 内上拉至高电平。若要产生写 0 时隙,必须将总线拉至逻辑低电平并保持不 变最少 60us。
2.2 读时隙
当我们发送完读取供电模式[B4h]或读高速缓存器[BEh]命令时,必须及时地生成读时隙,只有在读时隙 DS18B20 才能向主设备传送数据。每个读时隙最小必须有 60us 的持续 时间以及每个读时隙间至少要有 1us 的恢复时间。当主设备将总线从高电平拉至低电平超 过 1us,启动读时隙,如下图所示。当启动读时隙后,DS18B20 将会向主设备发送“0”或者“1”。DS18B20 通过将总线 拉高来发送 1,将总线拉低来发送 0 。当读时隙完成后,DQ 引脚将通过上拉电阻将总线拉高至高电平的闲置状态。从 DS18B20 中输出的数据在启动读时隙后的 15us 内有效,所以,主设备在读时隙开始后的 15us 内必须释放总线,并且对总线进行采样
四、工程实践
1.系统框图
2.程序设计
2.1 DS18B201驱动模块设计
2.1.1 DS18B20读取流程
1).初始化(IDLE)
2).ROM 配置,跳过ROM(ROM_SKIP)
3).发送温度转换命令,等待温度转换完成;
4).再次初始化,跳过ROM
5).发送温度读取命令,等待温度读取完成
2.1.2 状态机设计
2.1.3 驱动模块代码
module DS18B20_drive (
input clk ,
input rst_n ,
inout dq ,
output [21:0] temp_data ,
output sign ,
output reg temp_data_vld
);
//延时计数器最大值
parameter DELAY_480US = 15'd24_000,
DELAY_240US = 15'd12_000,
DELAY_1US = 15'd50,
DELAY_12US = 15'd600,
DELAY_20US = 15'd1_000 ,
DELAY_15US = 15'd1_500 ,
DELAY_60US = 15'd3_000 ,
DELAY_61US = 15'd3_050 ,
DELAY_80us_sampling = 15'd4_000;
//状态机状态
parameter IDLE = 0,
REST = 1,
RELS = 2,
RACK = 3,
ROM = 4,
CONT = 5,
RCMD = 6,
RTMP = 7;
/**************************************************************
变量/端口定义
**************************************************************/
//三态门
reg dq_en ;
reg dq_out;
wire dq_in ;
reg [2:0] state_c;
reg [2:0] state_n;
//状态跳转条件
wire idle2rst ;
wire rst2rels ;
wire rels2rack;
wire rack2rom ;
wire rack2idle;
wire rom2cont ;
wire rom2rcmd ;
wire rcmd2rtmp;
wire cont2idle;
wire rtmp2idle;
reg rack_flag ;//存在脉冲标志
reg [14:0] DELAY ;
reg [14:0] cnt_delay ;
wire add_cnt_delay;
wire end_cnt_delay;
reg flag;
//主机发送指令
reg [7:0] cmd;
reg [4:0] BIT_MAX ;
reg [3:0] cnt_bit ;
wire add_cnt_bit;
wire end_cnt_bit;
//温度数据转换
reg [15:0] rd_data ; // /*synthsis noprone*/防止优化
reg [21:0] rd_data_r ;
wire [21:0] rd_data_r1;
/**************************************************************
双向端口dq的使用方式
**************************************************************/
assign dq_in = dq; //高阻态的话,则把总线上的数据赋给dq_in
assign dq = dq_en ? dq_out : 1'bz; //使能1则输出,0则高阻态
always @(*) begin
if(state_c == REST || state_c == RELS
|| ((state_c == ROM || state_c == CONT || state_c ==RCMD) && cnt_delay <DELAY_60US )
||(state_c == RTMP && cnt_delay < DELAY_1US))
dq_en = 1;
else
dq_en = 0;
end
/**************************************************************
ASCII
**************************************************************/
reg [47:0] ascii_state;
always @(*)
case(state_c)
IDLE : ascii_state = "IDLE";
REST : ascii_state = "REST";
RELS : ascii_state = "RELS";
RACK : ascii_state = "RACK";
ROM : ascii_state = "ROM ";
CONT : ascii_state = "CONT";
RCMD : ascii_state = "RCMD";
RTMP : ascii_state = "RTMP";
default : ascii_state = "IDLE";
endcase
/**************************************************************
状态机模块
**************************************************************/
//第一段状态机
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
state_c <= IDLE;
end
else begin
state_c <= state_n;
end
end
//第二段状态机
always @(*)begin
case(state_c)
IDLE : if(idle2rst)
state_n = REST;
else
state_n = state_c;
REST : if(rst2rels)
state_n = RELS;
else
state_n = state_c;
RELS : if(rels2rack)
state_n = RACK;
else
state_n = state_c;
RACK : if(rack2rom)
state_n = ROM; //接收到了存在脉冲
else if(rack2idle)
state_n = IDLE; //没有接收到存在脉冲
else
state_n = state_c;
ROM : if(rom2cont)
state_n = CONT; //转换温度
else if(rom2rcmd)
state_n = RCMD; //读暂存器
else
state_n = state_c;
CONT : if(cont2idle)
state_n = IDLE;
else
state_n = state_c;
RCMD : if(rcmd2rtmp)
state_n = RTMP;
else
state_n = state_c;
RTMP : if(rtmp2idle)
state_n = IDLE;
else
state_n = state_c;
default : state_n = state_c;
endcase
end
//状态跳转条件
assign idle2rst = state_c == IDLE && 1 ;
assign rst2rels = state_c == REST && end_cnt_delay; //计满480us
assign rels2rack = state_c == RELS && end_cnt_delay; //计满20us
assign rack2rom = state_c == RACK && ~rack_flag && end_cnt_delay; //采样dq(在80us时采样一次,并寄存住)
assign rack2idle = state_c == RACK && rack_flag && end_cnt_delay;
assign rom2cont = state_c == ROM && end_cnt_bit && !flag ; //8bit数据发送完成
assign rom2rcmd = state_c == ROM && end_cnt_bit && flag ; //8bit数据发送完成
assign rcmd2rtmp = state_c == RCMD && end_cnt_bit ; //8bit数据发送完成
assign cont2idle = state_c == CONT && end_cnt_bit && dq_in ; //采样dq(检测到dq为1)
assign rtmp2idle = state_c == RTMP && end_cnt_bit ; //16bit数据发送完成
/**************************************************************
存在脉冲采样
**************************************************************/
always@(posedge clk or negedge rst_n)
if(!rst_n)
rack_flag <= 1;
else if(state_c == RACK && cnt_delay == DELAY_15US)
rack_flag <= dq_in ;
/**************************************************************
状态跳转flag
**************************************************************/
always@(posedge clk or negedge rst_n)
if(!rst_n)
flag <= 0;
else if(state_c == CONT)
flag <= 1;
else if(rcmd2rtmp)
flag <= 0;
/**************************************************************
延时计数器
**************************************************************/
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt_delay <= 'd0;
else if(add_cnt_delay) begin
if(end_cnt_delay)
cnt_delay <= 'd0;
else
cnt_delay <= cnt_delay + 1'b1;
end
assign add_cnt_delay = !IDLE; //
assign end_cnt_delay = add_cnt_delay && cnt_delay == DELAY - 1;
//延时计数最大值选择
always @(*) begin
case (state_c)
REST : DELAY = DELAY_480US;
RELS : DELAY = DELAY_20US;
RACK : DELAY = DELAY_240US;
ROM : DELAY = DELAY_61US;
CONT : DELAY = DELAY_61US;
RCMD : DELAY = DELAY_61US;
RTMP : DELAY = DELAY_61US;
default : DELAY = 0;
endcase
end
/**************************************************************
描述dq输出
**************************************************************/
always @(*) begin
case (state_c)
ROM : cmd = 8'hCC;
CONT : cmd = 8'h44;
RCMD : cmd = 8'hBE;
default : cmd = 0 ;
endcase
end
//bit计数器
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt_bit <= 'd0;
else if(add_cnt_bit) begin
if(end_cnt_bit)
cnt_bit <= 'd0;
else
cnt_bit <= cnt_bit + 1'b1;
end
assign add_cnt_bit = (state_c == ROM || state_c == CONT ||state_c == RCMD || state_c == RTMP) && end_cnt_delay;
assign end_cnt_bit = add_cnt_bit && cnt_bit == BIT_MAX - 1 ;
//bit计数器最大值选择
always@(*)
if(state_c == RTMP)
BIT_MAX = 5'd16;
else
BIT_MAX = 5'd8;
//写时隙
always@(posedge clk or negedge rst_n)
if(!rst_n )
dq_out <= 1;
else if(state_c == REST)
dq_out <= 0;
else if(state_c == ROM || state_c == CONT || state_c == RCMD)begin
if(cnt_delay < DELAY_1US)
dq_out <= 0;
else if(cnt_delay < DELAY_60US)
dq_out <= cmd[cnt_bit];
end
else if(state_c == RTMP)
if(cnt_delay < DELAY_1US)
dq_out <= 0;
//读时隙
always@(posedge clk or negedge rst_n)
if(!rst_n)
rd_data <= 0;
else if(state_c == RTMP && cnt_delay == DELAY_12US) //在12us时采样,
rd_data[cnt_bit] <= dq_in;
/**************************************************************
温度数据转换
**************************************************************/
//一级处理
always@(posedge clk or negedge rst_n)
if(!rst_n)
rd_data_r <= 0;
else if(rtmp2idle)begin
if(rd_data[15]) //符号位为1,表示负数
rd_data_r <= (~(rd_data[10:0] - 1'b1)) ;
else
rd_data_r <= rd_data[10:0] ;
end
// //二级乘法运算
//always@(posedge clk or negedge rst_n)
// if(!rst_n)
// rd_data_r1 <= 0;
// else
// rd_data_r1 <= rd_data_r * 11'd625; //11'd625 /7'd100
assign rd_data_r1 = rd_data_r * 11'd625;
assign sign = rd_data[15];
assign temp_data = rd_data_r1;
always@(posedge clk or negedge rst_n)
if(!rst_n)
temp_data_vld <= 0;
else
temp_data_vld <= rtmp2idle;
endmodule
2.2 控制模块设计
控制模块将采集到的数据进行转换,并将转换后的数据传递给tx和seg模块
module ctrl (
input clk ,
input rst_n ,
input [21:0] temp_data ,
input sign ,
input temp_data_vld ,
input tx_ready ,
output reg [7:0] tx_din ,
output tx_din_vld ,
output [23:0] display_data
);
binary2bcd #(
.binary_width (22),
.bcd_width (24)
) binary2bcd_inst(
/* input */.sys_clk (clk ),
/* input */.sys_rst_n (rst_n),
/* input [binary_width - 1 : 0] */.binary (temp_data),
/* input */.binary_vliad(temp_data_vld),
/* output reg [bcd_width - 1 : 0] */.bcd (display_data),
/* output reg */.bcd_vliad ()
);
reg flag;
wire cnt_flag;
reg [3:0] cnt_l;
wire add_cnt_l;
wire end_cnt_l;
reg [25:0] cnt_1s;
wire add_cnt_1s;
wire end_cnt_1s;
reg temp_data_vld_r;
always@(posedge clk or negedge rst_n)
if(!rst_n)
temp_data_vld_r <= 0;
else if(temp_data_vld)
temp_data_vld_r <= 1;
assign cnt_flag = temp_data_vld_r && end_cnt_1s;
always@(posedge clk or negedge rst_n)
if(!rst_n)
flag <= 0;
else if(cnt_flag)
flag <= 1;
else if(end_cnt_l)
flag <= 0;
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt_1s <= 'd0;
else if(add_cnt_1s) begin
if(end_cnt_1s)
cnt_1s <= 'd0;
else
cnt_1s <= cnt_1s + 1'b1;
end
assign add_cnt_1s = 1;
assign end_cnt_1s = add_cnt_1s && cnt_1s == 50_000_000 - 1 ;
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt_l <= 'd0;
else if(add_cnt_l) begin
if(end_cnt_l)
cnt_l <= 'd0;
else
cnt_l <= cnt_l + 1'b1;
end
assign add_cnt_l = tx_din_vld ;
assign end_cnt_l = add_cnt_l && cnt_l == 15 - 1 ;
assign tx_din_vld = tx_ready && flag ;
always @(*) begin
case (cnt_l)
0 : tx_din = 8'hCE;
1 : tx_din = 8'hC2;
2 : tx_din = 8'hB6;
3 : tx_din = 8'hC8;
4 : tx_din = ":";
5 : tx_din = sign?"-":"+";
6 : tx_din = display_data[20+:4] + "0";
7 : tx_din = display_data[16+:4] + "0";
8 : tx_din = ".";
9 : tx_din = display_data[12+:4] + "0";
10 : tx_din = display_data[8+:4] + "0";
11 : tx_din = display_data[4+:4] + "0";
12 : tx_din = display_data[0+:4] + "0";
13 : tx_din =8'hA1;
14 : tx_din =8'hE6;
default: ;
endcase
end
endmodule
// binary2bcd #(.binary_width(5),.bcd_width(8)) binary2bcd_inst(
// /*input */.sys_clk (sys_clk),
// /*input */.sys_rst_n (sys_rst_n),
// /*input [binary_width - 1 : 0] */.binary (),
// /*input */.binary_vliad(),
// /*output reg [bcd_width - 1 : 0] */.bcd (),
// /*output reg */.bcd_vliad ()
// );
module binary2bcd #(
parameter binary_width = 5,
parameter bcd_width = 8
)(
input sys_clk ,
input sys_rst_n ,
input [binary_width - 1 : 0] binary ,
input binary_vliad,
output reg [bcd_width - 1 : 0] bcd ,
output reg bcd_vliad
);
parameter SHIFT_MAX = binary_width; //移位次数与二进制的位宽相等
parameter IDLE = 3'b001,
SHIFT = 3'b010,
DONE = 3'b100;
reg [2:0] state;
/* 6个BCD编码,对应输出的BCD编码 */
reg [3:0] bcd_data0,bcd_data1,bcd_data2,bcd_data3,bcd_data4,bcd_data5;
wire [3:0] bcd_temp0,bcd_temp1,bcd_temp2,bcd_temp3,bcd_temp4,bcd_temp5;
//移位次数控制
reg [binary_width - 1 : 0] shift_cnt; //移位的次数,与二进制的位宽相同,可以保证位宽足够使用
wire add_shift_cnt,end_shift_cnt;
always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
shift_cnt <= 'd0;
else if(add_shift_cnt) begin
if(end_shift_cnt)
shift_cnt <= 'd0;
else
shift_cnt <= shift_cnt + 1'b1;
end
assign add_shift_cnt = state == SHIFT;
assign end_shift_cnt = add_shift_cnt && shift_cnt == SHIFT_MAX - 1; //达到最大的移位次数
/* 状态机 */
always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
state <= IDLE;
else case(state)
IDLE : if(binary_vliad == 1'b1)
state <= SHIFT;
SHIFT : if(end_shift_cnt) //达到最大的移位次数
state <= DONE;
DONE : state <= IDLE;
default : state <= IDLE;
endcase
//二进制数据移位
reg [binary_width - 1 : 0] shitf_data;
always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
shitf_data <= 'd0;
else if(state == SHIFT) //处于移位状态时,每个时钟左移对应计数值
shitf_data <= shitf_data << 1'b1;
else //其他状态,保持最新的二进制数据
shitf_data <= binary;
always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n) begin
bcd_data0 <= 4'd0;
bcd_data1 <= 4'd0;
bcd_data2 <= 4'd0;
bcd_data3 <= 4'd0;
bcd_data4 <= 4'd0;
bcd_data5 <= 4'd0;
end
else if(state == SHIFT) begin
bcd_data0 <= {bcd_temp0[2:0],shitf_data[binary_width - 1]}; //更新二进制位宽的最高一位
bcd_data1 <= {bcd_temp1[2:0],bcd_temp0[3]}; //保存上一个BCD缓冲区溢出的一位
bcd_data2 <= {bcd_temp2[2:0],bcd_temp1[3]}; //保存上一个BCD缓冲区溢出的一位
bcd_data3 <= {bcd_temp3[2:0],bcd_temp2[3]}; //保存上一个BCD缓冲区溢出的一位
bcd_data4 <= {bcd_temp4[2:0],bcd_temp3[3]}; //保存上一个BCD缓冲区溢出的一位
bcd_data5 <= {bcd_temp5[2:0],bcd_temp4[3]}; //保存上一个BCD缓冲区溢出的一位
end
else begin
bcd_data0 <= 4'd0;
bcd_data1 <= 4'd0;
bcd_data2 <= 4'd0;
bcd_data3 <= 4'd0;
bcd_data4 <= 4'd0;
bcd_data5 <= 4'd0;
end
//如果当前的BCD缓冲区的数据大于4,就会将该缓冲区的数据加3
assign bcd_temp0 = (bcd_data0 > 4'd4)? (bcd_data0 + 4'd3) : bcd_data0;
assign bcd_temp1 = (bcd_data1 > 4'd4)? (bcd_data1 + 4'd3) : bcd_data1;
assign bcd_temp2 = (bcd_data2 > 4'd4)? (bcd_data2 + 4'd3) : bcd_data2;
assign bcd_temp3 = (bcd_data3 > 4'd4)? (bcd_data3 + 4'd3) : bcd_data3;
assign bcd_temp4 = (bcd_data4 > 4'd4)? (bcd_data4 + 4'd3) : bcd_data4;
assign bcd_temp5 = (bcd_data5 > 4'd4)? (bcd_data5 + 4'd3) : bcd_data5;
//BCD编码数据输出
always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
bcd <= 'd0;
else if(state == DONE)
bcd <= {bcd_data5,bcd_data4,bcd_data3,bcd_data2,bcd_data1,bcd_data0};
//输出一个时钟周期的有效信号
always@(posedge sys_clk or negedge sys_rst_n)
if(!sys_rst_n)
bcd_vliad <= 1'b0;
else if(state == DONE)
bcd_vliad <= 1'b1;
else
bcd_vliad <= 1'b0;
endmodule
2.3 其余模块设计
略
2.4 顶层模块设计
module top(
input clk ,
input rst_n ,
inout dq ,
output [7:0] seg_out ,
output [5:0] sel ,
output tx_dout
);
wire [21:0] temp_data ;
wire temp_data_vld ;
wire [23:0] display_data ;
wire tx_ready ;
wire [7:0] tx_din ;
wire tx_din_vld ;
wire sign ;
DS18B20_drive DS18B20_drive_inst (
/* input */ .clk (clk ),
/* input */ .rst_n (rst_n ),
/* inout */ .dq (dq ),
/* output [21:0] */ .temp_data (temp_data ),
/* output */ .sign (sign ),
/* output reg */ .temp_data_vld(temp_data_vld)
);
seg_d#(.CNT_MAX (100_000))seg_d
(
/* input */.clk (clk ) ,
/* input */.rst_n (rst_n) ,
/* input [24:0] */.display_data (display_data) ,
/* input */.display_vld (1) ,
/* input [5:0] */.display_point(6'b010000) ,
/* output [5:0] */.sel (sel) ,
/* input [5:0] */.display_mask (6'b111111) ,//数码管掩码,高电平表示数码管显示
/* output [7:0] */.seg_out (seg_out)
);
uart_tx #(
.CLK_FREQ(50_000_000),
.BPS (115200 ),
.CHECK ("NONE" )
)uart_tx_inst(
/* input */ .clk (clk ) ,
/* input */ .rst_n (rst_n ) ,
/* input [7:0] */ .tx_din (tx_din ) ,
/* input */ .tx_din_vld(tx_din_vld) ,
/* output */ .tx_ready (tx_ready ) ,
/* output reg */ .tx_dout (tx_dout )
);
ctrl ctrl_inst(
/* input */ .clk (clk ) ,
/* input */ .rst_n (rst_n ) ,
/* input [21:0] */ .temp_data (temp_data ) ,
/* input */ .sign (sign ) ,
/* input reg */ .temp_data_vld(temp_data_vld) ,
/* input */ .tx_ready (tx_ready ) ,
/* output reg [7:0] */ .tx_din (tx_din ) ,
/* output */ .tx_din_vld (tx_din_vld ) ,
/* output [23:0] */ .display_data (display_data )
);
endmodule
3.仿真测试
3.1 仿真测试代码
`timescale 1ns/1ps
module ds18b20_drive_tb();
parameter CLK_CYCLE = 20;
reg sys_clk,sys_rst_n;
always #(CLK_CYCLE/2) sys_clk = ~sys_clk;
initial begin
sys_clk = 1'b1;
sys_rst_n = 1'b0;
#(CLK_CYCLE*2);
sys_rst_n = 1'b1;
end
wire dq;
pullup(dq);
DS18B20_drive DS18B20_drive_inst(
/* input */ .clk (sys_clk ),
/* input */ .rst_n (sys_rst_n ),
/* inout */ .dq (dq ),
/* output [21:0] */ .temp_data (),
/* output */ .sign (),
/* output reg */ .temp_data_vld()
);
ds18b20_model #(
.SIG_DATA(0 ),//0:正数、1:负数
.INT_DATA(85 ),//有效输入 -40 ~ +85
.DEC_DATA(4'b0000) //仅接受4bit-binary输入
)ds18b20_model(
/* input */ .Rst_n (sys_rst_n), //
/* inout */ .dq (dq) //
);
endmodule
`timescale 1ns/1ps
module top_tb();
parameter CLK_CYCLE = 20;
reg sys_clk,sys_rst_n;
always #(CLK_CYCLE/2) sys_clk = ~sys_clk;
initial begin
sys_clk = 1'b1;
sys_rst_n = 1'b0;
#(CLK_CYCLE*2);
sys_rst_n = 1'b1;
end
wire dq;
pullup(dq);
top top_tb(
/* input */ .clk (sys_clk) ,
/* input */ .rst_n (sys_rst_n) ,
/* inout */ .dq (dq ) ,
/* output [7:0] */ .seg_out( ) ,
/* output [5:0] */ .sel ( )
);
ds18b20_model #(
.SIG_DATA(0 ),//0:正数、1:负数
.INT_DATA(85 ),//有效输入 -40 ~ +85
.DEC_DATA(4'b0000) //仅接受4bit-binary输入
)ds18b20_model(
/* input */ .Rst_n (sys_rst_n), //
/* inout */ .dq (dq) //
);
endmodule
3.2 仿真测试图
仿真测试分析:
如图,当仿真串口输入指令8’hBE时,可以观察到DS18B20开始采集温度数据;当仿真串口输入指令8’h44时,可以观察到DS18B20停止采集温度数据;当仿真串口输入指令8’h11时,可以观察到数码管开始显示采集到的温度数据;当仿真串口输入指令8’hff时,可以观察到数码管显示关闭;
4.板级验证
通过串口控制DS18B20板级验证视频