Неопределенный выходной сигнал тестового сигнала кольцевого счетчика

#counter #vhdl #flip-flop

#счетчик #vhdl #триггер

Вопрос:

Я смоделировал 4-разрядный кольцевой счетчик с использованием D-триггера.

Общий триггер находится в отдельном файле, включенном в мою рабочую область. Триггер D работает правильно (выдает правильную форму выходного сигнала).

Это код кольцевого счетчика:

 library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity ring4counter is
    port (
        clk: std_logic;
        output: out std_logic_vector(3 downto 0));
end ring4counter;

architecture ring4counter_arch of ring4counter is
    component dff
    port (
        clk: std_logic;
        d: in std_logic;
        q: out std_logic;
        qbar: out std_logic);
    end component;

    signal temp:std_logic_vector(3 downto 0):=(others=>'0');
begin
    r1: dff port map(clk, temp(3), temp(0));
    r2: dff port map(clk, temp(0), temp(1));
    r3: dff port map(clk, temp(1), temp(2));
    r4: dff port map(clk, temp(2), temp(3));
    output <= temp;
end ring4counter_arch;
  

Вот тестовый код для кольцевого счетчика:

 library ieee;
use ieee.std_logic_1164.all;

entity ring4_tb is end ring4_tb ;

architecture arch of ring4_tb is
    component tbc is
    port (
        clk: std_logic;
        output: out std_logic_vector(3 downto 0));
    end component ;

    component dff
    port (
        clk: std_logic;
        d: in std_logic;
        q: out std_logic;
        qbar: out std_logic);
    end component;

    constant period : time := 50 ns ;

    signal clk      : std_logic := '0' ;    
    signal done     : boolean := false ;
    signal output   : std_logic_vector(3 downto 0) ;

    shared variable cycle : natural := 0 ;

    signal temp:std_logic_vector(3 downto 0):=(others=>'0');

begin
-- this is the unit under test
    u1: tbc
    port map(
        clk    => clk,
        output => output) ;

    clkprocess: process(done, clk)
    begin
    if (not done) then
        if (clk = '1') then
        cycle := cycle   1 ;
        end if ;
        clk <= not clk after period / 2 ;
    end if ;
    end process ;

    r1: dff port map(clk, temp(3), temp(0));
    r2: dff port map(clk, temp(0), temp(1));
    r3: dff port map(clk, temp(1), temp(2));
    r4: dff port map(clk, temp(2), temp(3));
    output <= temp;

    testbench: process
    begin
    wait until (clk = '0') ;
    temp <= "1000";
    wait for period*4 ;

    done <= true ;      -- force the clock process to shutdown
    wait ;          -- this waits forever
    end process ;
end arch ;
  

Но форма сигнала для «вывода» — это «U» для всех битов.
Где я ошибаюсь?

Комментарии:

1. Я знаю, что это более старый пост, но я хотел бы сделать стилистический комментарий — если вы когда-нибудь сделаете назначение должности по позиции в реальном мире, вас выследят и побьют. Никогда не делайте этого. r1: dff port map(clk=>clk, d=>temp(3), q=>temp(0)); допустимо использовать одну строку для простого компонента (но вас также высмеяли бы за то, что вам нужен компонент DFF).

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

Ответ №1:

В процессе testbench, когда вы пытаетесь инициализировать temp на «1000», триггеры по-прежнему также передают сигнал temp, так что у вас фактически продолжается борьба с шиной.

Комментарии:

1. Да, у вас не может быть нескольких вещей, управляющих шиной (в целом)

2. могу ли я как-нибудь это исправить? Я не очень хорошо знаю VHDL. Я даже опустил строку temp <= «1000», по-прежнему без изменений.

3. Вам нужно изменить способ инициализации общих триггеров. Одним из способов было бы разделить входы D и Q и явно загрузить значение инициализации при сбросе. Я не могу поместить форматированный код в комментарии, но r1: карта портов dff (clk, temp_in (3), temp (0)); temp_in <= «1000» при сбросе = ‘1’ else temp; должен направить вас в правильном направлении.

Ответ №2:

temp Для настройки сигнала используйте инициализацию в вашем кольцевом счетчике.

Обратите внимание, что это может неправильно синтезироваться в зависимости от вашей архитектуры и инструмента синтеза.

Наиболее общий способ сделать это — добавить сигнал сброса ко всем DFF, кроме on, и наложить на него предустановленный сигнал. Затем вы утверждаете сброс в начале, который установит DFF на хорошее значение.

Вот более простая версия вашего кода, которая делает это и позволяет избежать необходимости использования явных DFF. Вы также можете изменить ширину temp , и код сделает все остальное за вас:

 process (clk)
begin
   if reset = '1' then
      temp <= (0=>'1', others => '0'); -- set one bit high, the others low.
   elsif rising_edge(clk) then
      -- take the high bit and move it to the low bit. 
      -- Move the other bits left 1 place
      temp <= temp(temp'high-1 downto 0) amp; temp(temp'high);
   end if;
end process;
  

(Примечание: код, только что введенный в сообщение, может содержать синтаксические опечатки!)


Кстати, shared variable s — плохая идея, если они не имеют protected типов. У них могут быть условия гонки.

Ответ №3:

Одна вещь, которую нужно сделать, это добавить разрешающий сигнал к D триггерам. если вы хотите сбросить схему, сделайте сигнал включения низким, а затем измените температуру на «1000».

 r1: dff port map(clk, temp(3), temp(0), enable);

process(clk,reset)
begin
if(rising_edge(clk)) then
 if( reset='1') then
  enable='0';
  temp <= "1000";
 else
  enable <= '1';
 end if;
end if;
end process;
  

Комментарии:

1. Я не думаю, что это сработает — DFF все еще передают сигнал даже при сбросе.

2. @Martin : Хорошо. спасибо за примечание. Но что, если я определю триггер D таким образом, чтобы Q <=D назначался только при высоком уровне сигнала включения. В противном случае назначение не выполнено. Будет ли это работать в этом случае?

3. Это не происходит, когда происходит назначение. Тот факт, что процесс имеет назначение где-то в нем, создает «драйвер», и драйверы затем конфликтуют. В VHDL нет таких вещей, как неактивный драйвер. При std_logic этом у вас может быть драйвер Z, который затем разрешает так, как вы могли ожидать, но это все еще драйвер.