1
0
mirror of https://github.com/pConst/basic_verilog.git synced 2025-01-28 07:02:55 +08:00

626 lines
48 KiB
Plaintext
Raw Blame History

;
;------------------------------------------------------------------------------------------
; Copyright <20> 2012-2013, Xilinx, Inc.
; This file contains confidential and proprietary information of Xilinx, Inc. and is
; protected under U.S. and international copyright and other intellectual property laws.
;------------------------------------------------------------------------------------------
;
; Disclaimer:
; This disclaimer is not a license and does not grant any rights to the materials
; distributed herewith. Except as otherwise provided in a valid license issued to
; you by Xilinx, and to the maximum extent permitted by applicable law: (1) THESE
; MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL FAULTS, AND XILINX HEREBY
; DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY,
; INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT,
; OR FITNESS FOR ANY PARTICULAR PURPOSE; and (2) Xilinx shall not be liable
; (whether in contract or tort, including negligence, or under any other theory
; of liability) for any loss or damage of any kind or nature related to, arising
; under or in connection with these materials, including for any direct, or any
; indirect, special, incidental, or consequential loss or damage (including loss
; of data, profits, goodwill, or any type of loss or damage suffered as a result
; of any action brought by a third party) even if such damage or loss was
; reasonably foreseeable or Xilinx had been advised of the possibility of the same.
;
; CRITICAL APPLICATIONS
; Xilinx products are not designed or intended to be fail-safe, or for use in any
; application requiring fail-safe performance, such as life-support or safety
; devices or systems, Class III medical devices, nuclear facilities, applications
; related to the deployment of airbags, or any other applications that could lead
; to death, personal injury, or severe property or environmental damage
; (individually and collectively, "Critical Applications"). Customer assumes the
; sole risk and liability of any use of Xilinx products in Critical Applications,
; subject only to applicable laws and regulations governing limitations on product
; liability.
;
; THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE AT ALL TIMES.
;
;------------------------------------------------------------------------------------------
;
;
; _ ______ ____ ____ __ __ __
; | |/ / ___| _ \/ ___|| \/ |/ /_
; | ' / | | |_) \___ \| |\/| | '_ \
; | . \ |___| __/ ___) | | | | (_) )
; |_|\_\____|_| |____/|_| |_|\___/
;
;
; PicoBlaze Reference Design.
;
;
; Routines for XADC Communication, Control and Monitoring
;
; Ken Chapman - Xilinx Ltd
;
; 9th January 2013 - Initial Version
;
;
; NOTE - This is not a standalone PSM file. Include this file in a program that
; then calls these routines and works with the values in scratch pad memory.
;
; INCLUDE "xadc_routines.psm"
;
;
; IMPORTANT - These routines interact with input and output ports which must
; be appropriately defined to interface with XADC. The CONSTANT
; directives defined below must correspond with the port assignments.
;
;
; INTRODUCTION
; ------------
;
; This file implements two routines that allow the XADC registers to be read or written
; using the DRP and KCPSM6 interface circuit defined in the hardware. Please see the
; 'kc705_kcpsm6_xadc.vhd' reference design which contains full descriptions of the
; interface and various KCPSM6 input and output ports allocated to it.
;
; This file also includes routines which help to interpret and convert register values
; into their corresponding voltage and temperature values.
;
;------------------------------------------------------------------------------------------
; Hardware Constants
;------------------------------------------------------------------------------------------
;
; The following constants define the input and output ports allocated to the XADC DRP
; interface. These constants reflect the ports used in the 'kc705_kcpsm6_xadc.vhd'
; reference design file and should be modified if different ports are allocated in your
; own designs.
;
; Prior to initiating a read or write transaction, KCPSM6 must present the 7-bit address of
; the target XADC register to the DRP interface using the following output port.
;
CONSTANT XADC_register_address, 80 ; register address[6:0]
;
; If a new value is to be written to an XADC configuration register then the 16-bit value
; must also be presented to the DRP interface using the following pair of output ports.
;
CONSTANT XADC_write_data0, 82 ; new register value[7:0]
CONSTANT XADC_write_data1, 83 ; new register value[15:8]
;
; To initiate a transaction with XADC a value is output to a Constant Optimised Output
; Port. The value of bit0 defines the state of DWE for read (0) or write (1).
;
CONSTANT XADC_start_port, 02 ; 'k_write_strobe' starts transaction
CONSTANT XADC_read_mode, 00000000'b ; DWE = 0 read - bit0
CONSTANT XADC_write_mode, 00000001'b ; DWE = 1 write - bit0
;
; Once a transaction has been started, the hardware will present a 'transaction in progress'
; flag 'tip' to KCPSM6 via the 'XADC_status_port' defined below. KCPSM6 must wait for 'tip'
; to be Low (0) before proceeding to read the register value requested or starting another
; transaction. The status port also provides KCPSM6 with the ability to check if XADC is
; being used, or has been modified, by the JTAG interface. Finally, this port is also used
; to observe the over temperature alarm signal (OT).
;
CONSTANT XADC_status_port, 04
CONSTANT XADC_tip, 00000001'b ; 'transaction in progress' - bit0
CONSTANT XADC_JTAG_busy, 00000010'b ; JTAG busy - bit1
CONSTANT XADC_JTAG_locked, 00000100'b ; JTAG locked - bit2
CONSTANT XADC_JTAG_modified, 00001000'b ; JTAG modified - bit3
CONSTANT XADC_OT_alarm, 00010000'b ; OT over temperature alarm - bit4
;
; Following completion of a read transaction the 16-bit contents of the XADC register can
; be read from the following pair of input ports.
;
CONSTANT XADC_read_data0, 02 ; register value[7:0]
CONSTANT XADC_read_data1, 03 ; register value[15:8]
;
; As well as the 'OT' alarm observed via the 'XADC_status_port', XADC generates up to
; 7 more alarm signals (plus an 8th alarm which is the logical-OR of the 7 alarms). The
; following constant define the input port used by KCPSM6 to observe these alarms and the
; bits to which they have been allocated.
;
CONSTANT XADC_alarm_port, 05
CONSTANT XADC_ALM0_Temperature, 00000001'b ; ALM(0) Temperature - bit0
CONSTANT XADC_ALM1_VCCINT, 00000010'b ; ALM(1) VCCINT - bit1
CONSTANT XADC_ALM2_VCCAUX, 00000100'b ; ALM(2) VCCAUX - bit2
CONSTANT XADC_ALM3_VCCBRAM, 00001000'b ; ALM(3) VCCBRAM - bit3
CONSTANT XADC_ALM4_VCCPINT, 00010000'b ; ALM(4) VCCPINT (Zynq only) - bit4
CONSTANT XADC_ALM5_VCCPAUX, 00100000'b ; ALM(5) VCCPAUX (Zynq only) - bit5
CONSTANT XADC_ALM6_VCCO_DDR, 01000000'b ; ALM(6) VCCO_DDR (Zynq only) - bit6
CONSTANT XADC_ALM7, 10000000'b ; ALM(7) Any alarm - bit7
;
;
;------------------------------------------------------------------------------------------
; Routine to read and return the contents of an XADC register.
;------------------------------------------------------------------------------------------
;
; Reads XADC register via DRP.
; The 7-bit address of the register to be read must be provided in sA.
; The 16-bit register value will be returned in register pair [s9,s8].
;
; Registers used s0, s8, s9 (preserved) and sA.
;
;
read_XADC: OUTPUT sA, XADC_register_address ;set address (DADDR)
OUTPUTK XADC_read_mode, XADC_start_port ;Start read transaction (DWE = 0)
CALL wait_for_XADC_DRP ;wait for DRP to complete
INPUT s8, XADC_read_data0 ;read register value into [s9,s8]
INPUT s9, XADC_read_data1
RETURN
;
;
;------------------------------------------------------------------------------------------
; Routine to write new value to an XADC configuration register.
;------------------------------------------------------------------------------------------
;
; Write XADC register via DRP.
; The address of the register to be written must be provided in sA.
;
; NOTE - There are only 32 writable configuration registers so the
; register address should be in the range 40 to 5F hex.
;
; The 16-bit value to be stored in the configuration register must be provided in
; register pair [s9,s8].
;
; Registers used s0, s8 (preserved), s9 (preserved) and sA (preserved).
;
write_XADC: OUTPUT sA, XADC_register_address ;set address (DADDR)
OUTPUT s8, XADC_write_data0 ;set data (DI[7:0])
OUTPUT s9, XADC_write_data1 ;set data (DI[15:8])
OUTPUTK XADC_write_mode, XADC_start_port ;Start write transaction (DWE = 1)
;
; Test the 'transaction in progress' until it is observed to be Low.
; This will complete a write transaction or indicates when a register value
; is available to be read following a read transaction.
;
wait_for_XADC_DRP: INPUT s0, XADC_status_port
TEST s0, XADC_tip
JUMP NZ, wait_for_XADC_DRP
RETURN
;
;
;------------------------------------------------------------------------------------------
; Routine to read the XADC status and alarm signals.
;------------------------------------------------------------------------------------------
;
; This routine is a simple read of the input ports associated with the XADC status and
; alarm signals with the bits returned in registers 's8' and 's9'.
;
; Hint - Constants have been defined to identify the bit allocations.
; e.g. TEST s8, XADC_ALM1_VCCINT will test the VCCINT alarm bit.
;
;
; Register Bit XADC Signal CONSTANT defined to isolate bit
;
; s8 0 ALM(0) Temperature XADC_ALM0_Temperature
; s8 1 ALM(1) VCCINT XADC_ALM1_VCCINT
; s8 2 ALM(2) VCCAUX XADC_ALM2_VCCAUX
; s8 3 ALM(3) VCCBRAM XADC_ALM3_VCCBRAM
; s8 4 ALM(4) VCCPINT (Zynq only) XADC_ALM4_VCCPINT
; s8 5 ALM(5) VCCPAUX (Zynq only) XADC_ALM5_VCCPAUX
; s8 6 ALM(6) VCCO_DDR (Zynq only) XADC_ALM6_VCCO_DDR
; s8 7 ALM(7) Any alarm XADC_ALM7
;
; s9 1 JTAG busy XADC_JTAG_busy
; s9 2 JTAG locked XADC_JTAG_locked
; s9 3 JTAG modified XADC_JTAG_modified
; s9 4 OT over temperature alarm XADC_OT_alarm
;
; Registers s8 and s9.
;
read_XADC_status: INPUT s8, XADC_alarm_port
INPUT s9, XADC_status_port
AND s9, 00011110'b ;mask unused bits
RETURN
;
;
;------------------------------------------------------------------------------------------
; Routine to convert XADC Temperature sample to degrees centigrade
;------------------------------------------------------------------------------------------
;
; Die temperature is obtained by reading the temperature status register (00 hex) from
; XADC (obviously the die temperature channel must have been sampled for the value to be
; valid and reasonably current).
;
; The temperature sample obtained when reading the status register is 16-bits. Of these,
; it is the 12 most significant bits which are immediately trustworthy and represent a die
; temperature with a theoretical range from -273degC to +230.7degC. The transfer function
; for the 12-bit sample is...
;
; Temperature in degC = ((12-bit_ADC_code x 503.975) / 4096) - 273.15
;
; However, the use of sample averaging (built-in to XADC when enabled, in the application
; or a combination of both) can exploit the 4 least significant bits to minimize
; quantisation effects and/or improve resolution. So in this routine the full 16-bit
; value will be used and converted using the following modified transfer function.
;
; Temperature in degC = ((16-bit_ADC_code x 503.975) / (16 x 4096)) - 273.15
;
; Note that only a part of the theoretical temperature range could ever be observed in
; practice (e.g. -40 to +100 for industrial grade devices) so it is of more value to
; preserve the potentially useful resolution than the unused range. As such this routine
; converts the raw status register value into a new 16-bit value which more directly
; relates to degrees centigrade in a practical range.
;
; Hint - Without any form or sample averaging or filtering then the standard 12-bit
; resolution corresponds with 'steps' of 0.123degC . It is useful to recognise
; that this means that die temperature can be known and presented to the nearest
; WHOLE degree using simple rounding. It can also be justified to round
; temperature to the nearest one half of a degree. Note however that that it
; would be inappropriate to represent die temperature using greater numerical
; accuracy than the 0.123degC step size (i.e. a decimal representation using
; more than one decimal place). So just because the converted value produced
; by this routine appears to have greater resolution it should be used with
; due consideration.
;
;
; This routine will take the 16-bit temperature status register value in register pair
; [s9,s8] and convert it to a 16-bit signed value in register pair [s3,s2] representing
; die temperature in degrees centigrade.
;
; A 16x16 bit multiplication routine generating a 32-bit product is used to maintain a
; high degree of precision throughout the conversion process. The 16-bit temperature
; sample is multiplied by a 16-bit constant representing the value 503.975.
;
; 503.975 x 128 = 64508.8 --> 64509 ---> FBFD hex
;
; Then a 32-bit constant representing 273.15 is subtracted.
;
; 273.15 x 128 x 16 x 4096 = 2291348275.2 --> 2291348275 ---> 88933333 hex
;
; The most significant 16-bits of the 32-bit result will then represent temperature in
; degrees centigrade with a signed <9.7> format meaning 9 integer bits and 7 fractional
; bits providing more than adequate range and precision.
;
;
; Example
; 16-bit ADC Code = 9A85 hex (Theoretically +31.045 degC)
;
; 9A85
; x FBFD
; --------
; 98191C71 --> 98191C71
; - 88933333
; --------
; 0F85E93E --> 0F85
;
; 0F85 hex = 3973 --> 3973 / 128 = 31.039 degC
;
; 0F85 hex = 0000111110000101 --> 000011111.0000101 <9.7> format
; 31 and 5/128
;
;
; Operational limits of an industrial grade device
;
; Temp 16-bit Converted Meaning of
; degC ADC Code <9.7> format signed <9.7> value
;
; -40 766E hex EBFF hex -5121/128 = -40.0078 (-40 and 1/128)
; +100 BD8C hex 3200 hex +12800/128 = +100.0 (+100 and 0/128)
;
;
; Registers used s0, s1, s2 ,s3, s4, s5, s6, s7, s8, s9
;
; Provide: [s9,s8] - 16-bit temperature status register value.
; Returns: [s3,s2] - 16-bit signed <9.7> format temperature in degrees centigrade.
;
convert_XADC_temperature: LOAD s5, s9 ;copy original 16-bit sample
LOAD s4, s8
LOAD s7, FB ;16-bit constant representing 503.975
LOAD s6, FD
CALL mult_16x16 ;[s5,s4]x[s7,s6]=[s3,s2,s1,s0]
SUB s0, 33 ;subtract 32-bit constant representing 273.15
SUBCY s1, 33
SUBCY s2, 93
SUBCY s3, 88
RETURN ;[s3,s2] holds signed <9.7> format
;
;
;------------------------------------------------------------------------------------------
; Routine to convert an internal supply sample to a 16-bit milli-Volt integer value
;------------------------------------------------------------------------------------------
;
; Internal supply voltages are associated with the following status registers (obviously
; a supply must have been sampled for the value stored in a register to be valid).
;
; Power Status Registers (Hex addresses)
; Supply Last sample Minimum Maximum
;
; VCCINT 01 25 21
; VCCAUX 02 26 22
; VCCBRAM 06 27 23
;
; VCCPINT 0D 2C 28 (Zynq Only)
; VCCPAUX 0E 2D 29 (Zynq Only)
; VCCO_DDR 0F 2E 2A (Zynq Only)
;
;
; The value obtained when reading a power supply status register is 16-bits. Of these,
; it is the 12 most significant bits which are immediately trustworthy and represent a
; voltage with a theoretical range from 0v to 2.999v. The transfer function for the
; 12-bit sample is...
;
; Voltage = (12-bit_ADC_code / 4096) x 3
;
; However, the use of sample averaging (built-in to XADC when enabled, in the application
; or a combination of both) can exploit the 4 least significant bits to minimize
; quantisation effects and/or improve resolution. So in this routine the full 16-bit
; value will be used and converted using the following modified transfer function.
;
; Voltage = (16-bit_ADC_code / (16 x 4096) ) x 3
;
;
; This routine takes a 16-bit voltage status register value in register pair [s9,s8] and
; converts it to a 16-bit unsigned integer representing voltage rounded to the nearest
; milli-volt (mV). The standard 12-bit resolution corresponds with 'steps' of 0.732mV so
; 1mV resolution is justified and reasonable especially as this routine will maintain
; higher precision throughout the conversion process.
;
; A 16x16 bit multiplication routine generating a 32-bit product is used to scale
; the status register value into a 'milli-volt' value aligned with the upper 16-bits of
; the 32-bit product. Following multiplication, bit15 of the product represents 0.5mV and
; this is used to round the final voltage value before it is returned.
;
;
; Example
; 16-bit ADC Code = 5555 hex (Theoretically 1.000V = 1000mV)
;
; 5555
; x 0BB8 <-- Scaling factor
; --------
; 03E7FC18 --> 03E7 (upper 16-bits of 32-bit product)
; + 1 (most significant bit of FC18 is High >=0.5mv)
; ----
; 03E8 --> 1000mV
;
;
; Registers used s0, s1, s2 ,s3, s4, s5, s6, s7, s8, s9
;
; Provide: [s9,s8] - 16-bit supply voltage status register value.
; Returns: [s3,s2] - 16-bit unsigned voltage in milli-volts (mV).
;
convert_XADC_supply_voltage: LOAD s5, s9 ;copy original 16-bit sample
LOAD s4, s8
LOAD s7, 0B ;16-bit scaling constant
LOAD s6, B8
CALL mult_16x16 ;[s5,s4]x[s7,s6]=[s3,s2,s1,s0]
TEST s1, 10000000'b ;round up to next mV if fraction
ADDCY s2, 00 ; is 0.5mV or more
ADDCY s3, 00
RETURN ;[s3,s2] holds 16-bit mV value
;
;
;------------------------------------------------------------------------------------------
; Routines to convert Unipolar and Bipolar samples to a 16-bit milli-Volt integer value
;------------------------------------------------------------------------------------------
;
; The external analogue inputs are associated with the following status registers.
; Obviously an analogue input must be connected to XADC and that input must have been
; sampled for the value stored in the corresponding status register to be valid.
;
;
; Analogue Status Register
; Input (Hex addresses)
;
; VP/VN 03
; VAUXP[0]/VAUXN[0] 10
; VAUXP[1]/VAUXN[1] 11
; VAUXP[2]/VAUXN[2] 12
; VAUXP[3]/VAUXN[3] 13
; VAUXP[4]/VAUXN[4] 14
; VAUXP[5]/VAUXN[5] 15
; VAUXP[6]/VAUXN[6] 16
; VAUXP[7]/VAUXN[7] 17
; VAUXP[8]/VAUXN[8] 18
; VAUXP[9]/VAUXN[9] 19
; VAUXP[A]/VAUXN[A] 1A
; VAUXP[B]/VAUXN[B] 1B
; VAUXP[C]/VAUXN[C] 1C
; VAUXP[D]/VAUXN[D] 1D
; VAUXP[E]/VAUXN[E] 1E
; VAUXP[F]/VAUXN[F] 1F
;
;
; An input can be configured to be Unipolar with an input voltage range of 0.0v to +1.0v or
; Bipolar with and input range of -0.5v to +0.5v. In each case the total voltage range is
; 1v and the value read from the status register reflects this range. The only difference
; being that the Unipolar value is unsigned and the Bipolar value is a signed using twos
; complement format.
;
; The value obtained when reading one of these status registers is 16-bits. Of these bits,
; it is the 12 most significant bits which are immediately trustworthy and represent a
; voltage with the following transfer function...
;
; Voltage = 12-bit_ADC_code / 4096
;
; However, the use of sample averaging (built-in to XADC when enabled, in the application
; or a combination of both) can exploit the 4 least significant bits to minimize
; quantisation effects and/or improve resolution. So in this routine the full 16-bit
; value will be used and converted using the following modified transfer function.
;
; Voltage = 16-bit_ADC_code / (16 x 4096)
;
; When an input is Unipolar the ADC_code is a 16-bit unsigned value and must be converted
; to represent a voltage in the range 0.0v to +1.0v. When an input is Bipolar the ADC_code
; is a 16-bit signed value (twos complement) and must be converted to represent a voltage
; in the range -0.5v to +0.5v.
;
; 16-bit Unipolar Unipolar Bipolar Bipolar
; ADC_code value voltage value voltage
;
; 0000 0 0v 0 0v
; 7FFF 32767 0.49998v +32767 +0.49998v
; 8000 32768 0.5v -32768 -0.5v
; FFFF 65535 0.99998v -1 -0.0153v
;
; Both the routines provided below take a 16-bit voltage status register value in register
; pair [s9,s8] and convert it to a 16-bit signed integer representing voltage rounded to
; the nearest milli-volt (mV). The standard 12-bit resolution corresponds with 'steps' of
; 244uV so 1mV resolution is justified and reasonable especially as this routine will
; maintain higher precision throughout the conversion process. Note that the effect of
; rounding may result in converted values of 1000mv for Unipolar and +500mV for Bipolar
; even though the theoretical limit of the transfer function falls slightly short of these
; maximum positive levels.
;
; A Unipolar input should result in converted values in the range 0mV to 1000mv which is
; 0000 to 03E8 hex. Since all values are positive the 16-bit value could be considered to
; be an unsigned 16-bit integer. However, it can be useful to think in terms of the
; returned value being a 16-bit signed integer which only has positive values. In this
; way the same signed representation applies to both Unipolar and Bipolar values.
;
; A Bipolar input should result in values in the range -500mV to +500mv which is FE0C to
; 01F4 hex in 16-bit twos complement.
;
; The conversion process employs a 16x16 bit multiplication routine generating a 32-bit
; product which is used to scale the status register value into a 'milli-volt' value
; aligned with the upper 16-bits of the 32-bit product. Following multiplication of a
; positive value, bit15 of the product represents 0.5mV and this is used to round the
; final voltage value before it is returned.
;
; All Unipolar values are positive so the scaling and rounding is straightforward.
; Positive Bipolar values can also be handled in exactly the same way as Unipolar values.
; When a negative Bipolar value needs to be converted it will be complemented to form a
; positive value which can be scaled and rounded in the same way. The scaled and rounded
; result is then complemented to restore the negative polarity to the value. This scheme
; enables most of the code to be reused but also ensures that rounding effects are balanced
; around zero (something which is easy to get wrong when handling twos complement).
;
;
; Unipolar example
;
; 16-bit ADC Code = E666 hex (Theoretically 0.900V = 900mV)
;
; E666
; x 03E8 <-- Scaling factor
; --------
; 0383FE70 --> 0383 (upper 16-bits of 32-bit product)
; + 1 (most significant bit of FE70 High >=0.5mv)
; ----
; 0384 --> 900mV
;
;
; Bipolar example - Positive
;
; 16-bit ADC Code = 6666 hex (Theoretically +0.39999V = +400mV)
;
; Most significant bit of 999A is Low so value is positive and can be converted
; in the same way as a Unipolar value.
;
; 6666
; x 03E8 <-- Scaling factor
; --------
; 018FFE70 --> 018F (upper 16-bits of 32-bit product)
; + 1 (most significant bit of FE70 high >= +0.5mv)
; ----
; 0190 --> +400mV
;
;
; Bipolar example - Negative
;
; 16-bit ADC Code = 999A hex (Theoretically -0.39999V = -400mV)
;
; Most significant bit of 999A is High so value is negative. In this case the value
; is first converted to a positive number whilst remembering that the value is negative.
;
; 999A --> invert all bits --> 6665 --> +1 --> 6666
;
; Convert the positive value in the same way as a Unipolar value.
;
; 6666
; x 03E8 <-- Scaling factor
; --------
; 018FFE70 --> 018F (upper 16-bits of 32-bit product)
; + 1 (most significant bit of FE70 high >= +0.5mv)
; ----
; 0190 --> +400mV
;
; Restore the negative polarity.
;
; 0190 --> invert all bits --> FE6F --> +1 --> FE70
;
; FE70 --> -400mV
;
;
; Unipolar Conversion
; -------------------
;
; Provide: [s9,s8] - 16-bit Unipolar external input status register value.
; Returns: [s3,s2] - 16-bit signed (but only positive) voltage in milli-volts (mV).
;
; Registers used s0, s1, s2 ,s3, s4, s5, s6, s7, s8, s9
;
convert_XADC_unipolar_voltage: LOAD s5, s9 ;copy original 16-bit sample
LOAD s4, s8
LOAD s7, 03 ;16-bit scaling constant
LOAD s6, E8
CALL mult_16x16 ;[s5,s4]x[s7,s6]=[s3,s2,s1,s0]
TEST s1, 10000000'b ;round up to next mV if fraction
ADDCY s2, 00 ; is 0.5mV or more
ADDCY s3, 00
RETURN ;[s3,s2] holds 16-bit mV value
;
;
;
; Bipolar Conversion
; -------------------
;
; Provide: [s9,s8] - 16-bit Unipolar external input status register value.
; Returns: [s3,s2] - 16-bit signed (but only positive) voltage in milli-volts (mV).
;
; Registers used s0, s1, s2 ,s3, s4, s5, s6, s7, s8, s9
;
convert_XADC_bipolar_voltage: TEST s9, 10000000'b ;test sign of sample
JUMP NZ, negative_bipolar
JUMP convert_XADC_unipolar_voltage ;includes return
;
negative_bipolar: XOR s8, FF ;twos complement sample
XOR s9, FF ;to make positive
ADD s8, 01
ADDCY s9, 00
CALL convert_XADC_unipolar_voltage ;scale and round positive value
XOR s2, FF ;twos complement converted value
XOR s3, FF ;to make negative
ADD s2, 01
ADDCY s3, 00
RETURN ;[s3,s2] holds negative 16-bit mV value
;
;
;------------------------------------------------------------------------------------------
; 16-bit x 16-bit Multiplication routine (unsigned)
;------------------------------------------------------------------------------------------
;
; 16-bit input [s5,s4] (contents of [s5,s4] are not changed)
; 16-bit input [s7,s6]
; 32-bit output [s3,s2,s1,s0]
;
mult_16x16: LOAD s8, 16'd ;16-bits to multiply by
LOAD s3, 00 ;clear result
LOAD s2, 00 ;[s1,s0] do not need to be reset
mult_16x16_loop: SR0 s7 ;multiply by LSB to MSB
SRA s6 ;
JUMP NC, shift32
ADD s2, s4 ;add [s5,s4] to upper 16-bits of result
ADDCY s3, s5
shift32: SRA s3 ;shift result right (/2)
SRA s2 ;shift includes any carry from addition
SRA s1
SRA s0
SUB s8, 1'd ;count iterations
JUMP NZ, mult_16x16_loop
RETURN
;
;
;------------------------------------------------------------------------------------------
; End of 'xadc_routines.psm'
;------------------------------------------------------------------------------------------
;