1
\$\begingroup\$

I am trying to implement a basic spiking neural network on FPGA, and have came across a problem. The design uses fixed point binary addition and subtraction to sum input values. As weights can be positive or negative, I have the following circuit in VHDL:

signal adder_opA : std_logic_vector(31 downto 0); 
signal adder_opB : std_logic_vector(31 downto 0); 
signal adder_res : std_logic_vector(31 downto 0); 
adder_res <= std_logic_vector(unsigned(adder_opA) + unsigned(adder_opB)) when add_sub = '0' else
 std_logic_vector(unsigned(adder_opA) - unsigned(adder_opB)); 

The fixed point scheme I have started using is 5.27 (5 bits for the whole and 27 bits for the fractional part).

The operand A is a register that holds the accumulation of the input weights connected to that neuron. Operand B holds the weights that can be excitatory (add to accumulation) or inhibitory (subtract from accumulation), BUT weights are stored as positive numbers and an additional bit is added in memory to indicate the weight type e.g.

Weight Weight Type Weight Vector
 0.5 0 (exc) 00000.100000000000000000000000000
-2.75 1 (inh) 00010.110000000000000000000000000

First weight addition seems to be incorrect:

Weight accumulation initializes at 0 and the first weight to accumulate is -0.4216

In theory: 0 - 0.4261 = -0.4216

00000.000000000000000000000000000 - 0.011010111110110111111010010 = How to represent -0.4216?
On hardware: The adder result is 11111.100101000001001000000101110 and I am not sure how to handle this.

Question 1. How can this handled in hardware with fixed point addition/subtraction?

Even a simpler case like 1.75 - 3.5 = -1.75 (assuming 5.5 fixed point notation):

00001.11000 -> 1.75
00011.10000 -> 3.5

Question 2. How is this simple calculation worked out in two' complement?

asked Jun 6, 2024 at 19:17
\$\endgroup\$
8
  • 1
    \$\begingroup\$ I'm a little confused about your writing this: \0ドル - 0.4261 = -0.4216\$. The truth is \0ドル - 0.4261 \ne -0.4216\$. I must be misreading you. \$\endgroup\$ Commented Jun 6, 2024 at 19:29
  • 1
    \$\begingroup\$ 2's comp actually has the sign bits going all the way to the left. Have you read the wikipedia article on twos comp? \$\endgroup\$ Commented Jun 6, 2024 at 19:29
  • 1
    \$\begingroup\$ Also, there are several formats for representing negative numbers, including signed-magnitude, ones complement, and twos complement. Since you are in control with VHDL, which of these do you expect to use? I know you ask about working things out in twos complement in your 2nd question. But that doesn't tell me your intent. It tells me a question you have. So what exactly are you planning for negative values? \$\endgroup\$ Commented Jun 6, 2024 at 19:31
  • 1
    \$\begingroup\$ @David777 I don't think we see enough of the code to be of much help. But I'm not an expert on VHDL and I should stand aside and let experts handle this. But my gut is worrying about your use of unsigned when signed might be needed or where conversions between integer and std_logic or std_logic_vector may be something to drill down into. So I'm going to hold short at this point. Other than to suggest you also try using a + not(b) + 1 for subtraction with your given syntax to see if it makes a difference for you. \$\endgroup\$ Commented Jun 6, 2024 at 19:58
  • 1
    \$\begingroup\$ @periblepsis No problem, thanks for the help! \$\endgroup\$ Commented Jun 6, 2024 at 20:00

1 Answer 1

1
\$\begingroup\$

enter image description here

This result is absolutely correct.

00000.011010111110110111111010010 is the number you are subtracting from zero. The adder result is:

11111.100101000001001000000101110 and is the two's complement of of this number. Since the first bit is a "1", you must add the negative sign and take the two's complement.

00001.11000 – >1.75

00011.10000 -> 3.5

11100.01111 -> two’s complement of 3.5

11110.00111 -> 1.75 + two’s complement of 3.5

00001.11000 -> two's complement of answer (-1.75)

answered Jun 6, 2024 at 19:34
\$\endgroup\$
8
  • 1
    \$\begingroup\$ @David777 No one else can, either. It should have been written as 11100.10000 in 5.5 format. \$\endgroup\$ Commented Jun 6, 2024 at 20:06
  • 1
    \$\begingroup\$ @David777 Up until this very moment reading your latest comment above, I had assumed you were fluent with twos complement. Now I'm questioning that assumption. To answer your question, if you want -1.63 in fixed point format the usual hand-approach on paper is to first convert +1.63 to fixed point and then perform a twos complement operation. Similarly, if you have a negative value (upper bit is 1) in fixed point format, you first take the twos complement of it, convert that to decimal, and then prefix the minus sign to it and get the decimal result. Was I wrong to assume as I did? \$\endgroup\$ Commented Jun 6, 2024 at 20:31
  • 1
    \$\begingroup\$ @periblepsis Yeah, I understand this. I think I have noticed my issue! I perform a right shift on the value at some point and replace the MSB with a zero. So I am losing my sign bit! Need to keep the sign bit while shifting. \$\endgroup\$ Commented Jun 6, 2024 at 20:37
  • 1
    \$\begingroup\$ @David777 Losing the sign bit would be bad! Well, hopefully this problem is resolved and I can feel better, too. ;) \$\endgroup\$ Commented Jun 6, 2024 at 20:38
  • 1
    \$\begingroup\$ @periblepsis I will report back and hopefully we can both now sleep tonight! \$\endgroup\$ Commented Jun 6, 2024 at 20:40

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.