Фильтр VHDL не получает выходные данные для первых значений - PullRequest
0 голосов
/ 09 мая 2018

Я пытался внедрить пихтовый фильтр в VHDL, но в течение первых трех часов я не получаю вывод и ошибка at 0 ps, Instance /filter_tb/uut/ : Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)..

Исходный файл (у меня также есть 2 других файла для D-триггеров):

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;


entity filter is
    port ( x: in STD_LOGIC_VECTOR(3 downto 0);
            clk: in STD_LOGIC;
            y: out STD_LOGIC_VECTOR(9 downto 0));
end filter;


architecture struct of filter is


    type array1 is array (0 to 3) of STD_LOGIC_VECTOR(3 downto 0);
    signal coef : array1 :=( "0001", "0011", "0010", "0001");

    signal c0, c1, c2, c3: STD_LOGIC_VECTOR(7 downto 0):="00000000";    
    signal s0, s1, s2, s3: STD_LOGIC_VECTOR(3 downto 0) :="0000";
    signal sum: STD_LOGIC_VECTOR(9 downto 0):="0000000000";


    component DFF is
        Port ( d : in  STD_LOGIC_VECTOR(3 downto 0);
                clk : in  STD_LOGIC;
                q : out  STD_LOGIC_VECTOR(3 downto 0));
    end component;

    component lDFF is
        Port ( d : in  STD_LOGIC_VECTOR(9 downto 0);
                clk : in  STD_LOGIC;
                q : out  STD_LOGIC_VECTOR(9 downto 0));
    end component;

begin       

        s0<=x;
        c0<=x*coef(0);  
        DFF1: DFF port map(s0,clk,s1);
        c1<=s1*coef(1);     
        DFF2: DFF port map(s1,clk,s2);
        c2<=s2*coef(2);     
        DFF3: DFF port map(s2,clk,s3);
        c3<=s3*coef(3);
        sum<=("00" & c0+c1+c2+c3);
        lDFF1: lDFF port map(sum,clk,y);

end struct;

Testbench:

    LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use ieee.std_logic_unsigned.all;

ENTITY filter_tb IS
END filter_tb;

ARCHITECTURE behavior OF filter_tb IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT filter
    PORT(
         x : IN  STD_LOGIC_VECTOR(3 downto 0);
         clk : IN  std_logic;
         y : OUT STD_LOGIC_VECTOR(9 downto 0)
        );
    END COMPONENT;


   --Inputs
   signal x : STD_LOGIC_VECTOR(3 downto 0) := (others => '0');
   signal clk : std_logic := '0';

    --Outputs
   signal y : STD_LOGIC_VECTOR(9 downto 0);

   -- Clock period definitions
   constant clk_period : time := 10 ns;


BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: filter PORT MAP (
          x => x,
          clk => clk,
          y => y
        );

   -- Clock process definitions
   clk_process :process
   begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
   end process;


   -- Stimulus process
   stim_proc1: process
   begin        

      x<="0001";
        wait for 10ns;
        x<="0011";
        wait for 10ns;
        x<="0010";
        wait for 10ns;
        --x<="0011";


   end process;

END;

Выход: Output

Если кто-нибудь сможет помочь, я буду благодарен. Я думаю, что это как-то связано с начальными значениями сигналов c_i и s_i, но я не слишком уверен.

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Ваш FIR-фильтр содержит триггеры. Эти триггеры не имеют входа сброса и поэтому включаются в неизвестном состоянии. Вы моделируете это, инициализируя выходные данные триггеров "UUUU" (так как они имеют ширину четыре бита). Значение 'U' std_logic представляет собой неинициализированное значение.

Итак, ваш код ведет себя так, как и следовало ожидать. Если вас это не устраивает, вам нужно добавить вход сброса и подключить его к шлепанцам.

0 голосов
/ 09 мая 2018

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

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

Действительно правильным способом было бы иметь «действительный» сигнал, транспортируемый вдоль ваших данных. Вы предоставляете выходные данные только тогда, когда есть «действительный». Это стандартный метод обработки данных через любую аппаратную структуру конвейера.

Кстати: вы обычно не строите D-ffs самостоятельно. Синтезатор сделает это за вас. Вы просто используете синхронизированный процесс и обрабатываете векторы данных в нем.


У меня есть несколько вопросов. Если я добавлю контакт сброса, когда я переключу его с 1 на 0? Как я могу создать эту схему без явного использования D-FFS?

Вы делаете сигнал сброса так же, как вы делаете свои часы.

Что касается D-регистров: они выходят, если вы используете стандартный код VHDL регистра:

reg : process (clk,reset_n)
begin
   // a-synchronous active low reset
   if (reset_n='0') then 
      s0 <= "0000";
      s1 <= "0000";
      s2 <= "0000";
    elsif (rising_edge(clk)) then
      s0 <= x;
      s1 <= s0;
      s2 <= s1;
 ....

(Код введен как есть, не проверен на синтаксис или ошибки при наборе)

...