0
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
Matteo
  • 13
  • 4
  • Sequence of statements `exp <= SIGNED(d); act <= SIGNED(y); error := exp - act;` will result in the present values of `exp` and `act` being evaluated in the assignment to `error`. IEEE Std 1076-2008 14.7.5.3 Simulation cycle, steps c) and d) updating signal values precede step f) 2) resuming processes. A new signal value isn't available until the next simulation cycle at the earliest, while a resumed process executes until it suspends (in an implicit wait statement when using a sensitivity list). –  Jul 31 '18 at 23:59
  • Make assignments to exp and act concurrent assignment statements (outside the process, also changing the sensitivity list substituting `exp` and `act` for `d` and `y`) or use `error := SIGNED(d) - SIGNED(y);` where you're not dependent on signal update. The former won't work well, your model is discrete and depends on all the inputs that change changing at the same time to track `error` properly. –  Aug 01 '18 at 00:56
  • 1
    Possible duplicate of [sequential execution in process statement in vhdl](https://stackoverflow.com/questions/50158190/sequential-execution-in-process-statement-in-vhdl) –  Aug 01 '18 at 04:01
  • 1
    Your problem may be that you did not understand yet the difference between variables and signals. If I am right I suggest that you stop coding immediately and have a look at a VHDL book. Understanding this difference is the very first thing to understand before you can do anything useful in VHDL. – Renaud Pacalet Aug 01 '18 at 05:23
  • "...I suggest that you stop coding immediately..." xD that's funny. – JHBonarius Aug 02 '18 at 06:17

0 Answers0