Search code examples
vhdlfpgaquartus

Issue in Quartus Post synthesis -- output is obtaining as xxxxxxxx


I have written a vhdl code and I want to run it in FPGA, The code is working fine in ghdl and also in the Quartus 2 pre synthesis(RTL simulation) , but when i am running in gatelevel simulation, it is showing data_out as xxxxxxx .I cant able figure out what is the problem. Can anyone help me?

--- device code

   library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity SimpleCalculator is
port ( data_in :in std_logic_vector(3 downto 0);
data_valid : in std_logic;
data_out : out std_logic_vector(7 downto 0);
clk, reset: in std_logic);
end entity SimpleCalculator;


architecture behave of SimpleCalculator is
----------------------------------
-- defining main state consisting of states of main thread
----------------------------------
type main_state is (main_idle,main_read0,main_read1,main_read2,main_read3,main_read4,main_calc);
signal next_mainstate: main_state;


-- below code creates two dimensional
-- array of 8 inputs with 16 bits each

type inputs_bit is array(0 to 4) of std_logic_vector(3 downto 0);
signal input_array : inputs_bit;

signal calc_start : std_logic;
signal calc_done : std_logic;


------------------------------
-- defining signals and states for calc thread
------------------------------
type calc_state is (calc_idle,calc_check_inputs,calc_running,calc_error);
signal calcstate : calc_state;

-----------------------------
begin
main: process(clk,reset,data_valid,next_mainstate,calc_done)
variable nstate:main_state;
--variable count: integer:=0;
begin
nstate := next_mainstate;
case next_mainstate is

    when main_idle =>
    if(data_valid = '1' ) then
    nstate:= main_read0;
    else
    nstate:= main_idle;
    end if;

    when main_read0 =>
    input_array(0) <= data_in;
    nstate:=main_read1;

    when main_read1 =>
    input_array(1) <= data_in;
    nstate:=main_read2;

    when main_read2 =>
    input_array(2) <= data_in;
    nstate:=main_read3;

    when main_read3 =>
    input_array(3) <= data_in;
    nstate:=main_read4;

    when main_read4 =>
    input_array(4) <= data_in;
    nstate:=main_calc;
    calc_start <= '1';

    when main_calc =>
    calc_start <= '0';
    if(calc_done ='1') then
    nstate:= main_idle;
    else
    nstate:=main_calc;
    end if;

    when others => null;
    end case; 

