1
votes

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.

1
Your code is syntactically correct but does not describe real hardware, so it is not synthesizeable. Try to use B=0 as synchronous set signal for the err register.Juergen
Forgive me if I'm very noob to this at first but what does "synthesizeable" means? Is Synthesis different from the Simulation? Thanks for the answer :Dc2s1
There's no way this code could have 'worked' in ISE (and your 'instructor' shouldn't be setting you exercises like this, for lots of reasons - what sort of course is this??) Consider this - your process triggers only when clk changes. Your logic then does this: if there was a rising edge, carry out the pretend division and set err to 0; otherwise (ie. if there was a falling edge) and if B was 0 on that falling edge, set err to 1. Not what you want.EML
@c2s1 "synthesizable" means that the circuit behavior you describe can be mapped to the available hardware structures on your target FPGA. In your code, you describe some kind of weird behavior for the err signal, which cannot be mapped to real hardware structures. There are a lot of language constructs in VHDL which can only be used in simulation but not in synthesis. Back in those days when VHDL was invented, no one was even thinking about using it to do synthesis :-)Juergen
@Juergen now I understand what synthesis means. Well, thank you for the information. Looks like I'm gonna focus more on simulation than synthesis since in our class with basic vhdl coding, only simulation can be done to VHDL coding but Verilog HDL coding will be used for hardware implementation of our FPGA board.c2s1

1 Answers

1
votes

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.