I'm very new to VHDL and I would like to get some help. You see, we were told by our instructor to code the division of binary (by converting the binary to integer first) and if the divisor is zero, then the output error waveform will be displayed in the simulation. Here is my code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity division_in is
Port ( A : in STD_LOGIC_VECTOR (7 downto 0);
B : in STD_LOGIC_VECTOR (7 downto 0);
clk : in STD_LOGIC;
Y : out STD_LOGIC_VECTOR (7 downto 0);
err : out STD_LOGIC);
end division_in;
architecture Behavioral of division_in is
begin
process(clk)
begin
if clk='1' and clk'event then -- error here
Y <= conv_std_logic_vector(conv_integer(A)/conv_integer(B),8);
err <= '0';
elsif B = 0 then
err <= '1';
end if;
end process;
end Behavioral;
When I try to use the "check syntax" in the Xilinx ISE 9.1i (which was used by the university), there are no syntax errors that displayed on the transcript. I could even use the testbench waveform to simulate it with no problems. However, when I import this code to Quartus II, I got 5 errors in the message especially in this one:
Error (10818): Can't infer register for "err" at division_in.vhd(45) because it does not hold its value outside the clock edge
I don't know what I've done wrong in copying the exact code from the Xilinx to Quartus but a little help is much appreciated on why I got this error on Quartus II but not on Xilinx ISE 9.1i. Since Xilinx ISE is already not compatible to my laptop anymore, I just use Quartus II instead since it also has a simulation feature which is a "Vector Waveform File" simulation.
OK, first thing's first, do not use IEEE.STD_LOGIC_ARITH.ALL;
or use IEEE.STD_LOGIC_UNSIGNED.ALL
. You should use ieee.numeric_std.all
, which gives you arithmetic using types signed
and unsigned
, along with casts and conversion functions for std_logic_vector
and integer
.
Now let's look at your code:
if clk='1' and clk'event then -- error here
Y <= conv_std_logic_vector(conv_integer(A)/conv_integer(B),8);
err <= '0';
elsif B = 0 then
err <= '1';
end if;
Looking at the err
signal only, what this says is that on a rising clock edge, set err
to '0'
, otherwise if B
= 0
, set err
to '1'
. You mentioned that this works in simulation, but for synthesis you need to think about what this means in real hardware. How do you imagine the case where there isn't a clock edge being detected? The answer is that it cannot.
It's not clear exactly what you're trying to achieve, but two alternatives that would work, having made the package changes above, are:
if rising_edge(clk) then -- Use rising_edge() function
Y <= std_logic_vector(signed(A)/signed(B));
err <= '0'; -- Synchronous clear of `err`
end if;
if signed(B) = 0 then -- Asynchronous set of `err`
err <= '1';
end if;
or
if rising_edge(clk) then
Y <= std_logic_vector(signed(A)/signed(B));
if signed(B) = 0 then
err <= '1'; -- Synchronous control of `err`
else
err <= '0';
end if;
end if;
The code would need less type casts if you gave the ports the types that they actually are, i.e. signed
. The core of your process would then look like this:
if rising_edge(clk) then
Y <= A / B;
if B = 0 then
err <= '1'; -- Synchronous control of `err`
else
err <= '0';
end if;
end if;
I hope you can see how much easier this is to read.