本想着一天发一个实验的,这个ds18b20,耗时两天。代码写了两次,呜呜~
由于第二次写代码没画时序图,所以代码和时序图一些参数有些不一致,但问题不大。
这里有几件事情值得一提:
1:关于状态机的编写,我觉得还是三段式比较好。
2:关于生成其他时钟信号,用来做触发边沿。我不喜欢用这种方法(提一个概念“全局时钟网络”)。所以用产生一个1us base基础计时器,产生一个1us的标志信号。之后的计数器与该计数器级联,记得把<end_cnt_base>这个标志信号加上。
我犯下的错误:
1:在画时序图是,没有画<end_cnt_base>标志信号,直接默认时钟为周期为1us,造成了混乱。所以以后要注意。
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 definewire 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 definereg [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) beginif(~sys_rst_n) begindq_en <= 1'b0 ;dq_out <= 1'b0 ;end else begincase (state_c)INIT : beginif(cnt >= 0 && cnt <= 499) begindq_en <= 1'b1 ;dq_out <= 1'b0 ;end else begindq_en <= 1'b0 ;dq_out <= 1'b0 ;end endWR_CMD : beginif(cnt == 60) begindq_en <= 1'b0 ;dq_out <= 1'b0 ;end else beginif(WR_CMD_WORD[data_bit] == 1'b1) beginif(cnt >= 0 && cnt <= 14) begindq_en <= 1'b1 ;dq_out <= 1'b0 ;end else begindq_en <= 1'b0 ;dq_out <= 1'b0 ;endend else begindq_en <= 1'b1 ;dq_out <= 1'b0 ;endend endWAIT : begindq_en <= 1'b1 ;dq_out <= 1'b1 ;endINIT_AGIN: beginif(cnt >= 0 && cnt <= 499) begindq_en <= 1'b1 ;dq_out <= 1'b0 ;end else begindq_en <= 1'b0 ;dq_out <= 1'b0 ;end endRD_CMD : beginif(cnt == 60) begindq_en <= 1'b0 ;dq_out <= 1'b0 ;end else beginif(RD_CMD_WORD[data_bit] == 1'b1) beginif(cnt >= 0 && cnt <= 14) begindq_en <= 1'b1 ;dq_out <= 1'b0 ;end else begindq_en <= 1'b0 ;dq_out <= 1'b0 ;endend else begindq_en <= 1'b1 ;dq_out <= 1'b0 ;endend endRD_TEMP : beginif(cnt == 0 || cnt == 1) begindq_en <= 1'b1 ;dq_out <= 1'b0 ;end else begindq_en <= 1'b0 ;dq_out <= 1'b0 ;endenddefault: begindq_en <= 1'b0 ;dq_out <= 1'b0 ;endendcaseendend/***********************************************************************/// 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