Altera_Forum
Honored Contributor
12 years agoFixed point arithmetic not working for digital signal processing application
Hi,
I am currently trying to do some simple digital signal processing using the Terasic AD/DA card attached to the Terasic DE0 board (which has a Cyclone III on board). My situation is that I am sending a sine wave an an input to the AD/DA card, and I wish to multiply the amplitude of this sine wave by a factor, then output the result through the AD/DA card again. The AD/DA card recieves a signal and associates to it a signed number (in two's complement format) of 14 bits in length. Similarly, when provided a 14 bit signed number in two's complement format, the AD/DA card outputs a voltage corresponding to the number send to the card (ex. 01111111111111 input = 2 Volts output). So far, it works perfectly when I multiply by integer factors. Then I tried to do somethig similar with fixed point arithmetic (using David Bishop's compatibility VHDL libraries for fixed-point arithmetic in Quartus 12.1). I have uploaded the code. I have also uploaded the resulting image (the red sine wave is the input, and the blue shape is the ouput from the AD/DA card). Here is the idea: There are two channels in the AD/DA card, and so every operation is done twice. When "button" is pressed (If button = '0'), then the level (the signed number coming from the analog-digital converter) is scaled to be between -1 and 1 (representing volts). Then, the voltage is multiplied by a factor (here the factor is 1.45786 as declared at the top of the code). Then, the voltage_op (the voltage resulting from the mathematical operation) is scaled back to a signed number (level_op) that will be sent to the digital-analog converter For completeness, I have also tried to implement a similar program using the following method: When the digital-analog converter provides a number (call it "level"), and I want to multiply by a "factor" (which might be fractional, e.g. factor = 1.5), then I can use integer arithmetic like so: temp = (level * 2^10) * (factor * 2^10) -- Everything is integer output = temp / (2^20) Then, the output should be multiplied like desired. This approached yielded the same result as the code I have provided using fixed-point arithmetic. I suspect I have overlooked a small detail in VHDL coding, but I have been looking for a solution for a week and still haven't found a solution. Can anyone see a flaw in my code? Thank you immensely for your time. For the record, I am a student but this is not homework. I have a job in a physics lab that requires digital signal processing. [EDIT] I contacted Terasic and my assumption that the binary format is two's complement is wrong. The Terasic AD/DA daughter card is using offset binary, meaning that sending the unsigned 14-bit number representation of "0" will output -1V from the Digital-to-analog converter (DAC), while sending the unsigned 14-bit representation of "16383" (2^14 - 1) will output +1V