FPGA project : DS18B20

news2025/1/12 4:55:27

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1030347.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux系统编程——网络编程的学习

Linux系统编程学习相关博文 Linux系统编程——文件编程的学习Linux系统编程——进程的学习Linux系统编程——进程间通信的学习Linux系统编程——线程的学习 Linux系统编程——网络编程的学习 一、概述1. TCP/UDP2. 端口号3. 字节序4. Sockt服务器和客户端的开发步骤1. 服务器2…

网络编程 day4

1->广播模型 接收方 发送方 2->组播模型 接收方 发送方 3->多进程并发服务器 4->多线程并发服务器

openssl 交叉编译(uclibc)

参考文章 openssl 交叉编译_GeYi1998的博客-CSDN博客 本地实际操作一遍,和网上的文章有些不同. 先下载源码 /source/index.html 使用 1.1.1w的版本,最新的3.0.11试了,编译不过,很多gcc的写法问题(error: initializer element is not constant) 解压到 Document 目录下, h…

视频汇聚/视频云存储/视频监控管理平台EasyCVR分发rtsp流起播慢优化步骤详解

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

iOS自动化测试方案(一):MacOS虚拟机保姆级安装Xcode教程

文章目录 一、环境准备二、基础软件三、扩展&#xff1a;usb拓展插件 一、环境准备 1、下载VMware虚拟机的壳子&#xff0c;安装并注册软件(可以百度注册码)&#xff0c;最新版本&#xff1a;v17 2、下MacOS系统iOS镜像文件&#xff0c;用于vmware虚拟机安装&#xff0c;当前镜…

如何用一行CSS实现10种现代布局

现代 CSS 布局使开发人员只需按几下键就可以编写十分有意义且强大的样式规则。上面的讨论和接下来的帖文研究了 10 种强大的 CSS 布局&#xff0c;它们实现了一些非凡的工作。 超级居中&#xff1a;place-items: center 对于第一个“单行”布局&#xff0c;让我们解决所有 CSS…

使用 PyTorch 的计算机视觉简介 (3/6)

一、说明 在本单元中&#xff0c;我们将了解卷积神经网络&#xff08;CNN&#xff09;&#xff0c;它是专门为计算机视觉设计的。 卷积层允许我们从图像中提取某些图像模式&#xff0c;以便最终分类器基于这些特征。 二、卷积神经网络 计算机视觉不同于通用分类&#xff0c;因…

虚拟机中window/ubuntu系统如何联网?

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 参考博客 &#xff08;1&#xff09;VMware虚拟机中Windows11无法连接网络 &#xff08;2&#xff09;图解vmware虚拟机win8无线上网 &#xff08;3&#xff09;VMware中VMnet0、VMnet1、VMnet8是什么 &…

PyTorch深度学习(七)【循环神经网络-提高】

数据集文末分享。 模型&#xff1a; 做完padding之后&#xff0c;就可以转换为张量了。 bidirectional是是否使用双向RNN: 输出隐层两个&#xff1a; 代码&#xff1a; import csvimport timeimport matplotlib.pyplot as pltimport numpy as npimport mathimport gzip # 用…

巨人互动|Facebook海外户Facebook内容的类型

随着人们日益依赖的社交媒体来进行信息获取与交流&#xff0c;Facebook作为全球最大的社交媒体平台之一&#xff0c;那么Facebook的内容都有哪些类型呢&#xff1f;下面小编来讲讲吧&#xff01; 1、实时发生的事 我们需要实时了解时事动态&#xff0c;这样可以使用户对品牌发…

【网络层】IP协议

