Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
16 years ago

LUT help!!!

I have wrote this code for implementing a neural network.What it does is to take some values(inputs) and some weights and computes the SUM(values*weigths).What i want to do is to check if the total sum(values*weights)< threshold and correct the weights in order to sum(values*weights)>=threshold.I think that i have to store the weights on a look up table and change the values in order to sum(values*weights)>=threshold.How i can do this?.My code is :

LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL;

USE IEEE.STD_LOGIC_ARITH.ALL;

USE IEEE.STD_LOGIC_UNSIGNED.ALL;

USE IEEE.STD_LOGIC_SIGNED.ALL;

ENTITY ANN IS

GENERIC ( m : INTEGER := 4; -- Number of inputs or weights

b : INTEGER := 8); --Number of bits per input or weight

PORT ( x1,x2,x3,x4: IN UNSIGNED(b-1 DOWNTO 0);

w : IN UNSIGNED(b-1 DOWNTO 0);

clk: IN STD_LOGIC;

y : buffer UNSIGNED(2*b-1 DOWNTO 0);

id : buffer bit);

END ANN;

ARCHITECTURE NEURAL OF ANN IS

TYPE weights IS ARRAY (1 TO m) OF UNSIGNED(b-1 DOWNTO 0);

TYPE inputs IS ARRAY (1 TO m) OF UNSIGNED(b-1 DOWNTO 0);

BEGIN

PROCESS(clk,w,x1,x2,x3,x4)

VARIABLE weight : weights;

VARIABLE input : inputs;

VARIABLE prod,acc : UNSIGNED(2*b-1 DOWNTO 0);

VARIABLE sub : UNSIGNED(2*b-1 DOWNTO 0);

BEGIN

