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?
1 Answer 1
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)
-
1\$\begingroup\$ @David777 No one else can, either. It should have been written as 11100.10000 in 5.5 format. \$\endgroup\$periblepsis– periblepsis2024年06月06日 20:06:42 +00:00Commented 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\$periblepsis– periblepsis2024年06月06日 20:31:20 +00:00Commented 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\$David777– David7772024年06月06日 20:37:49 +00:00Commented 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\$periblepsis– periblepsis2024年06月06日 20:38:56 +00:00Commented Jun 6, 2024 at 20:38
-
1\$\begingroup\$ @periblepsis I will report back and hopefully we can both now sleep tonight! \$\endgroup\$David777– David7772024年06月06日 20:40:00 +00:00Commented Jun 6, 2024 at 20:40
unsigned
whensigned
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 usinga + not(b) + 1
for subtraction with your given syntax to see if it makes a difference for you. \$\endgroup\$