1
votes

I'm trying to write a driver for a MS5541C pressure/temperature sensor, but it doesn't seem like I'm able to. The datasheet provided some calculations which, if I put them into excel seems to work pretty fine. But when I try to write VHDL code for it and display it on a 7segment display it doesn't work.

The calculations provided are:

UT1 = 8 * C5 + 10000

where C5 is calibration data read from PROM

dT = D2 - UT1

Where D2 is the temperature read from the DAC

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

Where temp would be the actual temperature in 0.1 Celsius and C6 is also a calibration temperature.

In my case C5 = 2223 (dec), D2 = 28144 (dec) and C6 = 53. With these numbers I get a temperature of 22.7 degrees Celcius.

The code (MCVE) I use in VHDL is:

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;

The result of this is 2674(dec) or a72(hex) (actual numbers may differ a little bit from the excel because these are two measurements, but this isn't even close)

I've reread the calculations a few times and even tried different approaches, but the results are never correct. I assume it has something to do with the conversions of the types, but I don't know what.

P.s. for the person who wants to read the datasheet:

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

1
Turn these snippets into an MCVE. It's OK to use your example values as Constants, no need for ports, just an empty Entity and your declarations and a simple process in the architecture. What's an MCVE? stackoverflow.com/help/mcve - user_1818839
@BrianDrummond Done - Xinq
You have basic bound check failures in this code ... how did you simulate it? In which simulator? If in Xilinx ISIM, you need to turn runtime checking ON, they are off by default which is an insane choice in a simulator. - user_1818839
I see, I didn't simulate, I programmed it straight into the FPGA. ISE did give a warning, but I failed to check it. The fact that it needs 98 bits seems quite strange to me, since the datasheet says it only uses 64. - Xinq
Well it doesn't need 98 bits, the whole thing is a mess of inappropriate types and word lengths. Re-sizing to 33 bits and storing into a 34 bit vector doesn't help! Having got it working in a spreadsheet, examine what happens at the highest and lowest temperatures, and restrict ranges there. Then use the most appropriate types for each stage : UNsigned or Natural for things that can (and should) never be -ve : that would catch the error QuantumRipple pointed out. I recommend ranged integers for most of it, only converting to low level types where you absolutely have to. - user_1818839

1 Answers

0
votes

At least one problem is that when you do the signed conversion for C5, you are left with -4984, not 2223. You then extend this negative number to 33 bits wide.

If that was the only problem, your final result would be something like 4534, so there is probably another problem, but neither of your other constants that you convert to signed has a leading '1'.

Are C5, C6, D2 actually signed numbers? are they actually 12/7/16 bits wide as read from the prom?

I hope your clock is very slow or this isn't for synthesis, although I suspect you intend to use this in a real system. This kind of math, using variables instead of signals, will have extremely long paths to do it all on one clock cycle. 33 bit operands (on the wide side) exacerbate this problem.

Speaking of operand length, your math will be more efficient if you figure out the maximum value each calculation and operand will hold and use appropriate lengths. The optimizer may fix some of this, but they aren't always perfect.