]> jspc29.x-matter.uni-frankfurt.de Git - trbnet.git/commitdiff
Add UltraScale temperature read-out
authorThomas Gessler <Thomas.Gessler@exp2.physik.uni-giessen.de>
Fri, 7 Aug 2020 14:52:55 +0000 (16:52 +0200)
committerThomas Gessler <Thomas.Gessler@exp2.physik.uni-giessen.de>
Fri, 7 Aug 2020 14:52:55 +0000 (16:52 +0200)
xilinx/xcku/design.txt [new file with mode: 0644]
xilinx/xcku/read_sysmon.vhd [new file with mode: 0644]
xilinx/xcku/trb_net_xdna.vhd

diff --git a/xilinx/xcku/design.txt b/xilinx/xcku/design.txt
new file mode 100644 (file)
index 0000000..ec29a99
--- /dev/null
@@ -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 (file)
index 0000000..9d9d106
--- /dev/null
@@ -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;
index e0ec0a99c589b5c58dea96ff7a5a7019efd6c330..ceedede8ff601130844c9edcf76795e8c56674a0 100644 (file)
@@ -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;