2013-09-17 3 views
1

У меня есть объект, который смотрит на пять пар переключателей и устанавливает буквы на дисплее 7-сегмента на основании состояния этих выключателей (H для 00, E для 01, L для 10 и, O для 11).Как я могу использовать два разных процесса для одного и того же объекта, обращающихся к тем же выходам в VHDL?

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

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

Я совершенно не знаком с VHDL, так что это может показаться простым, но как я могу отделить эти две функции? Нужно ли им быть в разных файлах? Как заставить их работать одновременно?

ответ

1

Если вы подаете сигнал от двух разных процессов, два драйвера будут «конкурировать».

Для типов bit и std_ulogic компилятор будет жаловаться на то, что вам не разрешено иметь два драйвера по сигналу. Если вы используете типы std_logic, тогда есть «функция разрешения», которая решает, какое результирующее значение имеет значение при вводе двух разных значений в сигнал. Например, если вы водите 0 и 1, вы получите неопределенный результат X.

Можно передавать Z (высокоимпеданс) на сигнал, чтобы дать возможность другому сигналу переопределить его, однако, если вы хотите его синтезировать, вам нужно проверить, что ваши инструменты будут делать с ним, так как очень мало фишек этих дни могут фактически иметь реальные высокоимпедансные режимы на их внутренних сигналах.

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

process1: process 
begin 
    sig1 <= '1'; -- not driving 
    -- some statemachine eventually does 
    sig1 <= '0'; 
    -- and then 
    sig1 <= '1'; -- when it's finished 
end process; 

process2: process 
begin 
    sig2 <= '1'; -- not driving 
     --- similarly... 
     sig2 <= '0'; -- at some point 
end process; 

actual_sig <= sig1 and sig2; 

Если это имеет смысл для ваших целей для 0 быть «простаивает» состоянием, а затем использовать «или» вместо того, чтобы объединять сигналы вместе ,

1

Что-то вроде этого (предупреждение, что оно не было отлажено, оно анализирует и разрабатывает).

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

Возможно, rot_select можно отделить от указателя записи.

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

entity rot_digits is 
    port (
    -- the 8 7-segment display with defaults for simulation visibility. 
     dp0: out std_logic_vector (6 downto 0) := "0000001"; -- 0 
     dp1: out std_logic_vector (6 downto 0) := "1001111"; -- 1 
     dp2: out std_logic_vector (6 downto 0) := "0010010"; -- 2 
     dp3: out std_logic_vector (6 downto 0) := "0000110"; -- 3 
     dp4: out std_logic_vector (6 downto 0) := "1001100"; -- 4 
     dp5: out std_logic_vector (6 downto 0) := "0100100"; -- 5 
     dp6: out std_logic_vector (6 downto 0) := "0100000"; -- 6 
     dp7: out std_logic_vector (6 downto 0) := "0001111"; -- 7 
    -- rotation select, also used for write pointer 
     rot_select: in std_logic_vector(2 downto 0); 
     wr_enab: in std_logic; 
     reset:  in std_logic; 
     switch:  in std_logic_vector(1 downto 0) 
    ); 
    type display8 is array (integer range 0 to 7) of 
      std_logic_vector(6 downto 0); 

    constant H:   std_logic_vector (6 downto 0) := "1001000"; -- H 
    constant E:   std_logic_vector (6 downto 0) := "0110000"; -- E 
    constant L:   std_logic_vector (6 downto 0) := "1110001"; -- L 
    constant O:   std_logic_vector (6 downto 0) := "0000001"; -- O (0) 
    constant ERR:  std_logic_vector (6 downto 0) := "0110110"; -- error 
    constant BLANK:  std_logic_vector (6 downto 0) := "1111111";  

end entity; 

