Неопределенное значение счетчика в симуляции - PullRequest
0 голосов
/ 26 июня 2019

Я очень новичок в VHDL и, как часть университетского проекта, я пытаюсь создать машину состояний с четырьмя штатами. Я написал некоторый код VHDL и тестовый стенд, но я пока не мог подтвердить, работает ли машина состояний, но я проверю это после того, как решу текущую проблему:

Часть машины состояний - это счетчик без знака, который должен определять, следует ли извлекать данные в старший или младший байт. В моем тестовом стенде я просто хочу подтвердить, работает ли этот счетчик вообще. Прямо сейчас, после инициализации с 0, когда процесс подсчета начинается в первый раз, я получаю неопределенное значение в качестве значения счетчика.

Сначала я попытался реализовать счетчик как std_logic_vector, но я понял, почему это не может работать (без приведения). Поэтому я перешел на неподписанный и ожидал, что счетчик сработает. Комментируя отдельные процессы, я обнаружил, что в процессе подсчета возникают проблемы с процессами «изменение статуса» и «change_current_state». Но я просто не могу понять, почему эти процессы мешают друг другу. «change_current_state» никогда не достигает оператора «RESET» if - в моем тестовом стенде, поэтому он не может присвоить значение счетчику. Кроме того, процесс "change_status" никогда не достигает оператора elsif с состоянием "prepareData". Это единственный оператор, в котором значение присваивается счетчику.

Код VHDL:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity readFromADC is
    Port
        (
            CLK_IN  :   in  std_logic;
            RESET_IN_N  :   in std_logic;
            BUSY_IN :   in  std_logic;
            DATA_IN :   in  std_logic_vector(7 downto 0);
            ACK_ERROR_IN    :   in std_logic;

            ENABLE_I2C  :   out std_logic;
            ADDR_I2C    :   out std_logic_vector(6 downto 0);
            RW_I2C      :   out std_logic;
            DATA_WR_I2C :   out std_logic_vector(7 downto 0);

            DATA_OUT :  out std_logic_vector(15 downto 0);
            SHIFT_OUT_RDY   :   out std_logic;

            SHOWSTATE : out std_logic_vector (1 downto 0); -- debugging
            BYTECOUNTER: out unsigned (1 downto 0)
        );
end readFromADC;

architecture readFromADC_arch of readFromADC is

    constant const_data_wr    :   std_logic_vector(7 downto 0) := "00000000";
    constant const_rw_I2C :   std_logic := '1';
    constant const_addr_I2C :   std_logic_vector(6 downto 0) := "0101000";
    constant const_da2_control   :   std_logic_vector (3 downto 0) := "0000";

    type states is
        (
            idle,
            read,
            prepareData,
            shiftOut
        );
    signal sign_clk :   std_logic;

    signal sign_HighByte    :   std_logic_vector(7 downto 0);
    signal sign_LowByte    :   std_logic_vector(7 downto 0);

    signal current_state :   states;
    signal next_state :   states;

    signal sign_data_out :  std_logic_vector(15 downto 0);
    signal sign_ena_i2c : std_logic := '0'; 
    signal sign_count_bytes_uns : unsigned (1 downto 0) := "00"; 
    signal prepare_data_rdy :   std_logic := '0';
    signal sign_shift_out_rdy    :   std_logic := '0'; 
    signal debug_states         :   std_logic_vector (1 downto 0);

begin
    --Zuweisungen
    sign_clk <= CLK_IN;   

    ENABLE_I2C <= sign_ena_i2c;
    ADDR_I2C <= const_addr_I2C;
    RW_I2C <= const_rw_I2C;  
    DATA_WR_I2C <= const_data_wr;

    DATA_OUT <= sign_data_out;
    SHIFT_OUT_RDY   <= sign_shift_out_rdy;

    SHOWSTATE <= debug_states;
    BYTECOUNTER <= sign_count_bytes_uns;

    --nächsten Status zuweisen
    change_current_state : process (sign_clk, RESET_IN_N)
    begin
        if rising_edge(sign_clk) then
            if (RESET_IN_N = '0') then
                current_state <= idle;
                sign_shift_out_rdy <= '0';
                sign_data_out <= (others => '0');
                sign_count_bytes_uns <= "00";
            else
                current_state <= next_state;       
            end if;
        end if;
    end process change_current_state;

    --Status ändern
    change_status : process (current_state)
    begin
      if current_state = idle then
            debug_states <= "00";
            sign_shift_out_rdy <= '0';
            prepare_data_rdy <= '0';
            sign_ena_i2c <= '1';
        elsif current_state = read then
            debug_states <= "01";
