VHDL多个常量驱动程序

时间:2014-01-03 16:21:23

标签: vhdl

我正在尝试使用开关和十六进制显示来修改源代码(例如)和其他数学函数。

这是主要代码:

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 个答案:

答案 0 :(得分:2)

问题是在进程和进程之前都有HEX0HEX1的驱动程序,但任何信号/端口只能在典型的合成代码中从一个地方驱动。

如果HEX0HEX1是从流程驱动的,那么请在流程之前删除驱动程序。

答案 1 :(得分: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)在包中写一个函数和一个常量,并使用函数/ constant作为默认值。

另一种可能的解决方案是使用泛型默认值。这将允许您在默认值中使用SW字段的位。 (即:类似HEX2:out std_logic_vector(6 downto 0):=(SW(xx downto yy),其中SW在泛型端口中定义)