本想着一天发一个实验的,这个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 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

最低0.47元/天 解锁文章
960

被折叠的 条评论
为什么被折叠?