--            sign_count_bytes <= sign_count_bytes + 1;
            sign_shift_out_rdy <= '0';
        elsif current_state = prepareData then
            debug_states <= "10";
            sign_ena_i2c <= '0';
--            sign_count_bytes <= "00";
        elsif current_state = shiftOut then
            sign_count_bytes_uns <= "00";
            debug_states <= "11";
            sign_shift_out_rdy <= '1';
        end if;
    end process change_status;

    acquireData : process (sign_count_bytes_uns, current_state)
    begin
        if current_state = read then
            if (sign_count_bytes_uns = 1) then
                sign_HighByte <= DATA_IN;
            elsif (sign_count_bytes_uns = 2) then
                sign_LowByte <= DATA_IN;
            end if;
        end if;
    end process acquireData;

    gatherData : process (current_state)
    begin
        if current_state = prepareData then
            sign_data_out <= const_da2_control & sign_HighByte(3 downto 0) &  sign_LowByte;
            prepare_data_rdy <= '1';
        end if;
    end process gatherData;

    --Dekodiere den nächsten Status
    next_state_decode: process (current_state, BUSY_IN, ACK_ERROR_IN, sign_count_bytes_uns, prepare_data_rdy, sign_shift_out_rdy)
    begin
        next_state <= current_state;  --Default: behalte den aktuellen Status
        case (current_state) is
            when Idle =>
                if (BUSY_IN = '0') AND (ACK_ERROR_IN = '0') then
                   next_state <= read;
                end if;
             when read =>
                if sign_count_bytes_uns >= 2 then
--                if sign_count_bytes = "11" then
                   next_state <= prepareData;
                end if;
             when prepareData =>
                if prepare_data_rdy = '1' then
                    next_state <= shiftOut;
                end if;
             when shiftOut =>
                if sign_shift_out_rdy = '1' then
                    next_state <= Idle;
                end if;
        end case;      
    end process next_state_decode;

    countBusy : process (BUSY_IN)
    begin
        if falling_edge(BUSY_IN) then
            sign_count_bytes_uns <= sign_count_bytes_uns + 1;
--            if (sign_count_bytes_uns <= 2) then
--                sign_count_bytes <= std_logic_vector (sign_count_bytes_uns);   
            if (sign_count_bytes_uns > 2) then
                sign_count_bytes_uns <= "00";
            end if;

        end if;

    end process countBusy;

Testbench



library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity sim_read_adc is
--  Port ( );
end sim_read_adc;

architecture sim_read_adc_arch of sim_read_adc is
    component readFromADC is
    Port
        (
            CLK_IN  :   in  std_logic;
            RESET_IN_N  :   in std_logic;
            BUSY_IN :   in  std_logic;
            DATA_IN :   in  std_logic_vector(7 downto 0);
            ACK_ERROR_IN    :   in std_logic;

            ENABLE_I2C  :   out std_logic;
            ADDR_I2C    :   out std_logic_vector(6 downto 0);
            RW_I2C      :   out std_logic;
            DATA_WR_I2C :   out std_logic_vector(7 downto 0);

            DATA_OUT :  out std_logic_vector(15 downto 0);
            SHIFT_OUT_RDY   :   out std_logic;

            SHOWSTATE : out std_logic_vector (1 downto 0);
            BYTECOUNTER: out unsigned (1 downto 0)
        );
    end component readFromADC;

    signal sim_CLK_IN  :     std_logic;
    signal sim_RESET_IN_N  :   std_logic := '1';
    signal sim_BUSY_IN :    std_logic := '1';
    signal sim_DATA_IN :    std_logic_vector(7 downto 0) := "10101010";
    signal sim_ACK_ERROR_IN    :   std_logic := '0';

    signal sim_ENABLE_I2C  :   std_logic;
    signal sim_ADDR_I2C    :   std_logic_vector(6 downto 0);
    signal sim_RW_I2C      :   std_logic;
    signal sim_DATA_WR_I2C :   std_logic_vector(7 downto 0);

    signal sim_DATA_OUT :  std_logic_vector(15 downto 0);
    signal sim_SHIFT_OUT_RDY   : std_logic;

    signal sim_SHOWSTATE : std_logic_vector (1 downto 0);
    signal sim_BYTECOUNTER : unsigned (1 downto 0);
