0
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ You can use for loops in testbenches and simulation, if you use them in actual hardware, it will be only to make multiple 'copies' of the same hardware or to assign multiple statements without being redundant. \$\endgroup\$ – Voltage Spike May 19 '17 at 16:32
  • \$\begingroup\$ That is my goal to create copies of the same hardware. My problem is that shifting is not being replicated. \$\endgroup\$ – Nutwit May 19 '17 at 16:40
  • \$\begingroup\$ If you synthesized this code you could look at the synthesized version and see the actual wires and gates, this could help you debug it \$\endgroup\$ – Voltage Spike May 19 '17 at 16:53
  • 1
    \$\begingroup\$ Learn the difference in semantics between signal assignment and variable assignment. Start here stackoverflow.com/questions/13954193/… \$\endgroup\$ – Brian Drummond May 19 '17 at 20:12
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ So if I'm understanding correctly, only the last iteration of the for loop is looked at for performing the shifting. therefore, only 1 shift occurs. Is that accurate? If so, why is the combinational logic being replicated 32 times? Thanks for the suggestion. I will attempt to implement it. \$\endgroup\$ – Nutwit May 19 '17 at 15:48
  • \$\begingroup\$ The introduction of variables solved the issue. Thanks a lot for your assistance \$\endgroup\$ – Nutwit May 20 '17 at 8:35
  • 1
    \$\begingroup\$ I have accepted the answer, but cant upvote because of my reputation score. If my reputation ever climbs high enough, I'll be sure to upvote it. Thanks again. \$\endgroup\$ – Nutwit May 21 '17 at 12:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.