# **温度计数字模块设计方案** ## 需求分析 模拟端vout输出方波信号,接入数字芯片,数字芯片分析方波频率,再根据频率和温度关系曲线图,得到实时温度,再输出温度量。 局部截取_20260311_125312 局部截取_20260311_125339 # 设计细节确定 | 数据结构 | 子字段 | 位宽 | 比特序 | 功能描述 | 备注 | | -------- | -------- | --------- | ------- | -------------------------------- | ------------------------------------------------------------ | | **CMD** | W/R | 1 bit | [63] | 读写标识,0:写;1:读 | / | | ^ | ARD FLAG | 1 bit | [62] | 0 | 主动回读模块根据读出芯片请求读出实验数据 | | ^ | CID | 5 bits | [61:57] | 0 | 包括量子测控芯片组及其他需要配置的芯片组 | | ^ | ADDR | 25 bits | [56:32] | 低 25 位地址 | 可与 EXADDR 拼接使用,或直接映射到量子测控芯片的偏移地址 | | ^ | EXADDR | 12 bits | [31:20] | 0 | 可与 ADDR 拼接使用此时寻址空间为 128GByte;该 4096K 的地址空间可按照需求映射给集控中心和外部 SIP 芯片组 | | ^ | LENGTH | 20 bits | [19:0] | 指示读写数据长度,以 Byte 为单位 | 最大支持 1MByte | | **DATA** | - | N*4 bytes | [31:0] | 数据 | 读操作时,无需包含该项 | **通信方式**:串口通信,为115200波特率, 不可更改。采用如上指定数据帧结构配置寄存器(大端序)。 **温度精度**:温度分辨率为小数点后2位,-4032表示-40.32度 **温度测量范围**:-40°C~85°C ,超过则显示最大值。 **系统时钟周期**:50MHz。 **标定方式**:线性标定。**范围**:默认为-40°C对应160kHz, 85°C对应600kHz. **输出**:支持输出类型为3种:温度,频率,和单位采用窗口脉冲上升沿数。 **采样窗口时长**:默认1ms, 支持配置 **读回方式**:两种,可选择主动回传,也可以通过串口发指令直接读寄存器得结果。 **主动回传模式**:默认关闭。可通过配置0x10上报寄存器开启。 **主动回传间隔**:默认50ms,可配置。 # 设计细节 首先,需要设计一个pulse_freq_10ms模块,需要将方波的Vin的频率统计出来,这个模块的input 为clk rst_n ,vin , output为 [19:0]freq,valid。作用是统计10ms内方波的上升沿,获得其频率。 统计出来的频率和时钟周期,设置采用间隔有关系,所以要告诉这个模块, 其次,设计digital_thermometer。input为clk,rst_n, vin, mode(为0时线性输出,为1时使用映射表输出), output 为[15:0]temp_out,[19:0]freq,valid等。 在模式0,就是线性输出freq如果是500(50.0khz)对应的就是-40° 如果是1300 就是85°C 通过temp_out输出。 如果是1模式,则使用一个映射表标定,映射表默认初始化也是线性的,但能够修改 freq_valid拉高,下一个周期就把freq_valid也拉高同时freq_x100hz更新,tenp_out也要跟着变。 逻辑延时93-98 总延时148 **设计通信模块** 使用串口通信,需要用串口简单的读写寄存器,选择是定时输出温度,还是频率, 允许设置更新时间间隔等等。 要实现用固定的指令写寄存器需要做很多事情。 首先,要规定帧结构。固定CMD为64bit,data为32bit。 到时候通过解析帧操作经典5口。 其次,需要一个tb模块,比如uart_driver ,这个东西需要能够把txt变成电平,通过vif喂进去。 uart_driver.do_drive( case.txt) 然后 :vif = 真实接口 然后new一个类my_drv.itf = vif; 我觉得不需要这么麻烦,反正是仿真用的。 要一个能把物理接口,rx tx 的数据 转为经典5口的模块 。经典5口和systemregfile通信,就行读写寄存器了。 需要一个状态机, 空闲状态 ,一直等待接收数据, 此状态可接收到cmd h32 接收cmd L32 状态 , 此状态拿到 cmd l32 ,和上面拼凑一下拿到完整 cmd parse状态 , 基于上面拿到的cmd ,解析,可以知道是读还是写, 地址是什么 ,数据是什么。 同时还可拿到data32吗?不需要在这边拿!要拿的话需要if(rx_done)卡一下才行。结束拉高标志位 写状态 ,可以拿到下一个data32 。 进来的时候先判断当前还剩多少没写。 读状态 ,此时i_rddata准备好了吗?并没有,o_rden拉高一个时钟周期,下一个时钟周期对面把数据放上去,下下个周期才能稳定锁存。所以要读别人,发请求要事情,别人放数据也要时间,第三个时钟周期才能拿到数据。 需要被锁存进来发送缓冲区,同时拉高go 现在uart_ctrl_systemreg 和和简单版的systemregflie写完了 现在要用串口控制 温度传感器了, 用一个串口比较好,因为到时候和上位机通信连一个串口调试助手就行。 ![局部截取_20260408_101045](./温度计数字模块设计报告.assets/局部截取_20260408_101045.png # 寄存器设置 根据刚才补全的 `system_regfile` 模块逻辑,为您整理的寄存器说明表格如下。这些寄存器地址采用 **32位(4字节)对齐** 方式。 ### 1. 寄存器地址映射表 (Register Map) | **偏移地址 (Offset)** | **寄存器名称** | **属性** | **复位值** | **描述** | | --------------------- | -------------- | -------- | -------------- | -------------------------- | | `16'h00` | **TESTR** | R/W | `32'h1234567` | 芯片 ID / 测试寄存器 | | `16'h04` | **DATER** | R/W | `32'h20260406` | 生产日期寄存器 | | `16'h08` | **WIN_MODE_R** | R/W | `32'h000003E8` | 测量窗口时间与输出模式配置 | | `16'h0C` | **CALIB_R** | R/W | `32'h025800A0` | 温度计频率标定参数 | | `16'h10` | **REPORT_R** | R/W | `32'h0000c350` | 自动上报使能与间隔配置 | | `16'h14` | **RESULT** | **RO** | `32'h00000000` | 当前温度计状态与测量结果 | ------ ### 2. 寄存器位域详细说明 #### **WIN_MODE_R (Offset: 0x08)** | **位域** | **名称** | **属性** | **描述** | | --------- | ------------ | -------- | ------------------------------------------------------------ | | `[31:26]` | RESERVED | - | 保留 | | `[25:24]` | **out_mode** | R/W | 输出模式选择: 00: 温度值(0) 01: 原始频率值(1) 10: 单位窗口脉冲计数(2) | | `[23:0]` | **win_us** | R/W | 测量窗口时间,单位为微秒 (us)。默认值 1000us | #### **CALIB_R (Offset: 0x0C)** | **位域** | **名称** | **属性** | **描述** | | --------- | --------------------- | -------- | ---------------------------------------------------- | | `[31:16]` | **temp_85_fre_k** | R/W | 85°C 时对应的传感器频率 (kHz)。默认 600kHz (0x0258) | | `[15:0]` | **temp_neg_40_fre_k** | R/W | -40°C 时对应的传感器频率 (kHz)。默认 160kHz (0x00A0) | #### **REPORT_R (Offset: 0x10)** | **位域** | **名称** | **属性** | **描述** | | --------- | -------------- | -------- | ------------------------------------ | | `[31]` | **report_en** | R/W | 自动上报使能开关。1: 开启,0: 关闭 | | `[30:24]` | RESERVED | - | 保留 | | `[23:0]` | **rep_gap_us** | R/W | 自动上报的时间间隔 (us)。默认值 50ms | #### **RESULT_R(Offset: 0x14)** | **位域** | **名称** | **属性** | **描述** | | --------- | ------------- | -------- | ---------------------------------------------------- | | `[31:24]` | RESERVED | - | 保留 | | `[23:0]` | **therm_out** | **RO** | 温度计实时输出结果。具体定义取决于 `out_mode` 的设置 | ------ ### 使用说明: 1. **写操作**:通过 UART 发送对应的地址和数据即可修改配置(如标定值、测量窗口)。 2. **读操作**:读取 `0x14` 地址可获取当前最新的温度或频率数据,读取前建议先检查 `Bit[31]` 是否为 1。 3. **字节序**:寄存器内部采用大端或小端取决于您的 `uart_ctrl` 逻辑,通常在 FPGA 中建议保持与总线一致。 读data寄存器 80000004 00000004 00000004 00000004 20260407 开启主动上报使能 00000010 00000004 800fc350 00000010 00000004 0000c350 关闭 # 总结 用verilog做一个温度计的数字设计,模拟端vout输出的是方波信号,方波波形低电平是0,高电平是1.2v,波形可能会有极短时间的小下冲,方波的频率代表温度信息,频率越高温度越高,频率范围是50kHz到130KHz之间,对应的温度范围是-40°到85°。方波接入到数字芯片,数字芯片分析方波频率,再根据频率和温度关系图(近似正比),得到实时温度,再输出温度量。