begin
    dut : readFromADC

    port map
        (
            CLK_IN     => sim_CLK_IN, 
            RESET_IN_N => sim_RESET_IN_N,
            BUSY_IN => sim_BUSY_IN,
            DATA_IN => sim_DATA_IN,
            ACK_ERROR_IN => sim_ACK_ERROR_IN,

            ENABLE_I2C => sim_ENABLE_I2C,
            ADDR_I2C => sim_ADDR_I2C,
            RW_I2C => sim_RW_I2C, 
            DATA_WR_I2C => sim_DATA_WR_I2C,

            DATA_OUT => sim_DATA_OUT,
            SHIFT_OUT_RDY => sim_SHIFT_OUT_RDY,

            SHOWSTATE => sim_SHOWSTATE,
            BYTECOUNTER => sim_BYTECOUNTER
        );

    clk_gen : process
    begin
        sim_CLK_IN <= '0';
        wait for 0.5us;
        sim_CLK_IN <= '1';
        wait for 0.5us;
    end process clk_gen;

    generate_busy : process
    begin
        wait for 5us;
        sim_BUSY_IN <= '0';
        wait for 1us;
        sim_BUSY_IN <= '1';
    end process generate_busy;

end sim_read_adc_arch;

Моделирование (процесс не закомментирован): Моделирование (процесс не закомментирован)

* РЕДАКТИРОВАТЬ: обновленный код VHDL (испытательный стенд не нужно было менять):


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity readFromADC is
    Port
        (
            CLK_IN  :   in  std_logic;
            RESET_IN_N  :   in std_logic;
            BUSY_IN :   in  std_logic;
            DATA_IN :   in  std_logic_vector(7 downto 0);
            ACK_ERROR_IN    :   in std_logic;

            ENABLE_I2C  :   out std_logic;
            ADDR_I2C    :   out std_logic_vector(6 downto 0);
            RW_I2C      :   out std_logic;
            DATA_WR_I2C :   out std_logic_vector(7 downto 0);

            DATA_OUT :  out std_logic_vector(15 downto 0);
            SHIFT_OUT_RDY   :   out std_logic;

            SHOWSTATE : out std_logic_vector (1 downto 0); -- debugging
            BYTECOUNTER: out unsigned (1 downto 0)
        );
end readFromADC;

architecture readFromADC_arch of readFromADC is

    constant const_data_wr    :   std_logic_vector(7 downto 0) := "00000000";
    constant const_rw_I2C :   std_logic := '1';
    constant const_addr_I2C :   std_logic_vector(6 downto 0) := "0101000";
    constant const_da2_control   :   std_logic_vector (3 downto 0) := "0000";

    type states is
        (
            idle,
            read,
            prepareData,
            shiftOut
        );
    signal sign_clk :   std_logic;

    signal sign_HighByte    :   std_logic_vector(7 downto 0);
    signal sign_LowByte    :   std_logic_vector(7 downto 0);

    signal current_state :   states;
    signal next_state :   states;

    signal sign_data_out :  std_logic_vector(15 downto 0);
    signal sign_ena_i2c : std_logic := '0'; 
    signal sign_count_bytes_uns : unsigned (1 downto 0) := "00"; 
    signal prepare_data_rdy :   std_logic := '0';
    signal sign_shift_out_rdy    :   std_logic := '0'; 
    signal debug_states         :   std_logic_vector (1 downto 0);

begin
    --Zuweisungen
    sign_clk <= CLK_IN;   

    ENABLE_I2C <= sign_ena_i2c;
    ADDR_I2C <= const_addr_I2C;
    RW_I2C <= const_rw_I2C;  
    DATA_WR_I2C <= const_data_wr;

    DATA_OUT <= sign_data_out;
    SHIFT_OUT_RDY   <= sign_shift_out_rdy;

    SHOWSTATE <= debug_states;
    BYTECOUNTER <= sign_count_bytes_uns;

    --nächsten Status zuweisen
    change_current_state : process (sign_clk, RESET_IN_N)
    begin
        if rising_edge(sign_clk) then
--            if (RESET_IN_N = '0') then
--                current_state <= idle;
--                sign_shift_out_rdy <= '0';
--                sign_data_out <= (others => '0');
--                sign_count_bytes_uns <= "00";
--            else
            current_state <= next_state;       
