LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY WeightsUpdate IS
GENERIC ( n: INTEGER := 1;
m: INTEGER := 3;
b: INTEGER := 8);
PORT ( w0 : in SIGNED (b-1 DOWNTO 0);
w1 : in SIGNED (b-1 DOWNTO 0);
w2 : in SIGNED (b-1 DOWNTO 0);
y : in STD_LOGIC_VECTOR (b-1 DOWNTO 0);
x1 : in STD_LOGIC;
x2 : in STD_LOGIC;
d : in STD_LOGIC_VECTOR (b-1 DOWNTO 0);
up_w0 : out SIGNED (b-1 DOWNTO 0);
up_w1 : out SIGNED (b-1 DOWNTO 0);
up_w2 : out SIGNED (b-1 DOWNTO 0));
END WeightsUpdate;
ARCHITECTURE Behavioral OF WeightsUpdate IS
TYPE weights IS ARRAY (1 TO n*m) OF SIGNED(b-1 DOWNTO 0);
TYPE new_weights IS ARRAY (1 TO n*m) OF SIGNED(b-1 DOWNTO 0);
TYPE inputs IS ARRAY (1 TO m) OF SIGNED(b-1 DOWNTO 0);
TYPE outputs IS ARRAY (1 TO n) OF SIGNED(b-1 DOWNTO 0);
SIGNAL exp, act : SIGNED(b-1 DOWNTO 0);
BEGIN
PROCESS(w0, w1, w2, y, x1, x2, d)
VARIABLE weight: weights;
VARIABLE new_weight: new_weights;
VARIABLE input: inputs;
VARIABLE output: outputs;
VARIABLE error: SIGNED(b-1 DOWNTO 0);
VARIABLE delta_weight: SIGNED(2*b-1 DOWNTO 0);
BEGIN
input(1) := "0000000" & x1;
input(2) := "0000000" & x2;
input(3) := "11111111";
weight(1) := w1;
weight(2) := w2;
weight(3) := w0;
exp <= SIGNED(d);
act <= SIGNED(y);
error := exp - act;
L1: FOR i IN 1 TO m LOOP
delta_weight := input(i) * error;
new_weight(i) := weight(i) + delta_weight(b-1 DOWNTO 0);
END LOOP L1;
up_w0 <= new_weight(3);
up_w1 <= new_weight(1);
up_w2 <= new_weight(2);
END PROCESS;
END Behavioral;
Hi. Today I'm encountering a problem with above VHDL Code. It's a part of my NN and this module is responsible for updating the weights. It's done like:
d - expected_result
y - actual_result
error = expected_result - actual_result
new_weight = old_weight + (input * error)
Error is calculated once. I have 3 inputs to the neuron (one is bias so I set him for -1) and 3 weights (w0, w1, w2 - old_weights), one for every input so I'm doing the update in loop with 3 iterations. Below is the testbench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY WeightsUpdateTB IS
END WeightsUpdateTB;
ARCHITECTURE behavior OF WeightsUpdateTB IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT WeightsUpdate
PORT(
w0 : IN SIGNED(7 downto 0);
w1 : IN SIGNED(7 downto 0);
w2 : IN SIGNED(7 downto 0);
y : IN std_logic_vector(7 downto 0);
x1 : IN std_logic;
x2 : IN std_logic;
d : IN std_logic_vector(7 downto 0);
up_w0 : OUT SIGNED(7 downto 0);
up_w1 : OUT SIGNED(7 downto 0);
up_w2 : OUT SIGNED(7 downto 0)
);
END COMPONENT;
--Inputs
signal w0 : SIGNED(7 downto 0) := (others => '0');
signal w1 : SIGNED(7 downto 0) := (others => '0');
signal w2 : SIGNED(7 downto 0) := (others => '0');
signal y : std_logic_vector(7 downto 0) := (others => '0');
signal x1 : std_logic := '0';
signal x2 : std_logic := '0';
signal d : std_logic_vector(7 downto 0) := (others => '0');
--Outputs
signal up_w0 : SIGNED(7 downto 0);
signal up_w1 : SIGNED(7 downto 0);
signal up_w2 : SIGNED(7 downto 0);
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: WeightsUpdate PORT MAP (
w0 => w0,
w1 => w1,
w2 => w2,
y => y,
x1 => x1,
x2 => x2,
d => d,
up_w0 => up_w0,
up_w1 => up_w1,
up_w2 => up_w2
);
-- Stimulus process
stim_proc: process
begin
w0 <= "00000000";
w1 <= "00110000";
w2 <= "00110000";
y <= "00011111";
x1 <= '1';
x2 <= '1';
d <= "00100000";
wait for 100 ns;
w0 <= "00000000";
w1 <= "00110000";
w2 <= "00110000";
y <= "00011111";
x1 <= '0';
x2 <= '1';
d <= "00000000";
wait for 100 ns;
w0 <= "00000000";
w1 <= "00110000";
w2 <= "00110000";
y <= "00011111";
x1 <= '1';
x2 <= '0';
d <= "00000000";
wait for 100 ns;
w0 <= "00000000";
w1 <= "00110000";
w2 <= "00110000";
y <= "00011111";
x1 <= '1';
x2 <= '1';
d <= "00100000";
wait;
end process;
END;
And simulation: Simulation
And the problem is that it seems like the error is calculated wrong. During the first set of inputs in simulation the error is 0 when it should be 1 and then in second set it's 1 when it should be equal to -31 and so on - looks like it takes value from previous set? The weights in first set should look like:
up_w0 = -1
up_w1 = 49
up_w2 = 49
And second set:
up_w0 = 31
up_w1 = 48
up_w2 = 17
Third:
up_w0 = 31
up_w1 = 17
up_w2 = 48
Fourth:
up_w0 = -1
up_w1 = 49
up_w2 = 49