# How to use present and previous value of a signal for this VHDL code?

We need present and previous value of the signal noisysignal1 to compute certain equations. One of the equations is y[i] = noisysignal1[i]*w1 + noisysignal1[i-1]*w2;. How can we use the present and previous value of the noisysignal1 at the same time in our VHDL code?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.math_real.all;
use IEEE.STD_LOGIC_Unsigned.ALL;

use IEEE.NUMERIC_STD.ALL;
entity random is
generic (
width : integer :=  32;
nn : natural := 1; -- power of the binomial distribution <16
m : REAL := 0.0    -- mean output value
);
port (
clk : in std_logic;
random_num : out std_logic_vector (width-1 downto 0);   --output vector
RST : in STD_LOGIC;
DATA_OUT : out REAL := 0.0
);
end random;

architecture Behavioral of random is
type arri is array (0 to 15) of integer;
type arrr is array (0 to 15) of real;
signal noisysignal1 : real;
begin
process(clk,rst)
variable rand_temp : std_logic_vector(width-1 downto 0) := (width-1 => '1',others => '0');
variable temp : std_logic := '0';

variable s1 : arri := (3,33,333,3,4,5,6,7,8,9,11,22,33,others=>55);
variable s2 : arri := (5,55,555,50,6,7,8,9,5,6,7,21,33,others=>22);
variable r : arrr := (others=>0.0);
variable s : real := 0.0;

variable noisysignal : real;
begin
if rst='1' then
DATA_OUT <= 0.0;
elsif rising_edge(clk) then
temp := rand_temp(width-1) xor rand_temp(width-2);
rand_temp(width-1 downto 1) := rand_temp(width-2 downto 0);
rand_temp(0) := temp;

s := 0.0;
for i in 0 to nn-1 loop    -- nn noise generators
UNIFORM (s1(i),s2(i),r(i));
s := s+r(i);
end loop;
DATA_OUT <= 2.0*(s/real(nn)-0.5) + m;
noisysignal := real(to_integer(signed(rand_temp))) + ( 2.0 * (s/real(nn)-0.5) + m);
noisysignal1 <= noisysignal;
end if;
random_num <= rand_temp;
end process;
end Behavioral;

• I assume this is a purely simulation-driven exercise? Commented Aug 27, 2016 at 1:33
• Yes sir, only for simulation. We tried to make the code synthesisable using ufixed instead of real variables, but it is showing complications. Commented Aug 31, 2016 at 10:07
• Consider editing your question text to note that your initial 'proof of algorithm' implementation is intended to be simulation-only. Leave the 'problem' code as it is, though, so future readers can see the original problem and the answers proposing solutions. Commented Aug 31, 2016 at 11:56

You have to register noisysignal1 once. Here is the resulting code. The register is noisysignal1_r. Then you can use y = noisysignal1*w1 + noisysignal1_r*w2.

I hope I understood what you want.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.math_real.all;
use IEEE.STD_LOGIC_Unsigned.ALL;

use IEEE.NUMERIC_STD.ALL;
entity random is
generic
(
width : integer :=  32;
nn : natural := 1; --power of the binomial distribution <16
m : REAL:=0.0     -- mean output value
);
port
(
clk : in std_logic;
random_num : out std_logic_vector (width-1 downto 0);   --output vector
RST : in STD_LOGIC;
DATA_OUT : out REAL := 0.0
);
end random;

architecture Behavioral of random is
type arri is array (0 to 15) of integer;
type arrr is array (0 to 15) of real;
signal noisysignal1, noisysignal1_r : real;
begin
process(clk,rst)
variable rand_temp : std_logic_vector(width-1 downto 0) := (width-1 => '1', others => '0');
variable temp : std_logic := '0';

variable s1 : arri := (3,33,333,3,4,5,6,7,8,9,11,22,33,others=>55);
variable s2 : arri := (5,55,555,50,6,7,8,9,5,6,7,21,33,others=>22);
variable r : arrr := (others=>0.0);
variable s : real := 0.0;

variable noisysignal : real;

begin
if rst='1' then
DATA_OUT <= 0.0;
elsif rising_edge(clk) then
noisysignal1_r <= noisysignal1;
temp := rand_temp(width-1) xor rand_temp(width-2);
rand_temp(width-1 downto 1) := rand_temp(width-2 downto 0);
rand_temp(0) := temp;

s := 0.0;
for i in 0 to nn-1 loop    -- nn noise generators
UNIFORM (s1(i),s2(i),r(i));
s := s+r(i);
end loop;
DATA_OUT <= 2.0*(s/real(nn) - 0.5) + m;
noisysignal :=real (to_integer(signed(rand_temp))) + ( 2.0*(s/real(nn) - 0.5) + m);
noisysignal1 <= noisysignal;
end if;
random_num <= rand_temp;
end process;
end Behavioral;


Could you not add a signal noisysignal1_old in addition to your signal noisysignal1, and then at the end of your for loop you assign noisysignal1 to noisysignal1_old ? This way, the loop would be able to compute the equation with both the present and the previous value of noisysignal.

Beyond simply creating a temporary variable, the simplest way would be to use the last_value attribute, which provides the last value assigned to that signal. Ex:

y[i] = noisysignal1[i]*w1 + noisysignal1[i]'last_value * w2;


You can read more here, though some synthesis tools may not recognize it. It does simulate and synthesize in Vivado 2014.2.

• Not explicitly storing the value in another signal to be a 'register' in simulation just makes the code less readable and more difficult for someone trying to read it who is expecting a typical RTL pattern. Commented Aug 31, 2016 at 11:52

You just need to register the signals.

A register will store data from one cycle to the other (triggered using an @ rising edge statement). Each register in a chain will push the data one cycle further back.

The output of one register in the current cycle will be the value input in the previous cycle.

If you need the data from two cycles back, you could put another register at the output of the first [register], pushing its output back one further cycle.

• @rising_edge is Verilog. Commented Aug 27, 2016 at 0:52
• I guess I meant, the is an equivalent version for whatever language he is using. rising_edge(clk) then :P Commented Aug 27, 2016 at 1:19