如何在VHDL中为多个端口分配多个值

时间:2013-09-16 14:39:46

标签: variable-assignment vhdl

我正在编写一小部分VHDL来旋转八个7段显示器上的值。

我有这样的事情:

-- handle the rotation of displays
process(rot_select, d0, d1, d2, d3, d4, d5, d6, d7)
begin
    case rot_select is
        when "000" => -- rotate by 0
        when "001" => -- rotate by 1
        when "010" => -- rotate by 2
        when "011" => -- rotate by 3
        when "100" => -- rotate by 4
        when "101" => -- rotate by 5
        when "110" => -- rotate by 6
        when "111" => -- rotate by 7
    end case;
end process;

其中rot_select是用于计算旋转大小的选择器(第一个显示移动到第二个显示等),d0-d7表示作为每个显示输入的7位向量。

我想知道如果不是每次都像d1 <= d0; d2 <= d1; ...那样进行手动分配,我可以更自动地使用更少的代码吗?可能类似于(d0,d1,d2,d3,d4,d5,d6,d7) <= (d7,d0,d1,d2,d3,d4,d5,d6);或任何更有意义的东西。

3 个答案:

答案 0 :(得分:3)

汇总赋值在VHDL-2008中更强大,因此如果您使用的是VHDL-2008,则可以写:

(d0,d1,d2,d3,d4,d5,d6,d7) <= d7 & d0 & d1 & d2 & d3 & d4 & d5 & d6;

假设d0等声明为std_logic_vector或类似。

请注意,如果您使用的是VHDL-2008,您还可以将敏感度列表写为(all),而不是明确列出所有信号。

但正如Josh所写,表示为数组更合适,并且也适用于以前版本的VHDL。代码看起来像:

  ...

  -- 7-segment display
  subtype ssd_t is std_logic_vector(1 to 7);  -- Type for display
  type ssd_arr_t is array(natural range <>) of ssd_t;  -- Type for array of display
  signal d_cur : ssd_arr_t(0 to 7);  -- Current value
  signal d_nxt : ssd_arr_t(0 to 7);  -- Next value
  -- Rotation
  signal rot_select : std_logic_vector(2 downto 0);

begin

  -- Handle the rotation of displays
  process (rot_select, d_cur)
    variable idx_cur_v : unsigned(2 downto 0);
  begin
    for idx in d_nxt'range loop
      idx_cur_v := to_unsigned(idx, 3) - unsigned(rot_select);  -- Handles modulo  operation
      d_nxt(idx) <= d_cur(to_integer(idx_cur_v));
    end loop;
  end process;

  ...

答案 1 :(得分:1)

如果将显示d0-d7定义为7位向量而不是单个信号的数组,则此问题会更容易。然后你会得到一个信号display,其中display(0)对应于d0现在的信息。

一旦你有一个数值数组,那么你可以使用类似for...loop的东西来描述值从一个显示位置移动到另一个显示位置。

答案 2 :(得分:1)

作为聚合的信号分配目标一直是合法的,参见IEEE Std 1076-1987 8.3信号分配声明。他们是否在特定时间得到特定工具供应商的支持是一个单独的问题。

移位运算符自-1993以来就存在,并且是为bit(bit_vector)类型的一维数组(复合)预定义的。

ror是在包numeric_std中为有符号和无符号复合类型定义的,与to_integer一样。

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

entity rot_display is
end entity;

architecture foo of rot_display is
    signal d0:          std_logic := '1';
    signal d1:          std_logic := '1';
    signal d2:          std_logic := '0';
    signal d3:          std_logic := '0';
    signal d4:          std_logic := '0';
    signal d5:          std_logic := '1';  
    signal d6:          std_logic := '0';
    signal d7:          std_logic := '1';

    signal rot_select:  std_logic_vector(2 downto 0) := "000"; 
    type rot is array (integer range 0 to 7) of std_logic_vector(2 downto 0);
    constant rotation:  rot :=
            ("111", "110", "101", "100", "011", "010", "001", "000");

begin
TEST:
    process    
    begin
        wait for 10 ns;

        for i in rot'range loop
            rot_select <= rotation(i);  
            wait for 1 ns;          
            (d0,d1,d2,d3,d4,d5,d6,d7) <=             
                std_logic_vector ( 
                    unsigned'(d0,d1,d2,d3,d4,d5,d6,d7) 
                                   ror 
                    to_integer( unsigned(rot_select))           
                );
            wait for 9 ns; 
        end loop;

    -- put (d0,d1,d2,d3,d4,d5,d6,d7) back to original position by completing
    -- modulo 8 shift  (total of 32 shifts)

        rot_select <= "100";
        wait for 1 ns;
        (d0,d1,d2,d3,d4,d5,d6,d7) <=             
            std_logic_vector ( 
                unsigned'(d0,d1,d2,d3,d4,d5,d6,d7) 
                               ror 
                to_integer( unsigned(rot_select)) 
        );  
        wait for 9 ns;    

        wait;   -- stops simulation
    end process;
end architecture;

使用to_integer可以向您展示此测试用例要避免的元值问题。

等待1 ns语句可确保您看到新rot_select值的结果而不是之前的确认模拟周期,首先更新rot_select。等待9 ns语句将事务排列为模拟时间。

Waveform from test case

最后的rot_select分配和随后的旋转表明,通过完成下一个模数8的换档位置换档,(d0,d1,d2,d3,d4,d5,d6,d7)的值没有被改变。

您可以引入自己的ror和整数转换函数来消除类型转换。你自己的ror函数可以接受distance_logic_vector。