From 5d3d95459f23df8d8eff90074b681e7af0504559 Mon Sep 17 00:00:00 2001 From: Thomas Gessler Date: Fri, 7 Aug 2020 16:52:55 +0200 Subject: [PATCH] Add UltraScale temperature read-out --- xilinx/xcku/design.txt | 16 +++ xilinx/xcku/read_sysmon.vhd | 216 +++++++++++++++++++++++++++++++++++ xilinx/xcku/trb_net_xdna.vhd | 39 ++++++- 3 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 xilinx/xcku/design.txt create mode 100644 xilinx/xcku/read_sysmon.vhd diff --git a/xilinx/xcku/design.txt b/xilinx/xcku/design.txt new file mode 100644 index 0000000..ec29a99 --- /dev/null +++ b/xilinx/xcku/design.txt @@ -0,0 +1,16 @@ +-- Must use valid headers on all columns +-- Comments can be added to the stimulus file using '--' + +TIME TEMP VCCAUX VCCINT VCCBRAM VP VN VAUXP[0] VAUXN[0] +00000 45 1.8 1.0 1.0 0.5 0.0 0.7 0.0 +05000 85 1.77 1.01 1.01 0.3 0.0 0.2 0.0 + +-- Time stamp data is in nano seconds (ns) +-- Temperature is recorded in C (degrees centigrade) +-- All other channels are recorded as V (Volts) +-- Valid column headers are: +-- TIME, TEMP, VCCAUX, VCCINT, VCCBRAM, VCCPINT, VCCPAUX, VCCDDRO, VP, VN, +-- VUSER0, VUSER1, VUSER2, VUSER3, +-- VAUXP[0], VAUXN[0],...............VAUXP[15], VAUXN[15] +-- External analog inputs are differential so VP = 0.5 and VN = 0.1 the +-- input on channel VP/VN in 0.5 - 0.1 = 0.4V diff --git a/xilinx/xcku/read_sysmon.vhd b/xilinx/xcku/read_sysmon.vhd new file mode 100644 index 0000000..9d9d106 --- /dev/null +++ b/xilinx/xcku/read_sysmon.vhd @@ -0,0 +1,216 @@ +library ieee; +use ieee.std_logic_1164.all; + +library unisim; +use unisim.vcomponents.all; + +entity read_sysmon is + port ( + CLK_100 : in std_logic; + RESET : in std_logic; + TEMP : out std_logic_vector(15 downto 0); + TEMP_VALID : out std_logic; + VCCINT : out std_logic_vector(15 downto 0); + VCCINT_VALID : out std_logic; + VCCAUX : out std_logic_vector(15 downto 0); + VCCAUX_VALID : out std_logic; + VCCBRAM : out std_logic_vector(15 downto 0); + VCCBRAM_VALID : out std_logic + ); +end entity read_sysmon; + +-- The VALID signals go high for one clock cycle when the corresponding value +-- is updated. The outputs keep their values till the next VALID pulse. + +-- Transfer functions from UG580: +-- Voltages: U[V] = (value / 2**16) * 3 +-- Temperature: T[oC] = ((value * 501.3743) / 2**16) - 273.6777 +-- = ((value * 501.3743) - (273.677 * 2**16)) / 2**16 + +-- For conversion with an UltraScale DSP (27x18 multiplier): +-- +-- 501.3743 is b"0_111110101_01011111110100100" as Q9.17 (27-bit signed +-- fixed-point) +-- +-- Multiplication with the 16-bit ADC value extended to 17-bit signed integer +-- yields a Q26.17 (44-bit signed fixed-point) +-- +-- 273.6777 * 2**16 is b"0_01000100011010110101111101_10111111010010000" as +-- Q26.17 (44-bit signed fixed-point) + +-- The Sysmon is kept in default mode (continuously reads out the internal +-- sensors and writes them to DRP registers). The only non-default setting is +-- the clock-conversion factor. + +-- Maximum ADC clock frequency is 5.2 MHz +-- -> Divide 100 MHz DRP clock by 20 for a 5 MHz ADC clock +-- -> Divider value (upper byte of register 0x42) is 0x14 + +architecture structural of read_sysmon is + type state is (wait_eos, read_temp, wait_temp, read_vccint, wait_vccint, + read_vccaux, wait_vccaux, read_vccbram, wait_vccbram); + signal cur_state : state := wait_eos; + + signal do : std_logic_vector(15 downto 0); + signal drdy : std_logic; + signal eos : std_logic; + signal daddr : std_logic_vector(7 downto 0); + signal den : std_logic; +begin + SYSMONE1_inst : SYSMONE1 + generic map ( + INIT_40 => X"0000", + INIT_41 => X"0000", + INIT_42 => X"1400", -- f_DCLK / f_ADCCLK = 20 + INIT_43 => X"0000", + INIT_44 => X"0000", + INIT_45 => X"0000", + INIT_46 => X"0000", + INIT_47 => X"0000", + INIT_48 => X"0000", + INIT_49 => X"0000", + INIT_4A => X"0000", + INIT_4B => X"0000", + INIT_4C => X"0000", + INIT_4D => X"0000", + INIT_4E => X"0000", + INIT_4F => X"0000", + INIT_50 => X"0000", + INIT_51 => X"0000", + INIT_52 => X"0000", + INIT_53 => X"0000", + INIT_54 => X"0000", + INIT_55 => X"0000", + INIT_56 => X"0000", + INIT_57 => X"0000", + INIT_58 => X"0000", + INIT_59 => X"0000", + INIT_5A => X"0000", + INIT_5B => X"0000", + INIT_5C => X"0000", + INIT_5D => X"0000", + INIT_5E => X"0000", + INIT_5F => X"0000", + INIT_60 => X"0000", + INIT_61 => X"0000", + INIT_62 => X"0000", + INIT_63 => X"0000", + INIT_64 => X"0000", + INIT_65 => X"0000", + INIT_66 => X"0000", + INIT_67 => X"0000", + INIT_68 => X"0000", + INIT_69 => X"0000", + INIT_6A => X"0000", + INIT_6B => X"0000", + INIT_6C => X"0000", + INIT_6D => X"0000", + INIT_6E => X"0000", + INIT_6F => X"0000", + IS_CONVSTCLK_INVERTED => '0', + IS_DCLK_INVERTED => '0', + SIM_MONITOR_FILE => "design.txt", + SYSMON_VUSER0_BANK => 0, + SYSMON_VUSER0_MONITOR => "NONE", + SYSMON_VUSER1_BANK => 0, + SYSMON_VUSER1_MONITOR => "NONE", + SYSMON_VUSER2_BANK => 0, + SYSMON_VUSER2_MONITOR => "NONE", + SYSMON_VUSER3_MONITOR => "NONE" + ) + port map ( + ALM => open, + OT => open, + DO => do, + DRDY => drdy, + I2C_SCLK_TS => open, + I2C_SDA_TS => open, + BUSY => open, + CHANNEL => open, + EOC => open, + EOS => eos, + JTAGBUSY => open, + JTAGLOCKED => open, + JTAGMODIFIED => open, + MUXADDR => open, + VAUXN => (others => '0'), + VAUXP => (others => '0'), + CONVST => '0', + CONVSTCLK => '0', + RESET => RESET, + VN => '0', + VP => '0', + DADDR => daddr, + DCLK => CLK_100, + DEN => den, + DI => x"00_00", + DWE => '0', + I2C_SCLK => '1', + I2C_SDA => '1' + ); + + -- Wait until the current sampling sequence for all sensors is finished + -- (eos = '1'), then read out the DRP registers for each ADC value and + -- update the outputs. + process (CLK_100) is + begin + if rising_edge(CLK_100) then + den <= '0'; + daddr <= x"00"; + TEMP_VALID <= '0'; + VCCINT_VALID <= '0'; + VCCAUX_VALID <= '0'; + VCCBRAM_VALID <= '0'; + if RESET = '1' then + cur_state <= wait_eos; + else + case cur_state is + when wait_eos => + if eos = '1' then + cur_state <= read_temp; + end if; + when read_temp => + daddr <= x"00"; + den <= '1'; + cur_state <= wait_temp; + when wait_temp => + if drdy = '1' then + TEMP <= do; + TEMP_VALID <= '1'; + cur_state <= read_vccint; + end if; + when read_vccint => + daddr <= x"01"; + den <= '1'; + cur_state <= wait_vccint; + when wait_vccint => + if drdy = '1' then + VCCINT <= do; + VCCINT_VALID <= '1'; + cur_state <= read_vccaux; + end if; + when read_vccaux => + daddr <= x"02"; + den <= '1'; + cur_state <= wait_vccaux; + when wait_vccaux => + if drdy = '1' then + VCCAUX <= do; + VCCAUX_VALID <= '1'; + cur_state <= read_vccbram; + end if; + when read_vccbram => + daddr <= x"06"; + den <= '1'; + cur_state <= wait_vccbram; + when wait_vccbram => + if drdy = '1' then + VCCBRAM <= do; + VCCBRAM_VALID <= '1'; + cur_state <= wait_eos; + end if; + end case; + end if; + end if; + end process; +end architecture structural; diff --git a/xilinx/xcku/trb_net_xdna.vhd b/xilinx/xcku/trb_net_xdna.vhd index e0ec0a9..ceedede 100644 --- a/xilinx/xcku/trb_net_xdna.vhd +++ b/xilinx/xcku/trb_net_xdna.vhd @@ -1,5 +1,6 @@ library ieee; use ieee.std_logic_1164.all; +use ieee.numeric_std.all; entity trb_net_xdna is port ( @@ -19,6 +20,15 @@ architecture behavioral of trb_net_xdna is signal dna_valid : std_logic; signal dna : std_logic_vector(95 downto 0); + + constant temp_coeff_q9_17 : signed(26 downto 0) + := b"0_111110101_01011111110100100"; + constant temp_offset_q26_17 : signed(43 downto 0) + := b"0_01000100011010110101111101_10111111010010000"; + + signal temp_sysmon : std_logic_vector(15 downto 0); + signal temp_sysmon_signed : signed(16 downto 0); + signal temp_degc_q10_33 : signed(43 downto 0); begin THE_XDNA : entity work.read_dna_address port map ( @@ -28,6 +38,20 @@ begin VALID => dna_valid ); + THE_SYSMON : entity work.read_sysmon + port map ( + CLK_100 => CLK, + RESET => RESET, + TEMP => temp_sysmon, + TEMP_VALID => open, + VCCINT => open, + VCCINT_VALID => open, + VCCAUX => open, + VCCAUX_VALID => open, + VCCBRAM => open, + VCCBRAM_VALID => open + ); + PROC_STORE_ID: process(CLK) is begin @@ -72,5 +96,18 @@ begin end if; end process PROC_STORE_ID; - TEMP_OUT <= x"000"; + temp_sysmon_signed <= signed('0' & temp_sysmon); + + process (CLK) is + begin + if rising_edge(CLK) then + temp_degc_q10_33 <= (temp_coeff_q9_17 * temp_sysmon_signed) + - temp_offset_q26_17; + end if; + end process; + + -- Generate temperature output vector based on the DS18B20 format: + -- in degC as Q7.4 (12-bit signed fixed-point) + TEMP_OUT <= temp_degc_q10_33(43) + & std_logic_vector(temp_degc_q10_33(39 downto 29)); end architecture behavioral; -- 2.43.0