Search code examples
vhdlfpgaxilinxmodelsim

VHDL Implementing exclusive or data as a function


I'm trying to pack simple code into a function. Here is the VHDL code:

process(CLK, RST)
    variable newdata : std_logic_vector(7 downto 0)  := (others => '0');
    variable tempdata : std_logic_vector(7 downto 0) := (others => '0');
begin

    if (RST = '1') then
       tempdata := (others => '0');
       newdata  := (others => '0');
    elsif rising_edge(CLK) then
        tempdata := DIN;    
        newdata  := newdata XOR tempdata;
    end if;
    DOUT <= newdata;
end process;

Code simulation

RTL model

Everything works fine as i wanted to. But if a trying implement this code as a function it will fail

function f_MOD2ALG (foo : std_logic_vector) 
return std_logic_vector;
...
function f_MOD2ALG (foo : std_logic_vector) 
return std_logic_vector is
    variable tempdata : std_logic_vector(foo'range);
    variable newdata  : std_logic_vector(foo'range);
begin
    tempdata := foo;
    newdata := newdata xor tempdata;
    return newdata;
end function;

Fail simulation

Fail RTL model

No errors, no warnings.

On the RTL model look's like he is nulle'd data input, but i dont understand why. Can someon explain to me why it's happen? And how to properly create a function that's implement my code? Thank's!

Here is the calling of the function:

...
signal temp     : std_logic_vector(7 downto 0) := (others => '0');

begin

process(CLK, RST)
begin
    if (RST = '1') then
        temp <= (others => '0');
    elsif rising_edge(CLK) then
        temp <= f_MOD2ALG(DIN);
    end if;
end process;
DOUT <= temp;
...

Solution

  • As already written in my comment, the issue with your code is that the variable newdata inside your function will always be "UUUUUUUU" because it never gets initialized and it does not preserve its value between two function calls. And XORing something with U will always give U.

    If you initialize newdata to all zeros, the output will corresond to the input because XORing foo with 0 will give foo.

    I know Easics' CRC generator. In their function, they pass the previous CRC value as argument. You could do something similar:

    function f_MOD2ALG (foo : std_logic_vector; last_bar: std_logic_vector) 
    return std_logic_vector is
        variable new_bar  : std_logic_vector(foo'range);
    begin
        new_bar := foo xor last_bar;
        return new_bar;
    end function;
    

    And calling it somehow like that:

    signal bar : std_logic_vector(31 downto 0) := (others=>'0');
    ...
    process(clk)
    begin
       if rising_edge(clk) then
          bar <= f_MOD2ALG(foo, bar);
       end if;
    end process;