IF (clk'EVENT AND CLK='1') THEN

weight:=w&weight(1 TO m-1);

END IF;

input(1):=x1;

input(2):=x2;

input(3):=x3;

input(4):=x4;

acc:=(OTHERS=>'0');

FOR j IN 1 TO m LOOP

prod:=input(j)*weight(j);

acc:=acc+prod;

END LOOP;

y<=acc;

END IF;

END PROCESS;

END NEURAL;

70 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    you have 4 inputs x1/x2/x3 and x4. Also You are shifting the weights so you want to use the old weight values as there is only 1 weight input.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Why i want 4 of them and not 3?I am asking this because i have 3 pairs of inpputs-weights.So i need 3 multiply units and one accumulator to sum the results.Finally when you say in parallel what do you mean?

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    What you want is the multiply unit, with 4 of them in parallel and then sum the results from each one.

    With that, it will take 3/4 clocks to get your result.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I found a vhdl code for a simple mac unit in this forum:

    http://www.altera.com/support/examples/vhdl/vhd-unsigned-multiplier.html

    http://www.altera.com/support/examples/vhdl/vhd-signed-multiply-accumulator.html

    Is it write to use one of them(with the diferrence that i will have 6 inputs,3 inputs and 3 weights).Or can i modify it somehow to use just 2 inputs?What i mean is to insert the first 2 inputs do the computation,then insert the next 2 inputs do the computation etc.

    Thanks
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    First I recommend you got an modify your origional code into a proper multiply/accumulate pipeline before trying to modify it, otherwise it will never work on an FPGA at any useful speed. Then we can think about modifying the weights based on the result.

    The problem is, what you want to do would mean having a variable length pipeline as it going to require repeated iterations until the weights are correct, and with a properly built pipeline it will take more clocks to complete depending on the number of iterations. You will need a valid output to tell the next block when you have completed the weight adjustement.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks for your quick response(again).You are right that i think most like vhdl is a programming language because i am a newbie in vhdl.But from the things you wrote you mean that what i want to do is difficult?The first step as far as i know is a simple MAC unit.The difficult part is the part that i have to adjust the weights in order for sum>threshold.Can you please tell me at least if the first part(the MAC unit) is correct?As i mentioned above i want to insert 3 inputs,each of one has a weight and then multiply each input with each weight and finally sum.Thanks again.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    I store those as variables because every time i insert an input their values will be changed.As far as i know variables are used inside process(because their values change every clock time) and signals are constant values.(if i am right).I will try to explain you what exactly i want to do so you can help me.

    --- Quote End ---

    this is incorrect.

    Variables can exist in any process, function or procedure. A signal exists inside an architecture. The difference is that variables are updated immediatly, whereas signals are updated at the next delta. This can have a huge effect on the code you are writing. Take a look at the following code:

    
    signal a, b, c : std_logic;
    process(clk)
      variable x, y, z : std_logic;
    begin
      if rising_edge(clk)
        
        x := input;
        y := x;
        z := y;
        output <= z;
        
        a <= input;
        b <= a;
        c <= b;
        output <= c;
        
      end if;
    end process;
    
    The version using variables desicribes a 1 register delay from input to output. The version using signals describes a 4 register delay from input to output. This is because the variables are updated imediatly, they pass the value straight through. Because the signals are all updated at the same time, they are all updated at the clock edge, therefore each one is a register.

    now, just to screw with your head, here is a version of the a/b/c method above, but using variables, that describes exactly the same behaviour.

    
    process(clk)
      variable a,b,c : std_logic;
    begin
      if rising_edge(clk)
        
        output := c;
        c      := b;
        b      := a;
        a      := input;
        
      end if;
    end process;
    
    Now, because variables before the previous one updates, this will produce a pipeline of 4 registers as well.

    The trick to learning VHDL is not learning the language, but first understanding the hardware you are trying to discribe. Only then can you use tricks of the language to help you discribe things above. No offence, but it looks and sound like you are trying to write VHDL like a programming language, which it is not - it is a hardware description language.

    --- Quote Start ---

    I want to insert some inputs(lets say 3),each of one has one weight(random).So i would like to multiply each input with its own weight and then compute the sum of them.Then i would like to compare this sum with a predetermined threshold and if the sum that i have computed is greated than this threshold its ok.But if the sum is less than the threshold i would like to correct the values of the weights so the total sum is greater than the threshold.I hope i explained it good.

    P.S Sorry for my bad english

    --- Quote End ---

    And again, this points to you thinking VHDL is a programming language. FPGAs and hardware are very good at doing static things and doing repetative tasks. They are not good at decision making. What you want to do sounds like a very complicated task for an FPGA to do.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I store those as variables because every time i insert an input their values will be changed.As far as i know variables are used inside process(because their values change every clock time) and signals are constant values.(if i am right).I will try to explain you what exactly i want to do so you can help me.

    I want to insert some inputs(lets say 3),each of one has one weight(random).So i would like to multiply each input with its own weight and then compute the sum of them.Then i would like to compare this sum with a predetermined threshold and if the sum that i have computed is greated than this threshold its ok.But if the sum is less than the threshold i would like to correct the values of the weights so the total sum is greater than the threshold.I hope i explained it good.

    P.S Sorry for my bad english
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Looking again at your code:

    the stored value weight(m) is never used.

    you expect to multiply and accumulate unregistered values.

    At most, I recon the max clock speed will be very slow, maybe a 2Mhz if you are lucky!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I notice a couple of problems with the code first:

    --- Quote Start ---

    LIBRARY IEEE;

    USE IEEE.STD_LOGIC_1164.ALL;

    USE IEEE.STD_LOGIC_ARITH.ALL;

    USE IEEE.STD_LOGIC_UNSIGNED.ALL;

    USE IEEE.STD_LOGIC_SIGNED.ALL;

    --- Quote End ---

    You cannot use signed and unsigned libraries the same file, only one or the other. if you need both, then replace arith/unsigned/signed with ieee.numeric_std.all instead.

    --- Quote Start ---

    PROCESS(clk,w,x1,x2,x3,x4)

    VARIABLE weight : weights;

    VARIABLE input : inputs;

    VARIABLE prod,acc : UNSIGNED(2*b-1 DOWNTO 0);

    VARIABLE sub : UNSIGNED(2*b-1 DOWNTO 0);

    BEGIN

    --- Quote End ---

    Why are you storing these as variables and not signals? Do you understand the differences between the 2 and how they both behave? It may simulate correctly but unless you are carefull the synthesiser may just do something you weren't expecting. You have to be more careful with variables and synthesis.

    --- Quote Start ---

    END IF;

    input(1):=x1;

    input(2):=x2;

    input(3):=x3;

    input(4):=x4;

    acc:=(OTHERS=>'0');

    FOR j IN 1 TO m LOOP

    prod:=input(j)*weight(j);

    acc:=acc+prod;

    END LOOP;

    y<=acc;

    END IF;

    END PROCESS;

    END NEURAL;

    --- Quote End ---

    Again, I dont think you want to loop and have and accumulate like this. In your code, it will try and add up m values in 1 clock cycle, the more values there are, the slower your FMAX can be.

    For your actual question, you havent said how you need to change the weights if the sum is > theshold. Is there some formula for this (good), or do you have to work it out on an iterative basis (bad).

    There are many ways to store values in memories. You can instantiate an altsyncram or infer the ram from code. Until you explain how you intend to do such things, I dont think we can explain further.