Electrical – VHDL Behaviour of nested for loop

vhdl

Good day. I would like to preface this question by saying that I have searched both this site and the internet but haven't been able to find a solution and that this is my first post here. I apologize in advance if I am violating any posting practices. I would also like to state that I have been working with VHDL for only a few months and am still learning.

My problem lies in the fact that I cannot understand the behaviour of for loops in the context of the code I've written.

The code in question:

    library IEEE;
    use IEEE.std_logic_1164.all;
    use IEEE.numeric_std.all;


    entity grain128a is

    port (
         CLK_I : in std_logic;
         CLKEN_I : in std_logic := '1';
         ARESET_I : in std_logic;

         KEY_I : in std_logic_vector(31 downto 0);
         IV_I  : in std_logic_vector(31 downto 0);

         INJECT_INPUT_I : in std_logic;

         PAD_IV_I : in std_logic_vector(30 downto 0);
         ADD_OUTPUT_I : in std_logic;

        H_O : out std_logic_vector(31 downto 0)
        );
        end entity;


   architecture behav of grain128a is

    signal lfsr, nfsr : unsigned(0 to 127);
    signal func_h, func_g, func_f : std_logic_vector(31 downto 0) := (others=> '0');
    signal ADD_OUTPUT : std_logic_vector(31 downto 0) := (others=> '0');
    begin




        process(ADD_OUTPUT_I)
          begin
           if ADD_OUTPUT_I = '1' then
              ADD_OUTPUT <= (others=> '1');
           else
              ADD_OUTPUT <= (others=> '0');
           end if;
        end process;


    -- the shift registers:
    sr_proc : process(CLK_I)

         procedure calc(constant I : in natural) is
         begin
            func_h(I) <= 
        func_h(I) xor (nfsr(2) xor nfsr(15) xor nfsr(36) xor nfsr(45) xor nfsr(64) xor nfsr(73) 
        xor nfsr(89) xor lfsr(93) xor (nfsr(12) and lfsr(8)) xor (lfsr(13) and lfsr(20)) 
        xor (nfsr(95) and lfsr(42)) xor (lfsr(60) and lfsr(79)) 
        xor (nfsr(12) and nfsr(95) and lfsr(94)));

    func_g(I) <=
        func_g(I) xor (lfsr(0) xor nfsr(0) xor nfsr(26) xor nfsr(56) xor nfsr(91) xor nfsr(96) 
        xor (nfsr(3) and nfsr(67)) xor (nfsr(11) and nfsr(13)) xor (nfsr(17) and nfsr(18)) 
        xor (nfsr(27) and nfsr(59)) xor (nfsr(40) and nfsr(48)) xor (nfsr(61) and nfsr(65)) 
        xor (nfsr(68) and nfsr(84)) xor (nfsr(88) and nfsr(92) and nfsr(93) and nfsr(95))
                xor (nfsr(22) and nfsr(24) and nfsr(25)) xor (nfsr(70) and nfsr(78) and nfsr(82)));

    func_f(I) <=
        func_f(I) xor (lfsr(0) xor lfsr(7) xor lfsr(38) xor lfsr(70) xor lfsr(81) xor lfsr(96));
        end procedure;




    begin
                if ARESET_I = '1' then
                  lfsr <= (others=> '0');
                  nfsr <= (others=> '0');

        elsif rising_edge(CLK_I) then
            if CLKEN_I = '1' then




                if INJECT_INPUT_I = '1' then
                                         lfsr<= lfsr sll 32;
                                         nfsr<= nfsr sll 32;

                    lfsr(96 to 127) <= unsigned(IV_I or (PAD_IV_I & '0'));
                    nfsr(96 to 127) <= unsigned(KEY_I);

                    else
                                     for I in 0 to 31 loop
                                       calc(I);
                                       for j in 1 to 127 loop
                                         lfsr(j-1) <= lfsr(j);
                                         nfsr(j-1) <= nfsr(j);
                                       end loop;
                                        lfsr(127) <= func_f(I) xor (ADD_OUTPUT(I) and func_h(I));
                                        nfsr(127) <= func_g(I) xor (ADD_OUTPUT(I) and func_h(I));
                                       H_O(I) <= func_h(I);

                                      end loop;



                end if;
            end if;
        end if;
    end process;

end behav;

My goal is to compute the gate logic and perform one left shift of lfsr & nfsr for every iteration of the outer for loop, leading to a 32 bit shift in lfsr and nfsr for every clock iteration. However, that is not the behaviour i'm observing. These are the simulation results using ModelSim 10.4a :

lfsr and nfsr loaded

This is the waveform before computation starts

waveform after 1 clock iteration

The waveform after one clock iteration. As is evident the lfsr & nfsr have shifted only one bit, instead of the 32 I was expecting. The gate logic appears to have been replicated 32 times given that func_f,func_g,func_h and H_O are being filled. H_O takes the value of func_h in the next clock iteration.

How would I have to modify the code to achieve a left shift for every loop iteration? Is my implementation of the for loop incorrect? Thanks in advance for the assistance.

Best Answer

It's imperative to remember that VHDL is not a programming language. It's practices and behaviour are different to computer languages. It's a descriptor language, a very different thing.

Remember that in VHDL, signal assignments within a process only take effect at the end of that process.

All 'reads' of the signal values within the process will get the value of the signal at the start of the process, regardless of the assignments made to the signal during the process.

process(RST, CLK) is begin if (RST = '1') then a <= 0; elsif rising_edge(CLK) then a <= a + 2; a <= a + 5; end if; end process;

So in the above process, asserting RST will load integer signal 'a' with 0. Once RST's negated, 'a' will advance once per CLK through the sequence 5, 10, 15, 20, 25 etc. The 'add 2' line will do nothing and can be deleted.

To do what you need, you can (a) copy your signal to variables before your loops, (b) do your loops on the variables, then (c) assign the variables back to the signals after the loops. That'd be the simplest.

Related Topic