--            end if;
        end if;
    end process change_current_state;

    --Status ändern
    change_status : process (current_state)
    begin
      if current_state = idle then
            debug_states <= "00";
            sign_shift_out_rdy <= '0';
            prepare_data_rdy <= '0';
            sign_ena_i2c <= '1';
        elsif current_state = read then
            debug_states <= "01";
            sign_shift_out_rdy <= '0';
        elsif current_state = prepareData then
            debug_states <= "10";
            sign_ena_i2c <= '0';
        elsif current_state = shiftOut then
            debug_states <= "11";
            sign_shift_out_rdy <= '1';
        end if;
    end process change_status;

    acquireData : process (sign_count_bytes_uns, current_state)
    begin
        if current_state = read then
            if (sign_count_bytes_uns = 1) then
                sign_HighByte <= DATA_IN;
            elsif (sign_count_bytes_uns = 2) then
                sign_LowByte <= DATA_IN;
            end if;
        end if;
    end process acquireData;

    gatherData : process (current_state)
    begin
        if current_state = prepareData then
            sign_data_out <= const_da2_control & sign_HighByte(3 downto 0) &  sign_LowByte;
            prepare_data_rdy <= '1';
        end if;
    end process gatherData;

    --Dekodiere den nächsten Status
    next_state_decode: process (current_state, BUSY_IN, ACK_ERROR_IN, sign_count_bytes_uns, prepare_data_rdy, sign_shift_out_rdy)
    begin
        next_state <= current_state;  --Default: behalte den aktuellen Status
        case (current_state) is
            when Idle =>
                if (BUSY_IN = '0') AND (ACK_ERROR_IN = '0') then
                   next_state <= read;
                end if;
             when read =>
                if sign_count_bytes_uns >= 2 then
--                if sign_count_bytes = "11" then
                   next_state <= prepareData;
                end if;
             when prepareData =>
                if prepare_data_rdy = '1' then
                    next_state <= shiftOut;
                end if;
             when shiftOut =>
                if sign_shift_out_rdy = '1' then
                    next_state <= Idle;
                end if;
        end case;      
    end process next_state_decode;

    countBusy : process (BUSY_IN, RESET_IN_N)
    begin
        if falling_edge (RESET_IN_N) then
            sign_count_bytes_uns <= "00";

        elsif falling_edge(BUSY_IN) then
            sign_count_bytes_uns <= sign_count_bytes_uns + 1;  
            if (sign_count_bytes_uns > 2) then
                sign_count_bytes_uns <= "00";
            end if;

        end if;

    end process countBusy;

end readFromADC_arch;

1 Ответ

0 голосов
/ 26 июня 2019

Во-первых, получение некоторого «Х» в симуляции обычно означает, что сигналу присваивается 2 (или более) значения одновременно.Это часто означает, что вы назначаете этот сигнал в нескольких параллельных процессах.

В VHDL лучше избегать назначения сигнала в 2 разных процесса (обратите внимание, что линия вне любого процесса является процессом).

В вашем коде на сигнал sign_count_bytes_uns влияет 3 процесса.Я думаю, вам следует изменить как минимум 2 из них (объединяя их).

Но настоящая причина вашего 'X' немного сложнее, в этом процессе:

    change_status : process (current_state)
    begin
      if current_state = idle then
            debug_states <= "00";
            sign_shift_out_rdy <= '0';
            prepare_data_rdy <= '0';
            sign_ena_i2c <= '1';
        elsif current_state = read then
            debug_states <= "01";
            sign_shift_out_rdy <= '0';
        elsif current_state = prepareData then
            debug_states <= "10";
            sign_ena_i2c <= '0';
        elsif current_state = shiftOut then
            sign_count_bytes_uns <= "00";
            debug_states <= "11";
            sign_shift_out_rdy <= '1';
        end if;
    end process change_status;

Вы присваиваете sign_count_bytes_uns только в 1 случае, и я предполагаю, что вы не в этом случае на скриншоте симуляции, который вы нам дали, но sign_count_bytes_uns по-прежнему равен "XX".

Причина заключается в следующем: когда вы назначаете сигнал в процессе, но не во всех случаях, каждый раз, когда вы не находитесь в случае, когда на сигнал воздействует, этот сигнал примет свое предыдущее значение (память),При синтезе защелка будет выведена.Таким образом, ваш процесс change_status поддерживает sign_count_bytes_uns в "00", когда countBusy пытается изменить его, поэтому вы получаете немного "XX".

...