architecture foo of rot_digits is 

    -- digit is (a,b,c,d,e,f,g) 6 downto 0, '0' for ON (sink) 
    -- a 
    -- f b 
    -- g 
    -- e c 
    -- d 

    -- (d0,d1,d2,d3,d4,d5,d6,d7) are register values for stored digits 
    signal d0:   std_logic_vector (6 downto 0); 
    signal d1:   std_logic_vector (6 downto 0); 
    signal d2:   std_logic_vector (6 downto 0); 
    signal d3:   std_logic_vector (6 downto 0); 
    signal d4:   std_logic_vector (6 downto 0); 
    signal d5:   std_logic_vector (6 downto 0); 
    signal d6:   std_logic_vector (6 downto 0); 
    signal d7:   std_logic_vector (6 downto 0); 

    function "ror" (l: display8; r: std_logic_vector(2 downto 0)) 
     return display8 is 
     variable rot: integer range 0 to 7; 
    begin 
     if IS_X(TO_X01(r)) then -- unknown defaults to 0 rotation 
      rot := 0; 
     else 
      rot := to_integer(unsigned(r)); 
     end if; 

     case rot is 
      when 0 => return l; 
      when 1 => return 
       display8'(l(0),l(7),l(6),l(5),L(4),l(3),l(2),l(1)); 
      when 2 => return 
       display8'(l(1),l(0),l(7),l(6),l(5),L(4),l(3),l(2));    
      when 3 => return 
       display8'(l(2),l(1),l(0),l(7),l(6),l(5),L(4),l(3)); 
      when 4 => return 
       display8'(l(3),l(2),l(1),l(0),l(7),l(6),l(5),L(4));  
      when 5 => return 
       display8'(l(4),l(3),l(2),l(1),l(0),l(7),l(6),l(5)); 
      when 6 => return 
       display8'(l(5),l(4),l(3),l(2),l(1),l(0),l(7),l(6)); 
      when 7 => return 
       display8'(l(6),l(5),l(4),l(3),l(2),l(1),l(0),l(7)); 
     end case; 
    end function; 

    signal selected: std_logic_vector (6 downto 0); 

begin 

SEL: 
    selected <= H when switch = "00" else 
       E when switch = "01" else 
       L when switch = "10" else 
       O when switch = "11" else 
       ERR; 

ROTATE: 
    (dp0,dp1,dp2,dp3,dp4,dp5,dp6,dp7) 
      <= display8'(d0,d1,d2,d3,d4,d5,d6,d7) ror rot_select; 

Display_Registers: 
    process (wr_enab,reset, switch) 
    begin 
     if (reset = '1') then 
      (d0,d1,d2,d3,d4,d5,d6,d7) <= display8'(others => BLANK); 
     elsif (wr_enab = '1') then 
      case rot_select is 
       when "000" => d0 <= selected; 
       when "001" => d1 <= selected; 
       when "010" => d2 <= selected; 
       when "011" => d3 <= selected; 
       when "100" => d4 <= selected; 
       when "101" => d5 <= selected; 
       when "110" => d6 <= selected; 
       when "111" => d7 <= selected; 
       when others => 
        (d0,d1,d2,d3,d4,d5,d6,d7) <= display8'(others => ERR); 
      end case; 


     end if; 
    end process; 

end architecture; 

В ERR задания должны показать есть Иным, чем «0» или «1» либо в rot_select или переключатель векторов. Должны быть три горизонтальные полосы.

По определению существует эквивалентный процесс для назначения параллельного сигнала выходным портам дисплея. Аналогичным образом вы можете выполнить этот поворот без нового объявленного оператора «ror» shift.

1

Я попытаюсь больше сосредоточиться на решении вашей проблемы, чем ответить на ваш первоначальный вопрос. За хороший ответ на ваш вопрос см. Пост Мартина (@ martin-thompson).

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

  • сигнал # 1 = < массив букв, без вращения, выбранного непосредственно образуют свои пары переключателей
  • сигнал # 2 = < массив повернутых букв; количество оборотов происходит от ваших переключателей вращения

Таким образом, у нас может быть один процесс, который генерирует сигнал №1, а другой taht генерирует сигнал # 2. Обычно лучше структурировать ваше решение, чтобы каждый сигнал был назначен из одного процесса.

ниже код должен решить проблему:

entity switches_to_7seg is 
    port (
     -- each switch pair selects one letter from 'H', 'E', 'L', 'O' 
     switch_pair_0: in bit_vector(1 downto 0); 
     switch_pair_1: in bit_vector(1 downto 0); 
     switch_pair_2: in bit_vector(1 downto 0); 
     switch_pair_3: in bit_vector(1 downto 0); 
     switch_pair_4: in bit_vector(1 downto 0); 
     -- the rotation switches select the amount of rotation from 0 to 4 
     rotate_switches: in bit_vector(2 downto 0); 
     -- the outputs are five 7-segment displays 
     lcd_display_0: out bit_vector(6 downto 0); 
     lcd_display_1: out bit_vector(6 downto 0); 
     lcd_display_2: out bit_vector(6 downto 0); 
     lcd_display_3: out bit_vector(6 downto 0); 
     lcd_display_4: out bit_vector(6 downto 0) 
    ); 
end; 

architecture dataflow of switches_to_7seg is 

    -- declare an enumerated type to make it easier working with the output letters 
    type output_letter_type is ('H', 'E', 'L', 'O'); 
    type output_letter_vector_type is array (natural range <>) of output_letter_type; 

    -- this comes directly from the switches 
    signal switch_selected_letters: output_letter_vector_type(0 to 4); 
    -- this is an intermediary signal, with the letters rotated 
    signal rotated_letters: output_letter_vector_type(0 to 4); 

    -- return a letter corresponding to the state of a pair of switches 
    function output_letter_from_bit_vector(bits: bit_vector) return output_letter_type is 
    begin 
     case bits is 
     when "00" => return 'H'; 
     when "01" => return 'E'; 
     when "10" => return 'L'; 
     when "11" => return 'O'; 
     end case; 
    end; 

    -- return a value for driving a 7-segment display to show the corresponding letter 
    function seven_seg_from_output_letter(letter: output_letter_type) return bit_vector is 
    begin 
     case letter is 
     when 'H' => return "0110111"; 
     when 'E' => return "1001111"; 
     when 'L' => return "0001110"; 
     when 'O' => return "1111110"; 
     end case; 
    end; 

begin 

    -- this first part reads the input switches and convert them to letters 
    switch_selected_letters(0) <= output_letter_from_bit_vector(switch_pair_0); 
    switch_selected_letters(1) <= output_letter_from_bit_vector(switch_pair_1); 
    switch_selected_letters(2) <= output_letter_from_bit_vector(switch_pair_2); 
    switch_selected_letters(3) <= output_letter_from_bit_vector(switch_pair_3); 
    switch_selected_letters(4) <= output_letter_from_bit_vector(switch_pair_4); 

    -- this first process generates the intermediary signal 'rotated_letters' 
    rotate_letters: process (all) begin 
     case rotate_switches is 
     when "000" => 
      rotated_letters <= switch_selected_letters; 
     when "001" => 
      rotated_letters <= switch_selected_letters(1 to 4) & switch_selected_letters(0); 
     when "010" => 
      rotated_letters <= switch_selected_letters(2 to 4) & switch_selected_letters(0 to 1); 
     when "011" => 
      rotated_letters <= switch_selected_letters(3 to 4) & switch_selected_letters(0 to 2); 
     when "100" => 
      rotated_letters <= switch_selected_letters(4) & switch_selected_letters(0 to 3); 
     when others => 
      rotated_letters <= switch_selected_letters; 
     end case; 
    end process; 

    -- this second process outputs the rotated letters to the displays 
    output_letters: process (all) begin 
     lcd_display_0 <= seven_seg_from_output_letter(rotated_letters(0)); 
     lcd_display_1 <= seven_seg_from_output_letter(rotated_letters(1)); 
     lcd_display_2 <= seven_seg_from_output_letter(rotated_letters(2)); 
     lcd_display_3 <= seven_seg_from_output_letter(rotated_letters(3)); 
     lcd_display_4 <= seven_seg_from_output_letter(rotated_letters(4)); 
    end process; 

end; 
Смежные вопросы