由于第二次写代码没画时序图,所以代码和时序图一些参数有些不一致,但问题不大。
1:关于状态机的编写,我觉得还是三段式比较好。
2:关于生成其他时钟信号,用来做触发边沿。我不喜欢用这种方法(提一个概念“全局时钟网络”)。所以用产生一个1us base基础计时器,产生一个1us的标志信号。之后的计数器与该计数器级联,记得把
1:在画时序图是,没有画
2:&& 逻辑写成了 || 逻辑
3:三态门输出 Z 写成了 1
4:数据位宽定义错误,因为少思考了一个数据对应的位宽。
4:读取温度时,少记一位。注意data_bit跳转条件,和发指令时不一样的。




- module ds18b20(
- input wire sys_clk ,
- input wire sys_rst_n ,
-
- inout wire dq ,
-
- output reg [19:0] data ,
- output reg sign
- );
-
- // localparam 指令,先发低位。
- localparam WR_CMD_WORD = 16'h44CC ,
- RD_CMD_WORD = 16'hBECC ;
- localparam INIT = 6'b000_001 ,
- WR_CMD = 6'b000_010 ,
- WAIT = 6'b000_100 ,
- INIT_AGIN = 6'b001_000 ,
- RD_CMD = 6'b010_000 ,
- RD_TEMP = 6'b100_000 ;
- // wire signal define
- wire end_cnt_base ;
- wire INITtoWR_CMD ;
- wire WR_CMDtoWAIT ;
- wire WAITtoINIT_AGIN ;
- wire INIT_AGINtoRD_CMD ;
- wire RD_CMDtoRD_TEMP ;
- wire RD_TEMPtoINIT ;
- // reg signal define
- reg [5:0] cnt_base ;
- reg dq_en ;
- reg dq_out ;
- reg [5:0] state_c /*synthesis preserve*/;
- reg [5:0] state_n /*synthesis preserve*/;
- reg [19:0] cnt ;
- reg [4:0] data_bit ;
- reg flag_respond ;
- reg data_done ;
- reg [15:0] data_temp ; // 读取高速缓存器的byte0和byte1,一共16位。
-
- /****************************************************************************************/
- // reg [5:0] cnt_base ;
- // wire end_cnt_base ;
- always @(posedge sys_clk or negedge sys_rst_n)
- if(~sys_rst_n)
- cnt_base <= 6'd0 ;
- else if(end_cnt_base)
- cnt_base <= 6'd0 ;
- else
- cnt_base <= cnt_base + 1'b1 ;
- assign end_cnt_base = cnt_base == 49;
- // reg [5:0] state_c ;
- always @(posedge sys_clk or negedge sys_rst_n)
- if(~sys_rst_n)
- state_c <= INIT;
- else
- state_c <= state_n ;
- // reg [5:0] state_n ;
- always @(*)
- case (state_c)
- INIT :if(INITtoWR_CMD)
- state_n <= WR_CMD ;
- else
- state_n <= INIT ;
- WR_CMD :if(WR_CMDtoWAIT)
- state_n <= WAIT ;
- else
- state_n <= WR_CMD ;
- WAIT :if(WAITtoINIT_AGIN)
- state_n <= INIT_AGIN ;
- else
- state_n <= WAIT ;
- INIT_AGIN :if(INIT_AGINtoRD_CMD)
- state_n <= RD_CMD ;
- else
- state_n <= INIT_AGIN ;
- RD_CMD :if(RD_CMDtoRD_TEMP)
- state_n <= RD_TEMP ;
- else
- state_n <= RD_CMD ;
- RD_TEMP :if(RD_TEMPtoINIT)
- state_n <= INIT ;
- else
- state_n <= RD_TEMP ;
- default : state_n <= INIT ;
- endcase
- // 状态转移条件
- assign INITtoWR_CMD = (state_c == INIT ) && (end_cnt_base && flag_respond == 1'b1 && cnt == 999);
- assign WR_CMDtoWAIT = (state_c == WR_CMD ) && (end_cnt_base ==1'b1 && cnt == 60 && data_bit == 15) ;
- assign WAITtoINIT_AGIN = (state_c == WAIT ) && (end_cnt_base && cnt == 749_999) ;
- assign INIT_AGINtoRD_CMD = (state_c == INIT_AGIN ) && (end_cnt_base && flag_respond == 1'b1 && cnt == 999);
- assign RD_CMDtoRD_TEMP = (state_c == RD_CMD ) && (end_cnt_base ==1'b1 && cnt == 60 && data_bit == 15) ;
- assign RD_TEMPtoINIT = (state_c == RD_TEMP ) && (end_cnt_base ==1'b1 && cnt == 60 && data_done == 1'b1);
- // reg [19:0] cnt ;
- always @(posedge sys_clk or negedge sys_rst_n)
- if(~sys_rst_n)
- cnt <= 20'd0 ;
- else case (state_c)
- INIT : if(cnt == 999 && end_cnt_base == 1'b1)
- cnt <= 20'd0 ;
- else if(end_cnt_base == 1'b1)
- cnt <= cnt + 1'b1 ;
- WR_CMD : if(cnt == 60 && end_cnt_base == 1'b1)
- cnt <= 20'd0 ;
- else if(end_cnt_base == 1'b1)
- cnt <= cnt + 1'b1 ;
- WAIT : if(cnt == 749_999 && end_cnt_base == 1'b1)
- cnt <= 20'd0 ;
- else if(end_cnt_base == 1'b1)
- cnt <= cnt + 1'b1 ;
- INIT_AGIN : if(cnt == 999 && end_cnt_base == 1'b1)
- cnt <= 20'd0 ;
- else if(end_cnt_base == 1'b1)
- cnt <= cnt + 1'b1 ;
- RD_CMD : if(cnt == 60 && end_cnt_base == 1'b1)
- cnt <= 20'd0 ;
- else if(end_cnt_base == 1'b1)
- cnt <= cnt + 1'b1 ;
- RD_TEMP : if(cnt == 60 && end_cnt_base == 1'b1)
- cnt <= 20'd0 ;
- else if(end_cnt_base == 1'b1)
- cnt <= cnt + 1'b1 ;
- default : cnt <= 20'd0 ;
- endcase
- // reg [3:0] data_bit ;
- always @(posedge sys_clk or negedge sys_rst_n)
- if(~sys_rst_n)
- data_bit <= 5'd0 ;
- else case (state_c)
- INIT : data_bit <= 5'd0 ;
- WR_CMD : if(end_cnt_base == 1'b1 && cnt == 60 && data_bit == 15)
- data_bit <= 5'd0 ;
- else if(end_cnt_base == 1'b1 && cnt == 60)
- data_bit <= data_bit + 1'b1 ;
- else
- data_bit <= data_bit ;
- WAIT : data_bit <= 5'd0 ;
- INIT_AGIN : data_bit <= 5'd0 ;
- RD_CMD : if(end_cnt_base == 1'b1 && cnt == 60 && data_bit == 15)
- data_bit <= 5'd0 ;
- else if(end_cnt_base == 1'b1 && cnt == 60)
- data_bit <= data_bit + 1'b1 ;
- else
- data_bit <= data_bit ;
- RD_TEMP : if(end_cnt_base == 1'b1 && cnt == 10 && data_bit == 16) // 第十微秒的时候采样。
- data_bit <= 5'd0 ;
- else if(end_cnt_base == 1'b1 && cnt == 10)
- data_bit <= data_bit + 1'b1 ;
- else
- data_bit <= data_bit ;
- default : data_bit <= 5'd0 ;
- endcase
-
- // reg flag_respond ;
- always @(posedge sys_clk or negedge sys_rst_n)
- if(~sys_rst_n)
- flag_respond <= 1'b0 ;
- else if(state_c != INIT && state_c != INIT_AGIN)
- flag_respond <= 1'b0 ;
- else if((state_c == INIT || state_c == INIT_AGIN) && cnt == 590 && dq == 1'b0)
- flag_respond <= 1'b1 ;
- else
- flag_respond <= flag_respond ;
-
- // reg data_done ;
- always @(posedge sys_clk or negedge sys_rst_n)
- if(~sys_rst_n)
- data_done <= 1'b0 ;
- else if(state_c != RD_TEMP)
- data_done <= 1'b0 ;
- else if(state_c == RD_TEMP && end_cnt_base == 1'b1 && data_bit == 16)
- data_done <= 1'b1 ;
- else
- data_done <= data_done ;
-
- // reg [15:0] data_temp ;
- always @(posedge sys_clk or negedge sys_rst_n)
- if(~sys_rst_n)
- data_temp <= 16'd0 ;
- else if(state_c == RD_TEMP && end_cnt_base == 1'b1 && cnt == 13)
- data_temp <= {dq,data_temp[15:1]} ;
- else
- data_temp <= data_temp ;
-
- // reg dq_en ;
- // reg dq_out ;
- always @(posedge sys_clk or negedge sys_rst_n) begin
- if(~sys_rst_n) begin
- dq_en <= 1'b0 ;
- dq_out <= 1'b0 ;
- end else begin
- case (state_c)
- INIT : begin
- if(cnt >= 0 && cnt <= 499) begin
- dq_en <= 1'b1 ;
- dq_out <= 1'b0 ;
- end else begin
- dq_en <= 1'b0 ;
- dq_out <= 1'b0 ;
- end
- end
- WR_CMD : begin
- if(cnt == 60) begin
- dq_en <= 1'b0 ;
- dq_out <= 1'b0 ;
- end else begin
- if(WR_CMD_WORD[data_bit] == 1'b1) begin
- if(cnt >= 0 && cnt <= 14) begin
- dq_en <= 1'b1 ;
- dq_out <= 1'b0 ;
- end else begin
- dq_en <= 1'b0 ;
- dq_out <= 1'b0 ;
- end
- end else begin
- dq_en <= 1'b1 ;
- dq_out <= 1'b0 ;
- end
- end
- end
- WAIT : begin
- dq_en <= 1'b1 ;
- dq_out <= 1'b1 ;
- end
- INIT_AGIN: begin
- if(cnt >= 0 && cnt <= 499) begin
- dq_en <= 1'b1 ;
- dq_out <= 1'b0 ;
- end else begin
- dq_en <= 1'b0 ;
- dq_out <= 1'b0 ;
- end
- end
- RD_CMD : begin
- if(cnt == 60) begin
- dq_en <= 1'b0 ;
- dq_out <= 1'b0 ;
- end else begin
- if(RD_CMD_WORD[data_bit] == 1'b1) begin
- if(cnt >= 0 && cnt <= 14) begin
- dq_en <= 1'b1 ;
- dq_out <= 1'b0 ;
- end else begin
- dq_en <= 1'b0 ;
- dq_out <= 1'b0 ;
- end
- end else begin
- dq_en <= 1'b1 ;
- dq_out <= 1'b0 ;
- end
- end
- end
- RD_TEMP : begin
- if(cnt == 0 || cnt == 1) begin
- dq_en <= 1'b1 ;
- dq_out <= 1'b0 ;
- end else begin
- dq_en <= 1'b0 ;
- dq_out <= 1'b0 ;
- end
- end
- default: begin
- dq_en <= 1'b0 ;
- dq_out <= 1'b0 ;
- end
- endcase
- end
- end
-
- /***********************************************************************/
- // wire dq
- assign dq = (dq_en == 1'b1) ? dq_out : 1'bz ;
-
- // reg [19:0] data
- always @(posedge sys_clk or negedge sys_rst_n)
- if(~sys_rst_n)
- data <= 20'd0 ;
- else if(state_c == RD_TEMP && data_done == 1'b1)
- if(data_temp[15] == 1'b0)
- data <= data_temp[10:0] * 10'd625;
- else
- data <= (~data_temp[10:0] + 1'b1 ) * 10'd625;
- else
- data <= data ;
-
- // reg sign
- always @(posedge sys_clk or negedge sys_rst_n)
- if(~sys_rst_n)
- sign <= 1'b0 ;
- else if(state_c == RD_TEMP && data_done == 1'b1)
- sign <= data_temp[15];
- else
- sign <= sign ;
-
- endmodule
- module top(
- input wire sys_clk ,
- input wire sys_rst_n ,
-
- inout wire dq ,
-
- output wire ds ,
- output wire oe ,
- output wire shcp ,
- output wire stcp
- );
-
- wire [19:0] data_w /*synthesis keep */;
- wire sign_w ;
- wire [05:00] point_w ;
- wire seg_en_w ;
- assign seg_en_w= 1'b1 ;
- assign point_w = 6'b010_000 ;
-
-
-
- ds18b20 ds18b20_insert(
- .sys_clk ( sys_clk ) ,
- .sys_rst_n ( sys_rst_n ) ,
-
- .dq ( dq ) ,
-
- .data ( 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 ( seg_en_w ) ,
-
- .ds ( ds ) ,
- .oe ( oe ) ,
- .shcp ( shcp ) ,
- .stcp ( stcp )
- );
-
- endmodule
