VHDL, concurrent signal assignment wrong on FPGA but right in Modelsim

201 views Asked by At

I am modifying a multiplier and I am having trouble running it on an FPGA. In Modelsim, the simulation are all correct. I have the following which gives the wrong result on FPGA: Outside of the process statement, I have the following concurrent statement

(I have omitted the signal declarations)

architecture behavioral of multiplier is
 ...
 ...
begin
       a_argument <=       a1_neg when booth = "110"
                     else  a2_plus when booth = "011"; 

The value of a1_neg and a2_plus are precomputed in a process statement when entering a multiplication state:

when MULT_SIGNED_MULT =>
               a1_plus(33 downto 0) <= a(31) & a(31) & a;
               a1_neg(33 downto 0) <= not a(31) &  not a(31) &bv_negate(a);
               a2_plus(33 downto 0) <=   a(31) & a & "0";
               a2_neg(33 downto 0)<= not a(31) &bv_negate(a) & "0";

And then it enters a stage where multiplier computes new values of booth which influence the a_argument signal

On the other hand, when I don't precompute the values and directly enter everything into the concurrent statement as follows:

a_argument <=      not a(31) &  not a(31) &bv_negate(a)   when booth = "110" 
              else not a(31) &bv_negate(a) & "0"          when booth = "011";

The FPGA will produce a correct result. Also, Modelsim will give the correct result regardless of the difference betewen these two.

I was wondering why one option gives the correct result on FPGA and the other doesn't.

1

There are 1 answers

0
Samuel On

I think your concurrent statement is wrong :

a_argument <=       a1_neg when booth = "110"
                     else  a2_plus when booth = "011";

You should have another else statement when booth is different from "110" and "011". An example of a good concurrent statement :

a_argument <= a1_neg when booth = "110"
              else a2_plus when booth = "011"
              else (others => '0');

But the default value (others => '0') is maybe not what you want. Maybe you really want a latch, so you should place the assignment of a_argument into a clocked process where the latch of a_argument is done when booth is different from "110" and "011" :

process(clk)
begin
  if rising_edge(clk) then
    if (booth = "110") then
      a_argument <= a1_neg;
    elsif (booth = "011") then
      a_argument <= a2_plus;
    end if;
end