if(clk'event and clk = '1') then
      if(reset = '1') then
        next_mainstate <= main_idle;
      else
        next_mainstate <= nstate;
      end if;
    end if;
  end process main;

------------------------------------------------
--calc fsm
---------------------------------------------
calc: process(clk,reset,calc_start,calcstate)
variable nstate:calc_state;
begin
nstate := calcstate;

case calcstate is 

    when calc_idle =>
    if(calc_start = '1') then
    nstate := calc_check_inputs;
    else
    nstate := calc_idle;
    end if;

    when calc_check_inputs =>
    if(input_array(0) = "1010" and input_array(1) < "1010" and input_array(2) > "1011"
    and input_array(3) < "1010" and input_array(4) = "1011") then
    nstate := calc_running;
    else
    nstate := calc_error;
    end if;

    -- check for correct sequence 

    when calc_error =>
    data_out <= "11111111";

    when calc_running =>
    case input_array(2) is
        when "1100" =>
        data_out <= std_logic_vector(unsigned(input_array(1)) * unsigned(input_array(3)) ) after 1 ns;
        when "1101" =>
        data_out <= "0000" & std_logic_vector(unsigned(input_array(1)) + unsigned(input_array(3)) ) after 1 ns;
        when "1110" =>
        data_out <= "0000" & std_logic_vector(unsigned(input_array(1)) - unsigned(input_array(3)) ) after 1 ns;
        when "1111" =>
        data_out <= "0000" & std_logic_vector(unsigned(input_array(1)) / unsigned(input_array(3)) ) after 1 ns;
        when others => null;
    end case;
    calc_done <='1';
    nstate := calc_idle;

    when others => null;
end case;

if(clk'event and clk = '1') then
      if(reset = '1') then
        calcstate <= calc_idle;
      else
        calcstate <= nstate;
      end if;
    end if;
  end process calc;
end behave;







--- **testbench**




 library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;

    library std;
    use std.textio.all;

    entity Simplecalculator_tb is
    end entity;

    architecture behave of Simplecalculator_tb is
    signal data_in : std_logic_vector(3 downto 0);
    signal data_valid : std_logic:= '0';
    signal data_out : std_logic_vector(7 downto 0);
    signal clk, reset: std_logic:= '0';

    file stimulus_file: text is in "calci_inputs.txt";
    file result_file: text is in "calci_result.txt";

        component SimpleCalculator is
        port ( data_in :in std_logic_vector(3 downto 0);
        data_valid : in std_logic;
        data_out : out std_logic_vector(7 downto 0);
        clk, reset: in std_logic);
        end component;

        begin

          -- 10 ns clock.
          clk <= not clk after 5 ns;

          process
            variable L: line;
            variable next_number_input: bit_vector(3 downto 0);
            variable next_number_output: bit_vector(7 downto 0);

          begin

            reset <= '1';
            data_valid <= '0';
            wait until clk ='1';
            reset <= '0';

            data_valid <= '1';
            wait until clk ='1';
            data_valid <= '0';

            while( not endfile(stimulus_file)) loop
              readline(stimulus_file,L);
              read(L,next_number_input);

              data_in <= To_StdLogicVector(next_number_input);
            wait until clk='1';
            assert false report "Sent item " severity note;

            end loop;

            assert false report "Sent all items " severity note;

            wait for 20 ns;
            assert false report "Received done " severity note;

                readline(result_file,L);
                read(L,next_number_output);
                if(data_out = To_StdLogicVector(next_number_output)) then
                  assert false report "SUCCESS: got the correct result." severity note;
                else
                  assert false report "FAILURE: incorrect result! " severity ERROR;
                end if;

                wait;
              end process;  

        dut : SimpleCalculator port map
            ( data_in => data_in, data_valid => data_valid, data_out => data_out, clk => clk,
            reset => reset);

        end behave;

---input file 1010 0111 1110 0010 1011

-- output file content 00000101


I have changed my code and the testbench and I have included the even the delays, but still I am getting the same xxxx error...Can anyone pls help me what is wrong in the code..what else I need to change.Thanks in advance

------ modified code

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity SimpleCalculator is
port ( data_in :in std_logic_vector(3 downto 0);
data_valid : in std_logic;
data_out : out std_logic_vector(7 downto 0);
clk, reset: in std_logic);
end entity SimpleCalculator;


architecture behave of SimpleCalculator is
----------------------------------
-- defining main state consisting of states of main thread
----------------------------------
type main_state is (main_idle,main_read0,main_read1,main_read2,main_read3,main_read4,main_calc);
signal next_mainstate: main_state;


-- below code creates two dimensional
-- array of 8 inputs with 16 bits each

type inputs_bit is array(0 to 4) of std_logic_vector(3 downto 0);
signal input_array : inputs_bit;

signal calc_start : std_logic;
signal calc_done : std_logic;


------------------------------
-- defining signals and states for calc thread
------------------------------
type calc_state is (calc_idle,calc_check_inputs,calc_running,calc_error);
signal calcstate : calc_state;

-----------------------------
begin
main: process(clk,reset,data_valid,next_mainstate,calc_done)
variable nstate:main_state;
--variable count: integer:=0;
begin
nstate := next_mainstate;
case next_mainstate is

    when main_idle =>
    if(data_valid = '1' ) then
    nstate:= main_read0;
    else
    nstate:= main_idle;
    end if;

    when main_read0 =>
    input_array(0) <= data_in after 2 ns;
    nstate:=main_read1;

    when main_read1 =>
    input_array(1) <= data_in after 2 ns;
    nstate:=main_read2; 

    when main_read2 =>
    input_array(2) <= data_in after 2 ns;
    nstate:=main_read3;

    when main_read3 =>
    input_array(3) <= data_in after 2 ns;
    nstate:=main_read4;

    when main_read4 =>
    input_array(4) <= data_in after 2 ns;
    nstate:=main_calc; 
    calc_start <= '1' after 2 ns;

    when main_calc =>
    calc_start <= '0' after 2 ns;
    if(calc_done ='1') then
    nstate:= main_idle;
    else
    nstate:=main_calc;
    end if;

    when others => null;
    end case; 

if(clk'event and clk = '1') then
      if(reset = '1') then
        next_mainstate <= main_idle;
      else
        next_mainstate <= nstate;
      end if;
    end if;
  end process main;

------------------------------------------------
--calc fsm
---------------------------------------------
calc: process(clk,reset,calc_start,calcstate)
variable nstate:calc_state;
begin
nstate := calcstate;

case calcstate is 

    when calc_idle =>
    if(calc_start = '1') then
    nstate := calc_check_inputs;
    else
    nstate := calc_idle;
    end if;

    when calc_check_inputs =>
    if(input_array(0) = "1010" and input_array(1) < "1010" and input_array(2) > "1011"
    and input_array(3) < "1010" and input_array(4) = "1011") then
    nstate := calc_running;
    else
    nstate := calc_error;
    end if;

    -- check for correct sequence 

    when calc_error =>
    data_out <= "11111111";

    when calc_running =>
    case input_array(2) is
        when "1100" =>
        data_out <= std_logic_vector(unsigned(input_array(1)) * unsigned(input_array(3)) ) after 1 ns;
        when "1101" =>
        data_out <= "0000" & std_logic_vector(unsigned(input_array(1)) + unsigned(input_array(3)) ) after 1 ns;
        when "1110" =>
        data_out <= "0000" & std_logic_vector(unsigned(input_array(1)) - unsigned(input_array(3)) ) after 1 ns;
        when "1111" =>
        data_out <= "0000" & std_logic_vector(unsigned(input_array(1)) / unsigned(input_array(3)) ) after 1 ns;
        when others => null;
    end case;
    calc_done <='1' after 2 ns;
    nstate := calc_idle;

    when others => null;
end case;

if(clk'event and clk = '1') then
      if(reset = '1') then
        calcstate <= calc_idle;
      else
        calcstate <= nstate;
      end if;
    end if;
  end process calc;
end behave;

-- new testbench

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library std;
use std.textio.all;

entity Simplecalculator_tb is
end entity;

architecture behave of Simplecalculator_tb is
signal data_in : std_logic_vector(3 downto 0):= (others => '0');
signal data_valid : std_logic:= '0';
signal data_out : std_logic_vector(7 downto 0);
signal clk, reset: std_logic:= '0';

file stimulus_file: text is in "/home/student/pavanpalla/lab_5/calci_inputs.txt";
file result_file: text is in "/home/student/pavanpalla/lab_5/calci_result.txt";

component SimpleCalculator is
port ( data_in :in std_logic_vector(3 downto 0);
data_valid : in std_logic;
data_out : out std_logic_vector(7 downto 0);
clk, reset: in std_logic);
end component;

begin

  -- 10 ns clock.
  clk <= not clk after 20 ns;

  process
    variable L: line;
    variable next_number_input: bit_vector(3 downto 0);
    variable next_number_output: bit_vector(7 downto 0);

  begin

    reset <= '1';
    data_valid <= '0';
    wait until clk ='1';
    reset <= '0' after 2 ns;

    data_valid <= '1' after 2 ns;
    wait until clk ='1';
    data_valid <= '0' after 2 ns;

    while( not endfile(stimulus_file)) loop
      readline(stimulus_file,L);
      read(L,next_number_input);

      data_in <= To_StdLogicVector(next_number_input) after 10 ns;
    wait until clk='1';
    assert false report "Sent item " severity note;

    end loop;

    assert false report "Sent all items " severity note;

    wait for 50 ns;
    assert false report "Received done " severity note;

        readline(result_file,L);
        read(L,next_number_output);
        if(data_out = To_StdLogicVector(next_number_output)) then
          assert false report "SUCCESS: got the correct result." severity note;
        else
          assert false report "FAILURE: incorrect result! " severity ERROR;
        end if;

        wait;
      end process;  

dut : SimpleCalculator port map
    ( data_in => data_in, data_valid => data_valid, data_out => data_out, clk => clk,
    reset => reset);

end behave;

I am also attaching the images of presynthesis and postsynthesis. I cant able to figure out where I am giving wrong

presynthesis presynthesis post_synthesis post_synthesis


Solution

  • Gate-level simulation includes timing for design primitives, for example flip-flops, so setup and hold time for data to flip-flops must be respected, and otherwise the flip-flops may generate 'X' on the output.

    The test bench code is not written with this in mind; for example:

    wait until clk ='1';
    reset <= '0';
    

    The reset is removed 0 ps after rising edge of clk, and depending on the implementation there may be hold-time requirement for the synchronous design reset.

    This can be addressed by running at a "slow" clock and only change data "far" from the rising clk edge. This is acceptable since design timing should be verified through Static Timing Analysis (STA) and not simulation; post-synthesis simulation is only to get a good feeling that the design is OK, but it is unrealistic to verify design timing through test cases.

    You may also consider writing the processes as either clocked process or combinatorial process, since this generally will make design easier to write, read, and debug. The calc process is an example of a process both updating on rising edge of clk and on calcstate.