【问题标题】:type conversion VHDL类型转换 VHDL
【发布时间】:2016-10-25 22:35:48
【问题描述】:

我正在尝试为 MS5541C 压力/温度传感器编写驱动程序,但我似乎无法做到。 数据表提供了一些计算,如果我将它们放入 excel 中似乎工作得很好。 但是当我尝试为其编写 VHDL 代码并将其显示在 7 段显示器上时,它不起作用。

提供的计算是:

UT1 = 8 * C5 + 10000

其中 C5 是从 PROM 读取的校准数据

dT = D2 - UT1

其中 D2 是从 DAC 读取的温度

TEMP = 200 + dT*(C6+100)/2^11

其中 temp 是 0.1 摄氏度的实际温度,C6 也是校准温度。

在我的情况下,C5 = 2223(十进制),D2 = 28144(十进制)和 C6 = 53。 有了这些数字,我得到了 22.7 摄氏度的温度。

我在 VHDL 中使用的代码(MCVE)是:

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

use ieee.numeric_std.all;

ENTITY MS5541C_CONVERTER IS

PORT(
        CLK     : IN STD_LOGIC;
    RST     : IN STD_LOGIC;

    T_OUT   : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)
);
END ENTITY;

ARCHITECTURE MS5541C_CONVERTER OF MS5541C_CONVERTER IS

Constant C5     : STD_LOGIC_VECTOR(11 DOWNTO 0) := "100010101111"; -- Reference temperature
Constant C6     : STD_LOGIC_VECTOR( 6 DOWNTO 0) := "0110101"; -- Temp coefficient of the temperature

Constant D2     : STD_LOGIC_VECTOR(15 DOWNTO 0) := x"6df0"; -- temperature

BEGIN

PROCESS (CLK,RST) 
    VARIABLE UT1    : SIGNED(33 DOWNTO 0);
    VARIABLE dT     : SIGNED(33 DOWNTO 0);
    VARIABLE TEMPE  : SIGNED(33 DOWNTO 0);
    VARIABLE C5_s   : SIGNED(33 DOWNTO 0);
    VARIABLE C6_s   : SIGNED(33 DOWNTO 0);
BEGIN
    C5_s := RESIZE(signed(C5),33);
    C6_s := RESIZE(signed(C6),33);
    IF RST = '1' THEN

    ELSIF rising_edge(CLK) THEN
        UT1 := 8 * C5_s + 10000;
        dT  := RESIZE(signed(D2),33) - UT1;
        TEMPE := 200 + dT*(C6_s + 100)/ 2048;
        T_OUT <= STD_LOGIC_VECTOR(RESIZE(TEMPE,16));
    END If;
END PROCESS;
END ARCHITECTURE;

结果是 2674(十进制)或 a72(十六进制)(实际数字可能与 excel 略有不同,因为这是两个测量值,但这甚至不接近)

我已经重读了几次计算,甚至尝试了不同的方法,但结果永远都不正确。我认为这与类型的转换有关,但我不知道是什么。

附: 对于想要阅读数据表的人:

http://media.digikey.com/pdf/Data%20Sheets/Measurement%20Specialties%20PDFs/MS5541-CM.pdf

【问题讨论】:

  • 把这些 sn-ps 变成一个 MCVE。可以将您的示例值用作常量,不需要端口,只需一个空实体和您的声明以及架构中的一个简单过程。什么是 MCVE? stackoverflow.com/help/mcve
  • @BrianDrummond 完成
  • 你在这段代码中有基本的边界检查失败......你是如何模拟它的?在哪个模拟器?如果在 Xilinx ISIM 中,您需要打开运行时检查,默认情况下它们是关闭的,这在模拟器中是一个疯狂的选择。
  • 我明白了,我没有模拟,我直接将它编程到 FPGA 中。 ISE 确实给出了警告,但我没有检查它。它需要 98 位的事实对我来说似乎很奇怪,因为数据表说它只使用 64。
  • 好吧,它不需要 98 位,整件事就是一堆不合适的类型和字长。重新调整大小为 33 位并存储到 34 位向量中没有帮助!让它在电子表格中工作,检查在最高和最低温度下会发生什么,并限制那里的范围。然后为每个阶段使用最合适的类型:UNsigned 或 Natural 用于可以(并且应该)永远不会是 -ve 的事物:这将捕获 QuantumRipple 指出的错误。我建议大部分使用范围整数,仅在绝对需要的情况下转换为低级类型。

标签: type-conversion vhdl


【解决方案1】:

至少有一个问题是,当您对 C5 进行有符号转换时,您会得到 -4984,而不是 2223。然后您将这个负数扩展到 33 位宽。

如果这是唯一的问题,您的最终结果将类似于 4534,因此可能还有另一个问题,但您转换为有符号的其他常量都没有前导 '1'

C5、C6、D2 是真正有符号的数字吗?从舞会上读取的它们实际上是 12/7/16 位宽吗?

我希望你的时钟很慢,或者这不是用于综合,尽管我怀疑你打算在实际系统中使用它。这种使用变量而不是信号的数学运算将有很长的路径在一个时钟周期内完成所有运算。 33 位操作数(宽边)加剧了这个问题。

说到操作数长度,如果您算出每个计算和操作数将保持的最大值并使用适当的长度,您的数学运算会更有效率。优化器可能会修复其中的一些问题,但它们并不总是完美的。

【讨论】:

  • 谢谢,确实是签名部分!现在结果是 226!我目前使用的是 50MHz 时钟。你建议我应该使用信号而不是变量?我将 Cx 类型转换为 32 位,因为我认为这样可以完成这项工作,并在以后一切正常时担心宽度。
  • 所以我猜这解决了?您的数字似乎在十分之一度内返回,因此 226 (22.6) 与您的预期温度 22.7 非常接近。此外,您列出的临时计算 (TEMP = 200 + dT*(C6+100)2^11 + 1000) 与您在 VHDL 中所做的不匹配;我猜在“2 ^ 11”之前缺少除斜线,但我不知道“+ 1000”应该在哪里出现。你可能在 50 MHz 上没问题,但你应该实施时序约束,或者至少确保该工具建议的 fmax 高于 50MHz(当您不提供约束时,工具会尝试猜测)。
  • 我通常会使用显式 DSP 将这样的数学流水线化到大约 10 个时钟周期,但我能够以 500 MHz 运行它,这就是为什么不进行流水线化也可以的原因。
  • 我从未听说过 DSP 或流水线,但我想了解一下。我的书没有涵盖它(Zwolinski 和 Pedroni),你有什么建议可以让我了解更多吗?
  • 工作中的人推荐了“The Designer's Guide to VHDL”,但老实说,我从来没有破解过 VHDL 的书。我使用了在线语法参考,并从更有经验的同事那里学习了技巧和风格。我写了一个关于时间的文档页面,最后提到了流水线(在解释了为什么你可能需要它之后),但它并没有涵盖实现流水线所需的具体细节。 stackoverflow.com/documentation/vhdl/5936/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多