文章目录 IP协议1. 前提认识(1) IP的定位和作用(2) IP地址的构成(3) 基本概念 2. 协议头格式(1) 两个核心问题 3. 网段划分(重要)(1) 为什么要网段划分(2) 概念(3) 子网划分方案(4) 模拟子网划分 4. 特殊的IP地址5. IP地址的数量限制6. 私有IP地址和公网IP地址7. 路由及路由表(…

学习记忆——宫殿篇——记忆宫殿——记忆桩——火车+外院+客厅+卧室

护板 警示灯 烟筒 采集箱 司炉室 桥 电线杆 棚顶 车厢 护栏 植物 石阶 水泥台 竹门 树干 躺椅 柱子 墙 池 洞 方灯 枕头 树 浴池 墙 射灯 藤条 浴巾框 耳环 窗户 灯 沙发 壁炉 吊灯 兵马俑 门 石佛 沙发椅 圆木 弧形木箱盖 床 窗帘 画板 纸伞 花 沙发背 颜料 抽屉

Hadoop-sqoop

sqoop 1. Sqoop简介及原理 简介&#xff1a; Sqoop是一款开源的工具,主要用于在Hadoop(Hive)与传统的数据库(mysq1.postgresql..)间进行数据的传递&#xff0c;可以将一个关系型数据库&#xff08;例如: MySQL ,Oracle ,Postgres等&#xff09;中的数据导进到Hadoop 的HDFS中&…

【AI视野·今日Robot 机器人论文速览 第三十七期】Wed, 20 Sep 2023

AI视野今日CS.Robotics 机器人学论文速览 Wed, 20 Sep 2023 Totally 53 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Machine Learning-Driven Burrowing with a Snake-Like Robot Authors Sean Even, Holden Gordon, Hoeseok Yang, Yasemin Ozk…

《软件方法》第1章2023版连载(03)建模工作流

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 1.2 建模工作流 1.2.1 建模工作流ABCD 如何能做好需求和设计&#xff0c;达到“低成本制造好卖的系统”的目标&#xff1f;并非喊喊口号就可以&#xff0c;需要静下心来学习和实践一…

基于知识蒸馏的两阶段去雨去雪去雾模型学习记录(一)

前面完成了基于知识蒸馏的去雨去雪去雾模型大的部署与训练&#xff0c;下面则进行代码的学习。 使用debug的方式进行代码的学习。 首先是网络结构展示&#xff1a;轻易不要打开&#xff0c;这个模型太复杂了。说到底倒不是多复杂&#xff0c;就是层数太多了 Net((conv_input):…

玩玩“小藤”开发者套件 Atlas 200I DK A2 之VSCode远程连接

玩玩“小藤”开发者套件 Atlas 200I DK A2 之VSCode远程连接 0. 背景1. VSCode 安装 Remote - SSH 插件2. 安装 OpenSSH 组件3. VSCode SSH 连接 Atlas 200I DK A24. 打开远程文件夹 0. 背景 总所周知&#xff0c;英伟达的GPU供不应求&#xff0c;还各种限制。华为推出了升腾A…

ChatGLM2-6B 部署与微调

文章目录 一、ChatGLM-6B二、ChatGLM2-6B三、本地部署ChatGLM2-6B3.1 命令行模式3.2 网页版部署3.3 本地加载模型权重3.4 模型量化3.5 CPU部署3.6 多卡部署 四、P-tuning v2微调教程4.1 P-tuning v2 原理4.2 P-tuning v2微调实现4.2.1 安装依赖&#xff0c;下载数据集4.2.2 开始…

好题记录 Leetcode 394.字符串解码 中等难度

方法一&#xff1a;递归 思路很简单&#xff0c;比较好理解&#xff0c;注意细节处理&#xff01;&#xff01;&#xff01; class Solution { public:string decodeString(string s) {string ans;for(int i0;s[i]!0;i){if(s[i]>a&&s[i]<z)anss[i];if(s[i]>…

CentOS 7系统安装与配置、常用100条操作命令

CentOS 7 是一个广泛使用的开源 Linux 操作系统&#xff0c;它是 Red Hat Enterprise Linux (RHEL) 的一个免费重建版本&#xff0c;以稳定性和安全性而著称。在 CentOS 7 上安装虚拟机通常使用虚拟化技术&#xff0c;如 VirtualBox 或 VMware 等。以下是 CentOS 7 的简要介绍以…