# VHDL - big difference in schematics between integer with and without range

I just discovered something that I would like some expert to comment on.

CODE EXAMPLE A:

entity PipelinePoc is
Port ( clk : in STD_LOGIC;
led : out std_logic_vector(0 downto 0)
);
end PipelinePoc;

architecture Behavioral of PipelinePoc is

begin
process(clk) is
variable x : integer;
variable y : integer;
begin

if rising_edge(clk) then
if(x = 299)
then
x := 0;
if(y >= 500)
then
y := 0;
else
y := y + 1;
end if;
else
x := x + 1;
end if;
if((x+y) / 49 > 200)
then
led(0) <= '1';
else
led(0) <= '0';
end if;

end if;
end process;
end Behavioral;


CODE EXAMPLE B (Only difference is limited range on the integers):

    entity PipelinePoc is
Port ( clk : in STD_LOGIC;
led : out std_logic_vector(0 downto 0)
);
end PipelinePoc;

architecture Behavioral of PipelinePoc is

begin
process(clk) is
variable x : integer range 0 to 1280 := 0;
variable y : integer range 0 to 960 := 0;
begin

if rising_edge(clk) then
if(x = 299)
then
x := 0;
if(y >= 500)
then
y := 0;
else
y := y + 1;
end if;
else
x := x + 1;
end if;
if((x+y) / 49 > 200)
then
led(0) <= '1';
else
led(0) <= '0';
end if;

end if;
end process;
end Behavioral;


SCHEMATICS FOR EXAMPLE A:

SCHEMATICS FOR EXAMPLE B:

I would expect some difference between the example a with no range, assuming 32 bit may be representing the x and y values while the range 0 to 1280 can be represented with only 11 bit.

But the difference between the corresponding schematics is so huge, that either: - I may be missing some bug in my example be, allowing for the compiler to greatly simplify the logic - Or the FPGA has some small units that can do operations of a certain size (I am using a Basys3 board).

Can anyone explain why I end up with these very different schematics with only adding integer ranges?

Thanks

• The difference is not the integer range, but you setting the integer to 0 initially. Which renders your counting thingie completely non-functional, as schematics B might slightly indicate :D May 2 '20 at 10:26
• Well the compiler may realise that if((x+y) / 49 > 200) will never be true and just skip it all, yes. And maybe the compiler can only be certain of this based on the integer range. I will go make a new test with something that the compiler cannot leave out. Thanks :) May 2 '20 at 10:29
• ah by the way, I'm hopeful the synthesizer recognizes that (x+y)/49 > 200 can be simplifed to x+y > 9800, but you really better write it like that, in case you're missing some integer semantic corner case, where the synthesizer will actually have to implement a divisions. Division is the most complicated to implement basic arithmetic function, by far. If you can at almost any cost avoid it:don't divide to actual variables(not constants,these can be optimized). May 2 '20 at 10:32
• Thanks, Marcus. I updated the post. I just love this game of hunting down complexity. I am new to all this fpga. Thanks for your comment. If you post an answer (just like "The compiler optimized it all away in example b) then I can go accept it as the right answer. May 2 '20 at 10:39
• Hey, I think your edit to your question would actually be an answer to your question! Self-answering your questions is actually very appreciated here, so do just take the content of your edit, and cut&paste it to the answer field! That will allow you to mark the question answered, and us to upvote the answer :) May 2 '20 at 10:55

## 1 Answer

As Marcus Müller pointed out, the compiler can ignore all logic as if((x+y) / 49 > 200) will never render true with the limited integers. I have made a new test with some logic that the compiler has to respect:

Example A V2:

entity PipelinePoc is
Port ( clk : in STD_LOGIC;
led : out std_logic_vector(0 downto 0)
);
end PipelinePoc;

architecture Behavioral of PipelinePoc is

begin
process(clk) is
variable x : integer;
variable y : integer;
begin

if rising_edge(clk) then
-- STEP 0: Adjust pixel if overflow
if(x = 299)
then
x := 0;
if(y >= 500)
then
y := 0;
else
y := y + 1;
end if;
else
x := x + 1;
end if;
if((x+y) = 70)
then
led(0) <= '1';
else
led(0) <= '0';
end if;

end if;
end process;
end Behavioral;


Schematics for A v2:

Example B V2:

entity PipelinePoc is
Port ( clk : in STD_LOGIC;
led : out std_logic_vector(0 downto 0)
);
end PipelinePoc;

architecture Behavioral of PipelinePoc is

begin
process(clk) is
variable x : integer range 0 to 1280;
variable y : integer range 0 to 1280;
begin

if rising_edge(clk) then
-- STEP 0: Adjust pixel if overflow
if(x = 299)
then
x := 0;
if(y >= 500)
then
y := 0;
else
y := y + 1;
end if;
else
x := x + 1;
end if;
if((x+y) = 70)
then
led(0) <= '1';
else
led(0) <= '0';
end if;

end if;
end process;
end Behavioral;


Schematics for B v2:

CONCLUSION:

Compiler was clever enough to figure that the logic could be totally left out.

• Synthesis is good at that. That's part of why it's good to get things right in simulation first; THEN synthesise. May 2 '20 at 17:31