DS18B20-verilog驱动
1.
module ds18b20_dri1(input clk , input rst_n , inout dq , output reg [19:0] temp_data , output reg sign
);localparam ROM_SKIP_CMD = 8'hCC;
localparam CONVERT_CMD = 8'h44;
localparam READ_TEMP_CMD = 8'hbe; reg [ 4:0] cnt ;
reg clk_1us ;
reg [19:0] cnt_1us ;
reg [ 3:0] flow_cnt ;
reg flow_cnt_ok ;
reg [ 2:0] order_cnt ;
reg [ 3:0] wr_cnt ;
reg [ 4:0] rd_cnt ;
reg rest_ok ;
reg [ 7:0] wr_data ;
reg [15:0] rd_data ;
reg [15:0] org_data ;
reg [10:0] data1 ;
reg cnt_1us_en ;
reg dq_out ;
wire [19:0] data2 ;
assign dq = dq_out;always @ (posedge clk or negedge rst_n) beginif (!rst_n) begincnt <= 5'b0;clk_1us <= 1'b0;endelse if(cnt < 5'd24) begincnt <= cnt + 1'b1;clk_1us <= clk_1us;endelse begincnt <= 5'b0;clk_1us <= ~clk_1us;end
end
always @ (posedge clk_1us or negedge rst_n) beginif (!rst_n)cnt_1us <= 20'b0;else if (cnt_1us_en)cnt_1us <= cnt_1us + 1'b1;elsecnt_1us <= 20'b0;
end
always @ (posedge clk_1us or negedge rst_n) beginif (!rst_n)begin rest_ok<= 1'b0;flow_cnt_ok<= 1'b0;order_cnt<= 3'b0;cnt_1us_en<= 1'b0;flow_cnt<=5'd0;dq_out <= 1'bZ;wr_data<=8'd0;rd_data<=16'd0;wr_cnt<=4'd0;rd_cnt<=5'd0;org_data<=16'd0;end else if (flow_cnt_ok)begin flow_cnt<=((flow_cnt>=5'd12)? (1'b0):(flow_cnt+1'b1));flow_cnt_ok<= 1'b0;end else if (flow_cnt==5'd0||flow_cnt==5'd6)begincnt_1us_en<= 1'b1;if (cnt_1us <= 20'd500)dq_out <= 1'b0;else if (cnt_1us == 20'd501)dq_out <= 1'bz;else if (cnt_1us <= 20'd1000)begin if(!dq) rest_ok <= 1'b1;end else if(rest_ok==1'b1)begin flow_cnt_ok<= 1'b1;cnt_1us_en<= 1'b0;rest_ok<= 1'b0;end else begin cnt_1us_en<= 1'b0;end endelse if (flow_cnt==5'd1||flow_cnt==5'd7)begin wr_data <= ROM_SKIP_CMD;flow_cnt_ok<= 1'b1;endelse if (flow_cnt==5'd3)beginwr_data <= CONVERT_CMD;flow_cnt_ok<= 1'b1;endelse if (flow_cnt==5'd9)beginwr_data <= READ_TEMP_CMD;flow_cnt_ok<= 1'b1;endelse if (flow_cnt==5'd2||flow_cnt==5'd4||flow_cnt==5'd8||flow_cnt==5'd10)begin if(wr_cnt<= 4'd7)begincnt_1us_en<= 1'b1;if (cnt_1us <= 20'd0)dq_out <= 1'b0;else if (cnt_1us <= 20'd60)dq_out <= wr_data[wr_cnt];else if (cnt_1us <= 20'd79)dq_out <= 1'bz; else if (cnt_1us == 20'd80)wr_cnt<=wr_cnt+1'b1;else begincnt_1us_en<= 1'b0;endendelse beginwr_cnt <= 4'b0;cnt_1us_en<= 1'b0;flow_cnt_ok<= 1'b1;endend else if (flow_cnt==5'd5)begincnt_1us_en<= 1'b1;if (cnt_1us >= 20'd10000)begincnt_1us_en<= 1'b0;flow_cnt_ok<= 1'b1;end endelse if (flow_cnt==5'd11)beginif(rd_cnt < 5'd16)begincnt_1us_en <= 1'b1;if (cnt_1us <= 20'd1)dq_out <= 1'b0;else if (cnt_1us <= 20'd13)dq_out <= 1'bz;else if (cnt_1us == 20'd14)beginrd_data <= {dq,rd_data[15:1]}; endelse if (cnt_1us <= 20'd64) begindq_out <= 1'bz;rd_cnt<=rd_cnt+1'b1;endelse cnt_1us_en<=1'b0;endelse beginrd_cnt <= 5'd0;cnt_1us_en<= 1'b0;flow_cnt_ok<= 1'b1;org_data <= rd_data;endendelse if (flow_cnt==5'd12)begincnt_1us_en<= 1'b1;if (cnt_1us >= 20'd100000)begincnt_1us_en<= 1'b0;flow_cnt_ok<= 1'b1;end end
end
always @(posedge clk_1us or negedge rst_n) beginif(!rst_n) beginsign <= 1'b0;data1 <= 11'b0;endelse if(org_data[15] == 1'b0) beginsign <= 1'b0;data1 <= org_data[10:0];endelse if(org_data[15] == 1'b1) beginsign <= 1'b1;data1 <= ~org_data[10:0] + 1'b1;end
end
assign data2 = (data1 * 11'd625)/ 7'd100;
always @(posedge clk_1us or negedge rst_n) beginif(!rst_n)temp_data <= 20'b0;elsetemp_data <= data2;
endendmodule