Search code examples
vhdlxilinxmodelsimxilinx-ise

Integer output turns to binary in synthesize ISE


I have a VHDL BCD counter whose output is an integer value (digit).

But when I simulate the code in Xilinx ISE it shows the code's waveform in binary value. The code works but the output should be integer but it's not. I have tested this code in Modelsim and the output is correct and it's in integer value. This problem is in code synthesize too and the value is binary.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity bcdcnt is
    Port ( clk : in  STD_LOGIC;
           digit : out  INTEGER RANGE 0 TO 9);
end bcdcnt;

architecture Behavioral of bcdcnt is

begin   
count: PROCESS(clk)
    VARIABLE temp : INTEGER RANGE 0 TO 10;
    BEGIN 
        IF (clk'EVENT AND clk = '1') THEN 
            temp := temp + 1;
            IF (temp = 10) THEN temp := 0;
            END IF;
        END IF;
        digit <= temp;
    END PROCESS count;
end Behavioral;

Solution

  • That's what synthesis does.

    That's what synthesis MUST do : it translates your high level design to the resources in your FPGA or ASIC, which are binary. So, what's the problem here?

    If you need to simulate the post-synth result, the usual approach is to create a wrapper entity that takes the correct port types, and translates between those and the post-synthesis netlist component.

    Then, simulation should work with either the original entity, or this wrapper entity, both of which have integer ports.

    Better still, you can re-use the same entity, and add the wrapper as a second architecture, thus guaranteeing that it uses the same interface (ports).

    (You can even instantiate both the original and post-synth in its wrapper in the testbench, in parallel with a comparator on their outputs, to see they both do the same thing. But note there will be gate-level delays between them; usually you check outputs only on clock edges so these do not matter.)


    Another approach is to restrict port types on the top level of the design to binary types like std_logic_vector. This plays nicer with badly designed tools, like ISE where the automatically generated testbench will have binary port types, (I generally edit them back to the correct ones; it's almost easier to write TBs from scratch).

    But it restricts you to using an obscure and complex design style instead of higher level abstractions like Integers.

    It's bad - really bad - that this approach is taught and encouraged so widely. But it is, and sometimes you'll just have to live with it. (Even in this approach, there's no reason to avoid decent abstractions internal to the FPGA, as long as the synthesis tool understands them).


    A third approach - roughly, "trust, but verify" - is to trust that synthesis tools are competently written - which is usually true - and forget about post-synthesis simulation.

    Just verify the design thoroughly at the behavioural level in simulation, then synthesise it, and test in live FPGA.

    99% of the time (unless you're writing really weird VHDL), synth and P&R have done the right thing, and any differences you see are due to the aforementioned I/O timings (gate delays at the I/O pins). Then model these in the testbench and/or wrapper until you see the same behaviour in both (fix anything that needs fixing, and re-synthesise).

    In this approach you only need to bother with the (MUCH slower) post-synth and post-PAR simulations if you need to track down a suspected synthesis tool bug.

    This does happen : I've seen two in a quarter century.

    Most of the time I just use the third approach.