2014-01-03 2 views
0

Я пытаюсь изменить исходный код для выполнения суммы (например) и другой математической функции с помощью переключателя и шестнадцатеричного дисплея.VDDL несколько постоянных драйверов

Это основной код:

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

entity Switch7Segment is 
    port (
    SW  : in std_logic_vector(9 downto 0); 
    HEX0  : out std_logic_vector(6 downto 0); 
    HEX1  : out std_logic_vector(6 downto 0); 
    HEX2  : out std_logic_vector(6 downto 0); 
    HEX3  : out std_logic_vector(6 downto 0); 
    KEY  : in std_logic_vector(3 downto 0); 
    CLOCK_50 : in std_logic 
    ); 
end entity Switch7Segment; 

architecture behavior of Switch7Segment is 
    signal segments1 : std_logic_vector(13 downto 0); 
    signal segments2 : std_logic_vector(13 downto 0); 
    signal segmentsR : std_logic_vector(13 downto 0); -- Range changed from 27 downto 0 to allow compile 
    signal input1 : integer; 
    signal input2 : integer; 
    signal result : unsigned(31 downto 0); -- Range added to allow compile 
    signal temp  : integer; 
begin 

    input1 <= to_integer(unsigned(SW(4 downto 0))); 
    input2 <= to_integer(unsigned(SW(9 downto 5))); 

    segments1 <= unsigned_to_seven_segment(value => unsigned(SW(4 downto 0)), number_of_digits => 2, value_is_bcd => false); 
    segments2 <= unsigned_to_seven_segment(value => unsigned(SW(9 downto 5)), number_of_digits => 2, value_is_bcd => false); 

    HEX1 <= segments1(13 downto 7); 
    HEX0 <= segments1(6 downto 0); 
    HEX3 <= segments2(13 downto 7); 
    HEX2 <= segments2(6 downto 0); 

    process(CLOCK_50) 
    begin 
    if (CLOCK_50' EVENT and CLOCK_50 = '1' AND KEY(0) = '1') then 
     temp  <= input1+input2; 
     result <= to_unsigned(integer(temp), result'length); 
     segmentsR <= unsigned_to_seven_segment(value => unsigned(result), number_of_digits => 2, value_is_bcd => false); 
     HEX1  <= segmentsR(13 downto 7); 
     HEX0  <= segmentsR(6 downto 0); 
    end if; 
    end process; 

end architecture; 

И затем есть пакет:

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

package seven_segment_pkg is 
-- Return a std_logic_vector ready for driving a number of 7-segment displays. 
    function unsigned_to_seven_segment(value : unsigned; number_of_digits : integer; value_is_bcd : boolean) 
    return std_logic_vector; 
end; 

package body seven_segment_pkg is 

    function seven_seg_from_bcd_digit(bcd_digit : std_logic_vector(3 downto 0)) return std_logic_vector is 
    begin 
    case bcd_digit is 
     --     abcdefg 
     when x"0" => return "1000000"; 
     when x"1" => return "1111001"; 
     when x"2" => return "0100100"; 
     when x"3" => return "0110000"; 
     when x"4" => return "0011001"; 
     when x"5" => return "0010010"; 
     when x"6" => return "0000010"; 
     when x"7" => return "1111000"; 
     when x"8" => return "0000000"; 
     when x"9" => return "0010000"; 
     when x"a" => return "0001000"; 
     when x"b" => return "0000011"; 
     when x"c" => return "1000110"; 
     when x"d" => return "0100001"; 
     when x"e" => return "0000110"; 
     when x"f" => return "1110001"; 
     when others => return "0000000"; 
    end case; 
    end function; 

    -- Return a vector ready for driving a series of 7-segment displays. 
    function unsigned_to_seven_segment(
    value   : unsigned; 
    -- Number of 7-segment displays (determines output vector width: W = 7*N) 
    number_of_digits : integer; 
    -- When true, treat the input value as a BCD number where every 4 bits hold one 
    -- digit from 0 to A. When false, treat the input number as an unsigned integer. 
    value_is_bcd  : boolean 
    ) return std_logic_vector is 

    variable segments  : std_logic_vector(number_of_digits*7-1 downto 0); 
    variable bcd_quotient : unsigned(value'range); 
    variable bcd_remainder : unsigned(3 downto 0); 
    begin 

    if value_is_bcd then 
     for i in 0 to number_of_digits-1 loop 
     segments(i*7+6 downto i*7) := seven_seg_from_bcd_digit(
      std_logic_vector(value(i*4+3 downto i*4)) 
     ); 
     end loop; 
    else 
     bcd_quotient := value; 
     for i in 0 to number_of_digits-1 loop 
     bcd_remainder := resize(bcd_quotient mod 10, 4); 
     bcd_quotient := bcd_quotient/10; 
     segments(i*7+6 downto i*7) := seven_seg_from_bcd_digit(
      std_logic_vector(bcd_remainder) 
     ); 
     end loop; 

    end if; 

    return segments; 
    end function; 

end package body; 

Я думаю, что есть ошибка, что в данный момент я никогда не подписывал вот что длина результата. если мы скомпилируем этот код VHDL, Quartus скажет нам, что функция предназначена для 13 элементов, а не для 27. Но я не вижу препятствия для ее решения .... моя проблема связана с выводами (HEX0 ..... HEX3)

Если я изменить код и я вставить

signal segmentsR: std_logic_vector(13 downto 0); 

Я решить проблему длины, но я буду видеть ошибки 10028 (несколько постоянных водителей). Если я понял правильно, я не могу назначить два раза у одного и того же вектора два разных значения или что-то подобное верно? возможно, я всегда думаю, как программист на C++/C. Я думаю, что если я использую CLOCK, проблема будет решена, но это не так ...

ответ

2

Проблема в том, что есть драйверы для HEX0 и HEX1 как перед процессом, так и в процессе, но любой сигнал/порт должен быть из одного места в типичном синтезированном коде.

Если из процесса выведены HEX0 и HEX1, удалите драйверы перед процессом.

0

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

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

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

entity Switch7Segment is 
port (
    SW  : in std_logic_vector(9 downto 0); 
    HEX0  : out std_logic_vector(6 downto 0); 
    HEX1  : out std_logic_vector(6 downto 0) := (others => '0'); 
    HEX2  : out std_logic_vector(6 downto 0) := (others => '0'); 
    HEX3  : out std_logic_vector(6 downto 0); 
    KEY  : in std_logic_vector(3 downto 0); 
    CLOCK_50 : in std_logic 
); 
end entity Switch7Segment; 

Это обеспечивает значение по умолчанию для объекта. Независимо от того, что создает объект, он может иметь другое значение, чем значение по умолчанию. Подробнее читайте здесь: http://vhdl.renerta.com/mobile/source/vhd00051.htm

Похоже, что ваше значение по умолчанию более сложное (основанное на входах функции). В этом случае я либо (1) изменил бы свой интерфейс, чтобы вызывающий обеспечивал информацию, либо (2) записывал функцию и константу в пакет и использовал функцию/константу как значение по умолчанию.

Другим возможным решением является использование дженериков и значение по умолчанию. Это позволит вам использовать биты поля SW в ваших значениях по умолчанию.(т. е. что-то вроде HEX2: out std_logic_vector (6 downto 0): = (SW (xx downto yy), где SW определен в родовом порту)

+0

Проблема с несколькими драйверами ничем не отличается от мьютекса или гонки. не существует понятия _time_ с несколькими драйверами, поэтому нет условия гонки. Несколько драйверов означают, что две физические схемы пытаются одновременно изменять и изменять напряжение узла схемы. Это проблема с электроникой. Когда вы начинаете говорить о ** caller ** и ** значение по умолчанию для сущности ** ясно, что вы не понимаете разницы между языком программирования и языком описания аппаратного обеспечения. –

+0

Я использовал вызывающего абонента для обозначения того, где создается экземпляр объекта и настройка порты. Я должен был указать значение по умолчанию для порта вместо объекта по умолчанию, это была опечатка. В терминах нескольких драйверов, если вы отправляетесь в fr om программного фона, взаимное исключение в программном обеспечении может быть полезной аналогией для нескольких драйверов на аппаратном уровне. Совместное исключение в программном обеспечении защищает общие ресурсы от многопоточности/процесса. Предотвращение нескольких драйверов в регистре (например) предотвращает упоминание вами электрического фонаря. – heisenBug

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