1
\$\begingroup\$

After a year's hiatus, I returned to learning VHDL. I'm working on the exercises on Peter Ashenden's book Beginner's Guide to VHDL and I'm stuck on exercise 11 of chapter 3.

The goal is to write a module, that will perform basic arithmetic operations on two real numbers. Here is my module:

-- floating point ALUish thing

entity FPALU is
    port ( x, y : in real;
           f1, f0 : in bit;
           z : out real );
end entity FPALU;

architecture behav of FPALU is
begin
    fpalu_behavioral : process(x, y, f1, f0) --is
        variable result : real := 0.0;
    begin
        if f1 = '0' and f0 = '0' then
            result := x + y;
        elsif f1 = '0' and f0 = '1' then
            result := x - y;
        elsif f1 = '1' and f0 = '0' then
            result := x * y;
        elsif f1 = '1' and f0 = '1' then
            result := x / y;
        -- else null;
        end if;
        z <= result;
    end process fpalu_behavioral;
end architecture behav;

And its test bench:

-- test bench for floating point operations

entity FPALU_test_bench is
end entity FPALU_test_bench;

architecture test_FPALU of FPALU_test_bench is

    signal x, y, z : real;
    signal f0, f1 : bit;

begin
    dut : entity work.FPALU(behav)
        port map ( x, y, f1, f0, z );

    stimulus : process is
    begin
        x <= 3.4; y <= 5.8; f1 <= '0'; f0 <= '0'; wait for 20 ns;
        x <= 3.4; y <= 5.8; f1 <= '0'; f0 <= '1'; wait for 20 ns;
        x <= 3.4; y <= 5.8; f1 <= '1'; f0 <= '0'; wait for 20 ns;
        x <= 3.4; y <= 5.8; f1 <= '1'; f0 <= '1'; wait for 20 ns;
        wait;
    end process stimulus;

end architecture test_FPALU;

This code will analyze and elaborate fine, but once I try to run the test bench I get this error:

ghdl -r FPALU_test_bench --vcd=FPALU.vcd
./fpalu_test_bench:error: bound check failure at FPALU.vhdl:15
./fpalu_test_bench:error: simulation failed

Line 15 being result := x + y;. This question seems to be similar, but since packages haven't been introduced yet in the book, I assume it should be possible to do without. Also, I added two real numbers in a similar fashion in another module and it worked fine. So, why won't this simulation run? I guess it's an "overflow issue" from what I have found here and on Google, but no definite answer.

\$\endgroup\$
4
  • \$\begingroup\$ i am not very familiar with VHDL, but i read your question. ... the question that you refer to has an answer with this line The syntax for resize in fixed_pkg appears to differ from that used in numeric_std for signed and unsigned numbers. ... it implies that numeric_std has a resize command (or statement?) also \$\endgroup\$ – jsotola Jan 31 '18 at 3:13
  • 1
    \$\begingroup\$ The implicit initial value for an object of type real without an explicit initial value is real'left (-1.79769313486232E+308 for later ghdl versions). Add two of those together and you have a negative number with a value not between the left and right range bounds (inclusively). Explicitly initialize x and y: signal x, y: real := 0.0; signal z: real; Your testbench then simulates. Your adding before the first assignment takes effect using the implicit initial values. \$\endgroup\$ – user8352 Jan 31 '18 at 5:05
  • \$\begingroup\$ @user8352 avoid writing answers in comments \$\endgroup\$ – scary_jeff Feb 1 '18 at 13:34
  • \$\begingroup\$ Here's an example of the same problem for multiplication of reals with no explicit initial value. Simualtion (sic) stops at time 0 after a real to real multiplication!. Addition and multiplication both can have a result for operands of the value real'left that is out of the value range of type real. Division yields 1.0 while subtraction yields 0.0. You could provide initial values for f0 and f1 or reorder the operations and duplicate the linked question problem. \$\endgroup\$ – user8352 Feb 1 '18 at 16:04
1
\$\begingroup\$

I'm sorry for my late reply, I got caught up in other stuff yet again. I managed to update my code the way @user8352 suggested to get it to run, so here are the working versions:

entity floatALU is
    port ( x, y : in real;
           f1, f0 : in bit;
           z : out real );
end entity floatALU;

-- behavrioal body
architecture behav of floatALU is
begin
    calculate : process ( x, y, f1, f0 ) is
    begin
        -- I combine if and case statements on purpose here
        if f1 = '0' then
            case f0 is
                when '0' => z <= x + y;
                when '1' => z <= x - y;
            end case;
        else
            case f0 is
                when '0' => z <= x * y;
                when '1' => z <= x / y;
            end case;
        end if;
    end process calculate;
end architecture behav;

And the test bench:

entity floatALU is
    port ( x, y : in real;
           f1, f0 : in bit;
           z : out real );
end entity floatALU;

-- behavrioal body
architecture behav of floatALU is
begin
    calculate : process ( x, y, f1, f0 ) is
    begin
        -- I combine if and case statements on purpose here
        if f1 = '0' then
            case f0 is
                when '0' => z <= x + y;
                when '1' => z <= x - y;
            end case;
        else
            case f0 is
                when '0' => z <= x * y;
                when '1' => z <= x / y;
            end case;
        end if;
    end process calculate;
end architecture behav;

Thank you all for your help!

\$\endgroup\$
0

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.