1

我正在编写一小段 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);或更有意义的东西。

4

3 回答 3

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;

  ...
于 2013-09-16T15:20:23.913 回答
1

聚合的信号分配目标一直是合法的,请参阅 IEEE Std 1076-1987 8.3 Signal Assignment Statement。它们是否在特定时间得到特定工具供应商的支持是一个单独的问题。

移位运算符自 -1993 年以来一直存在,并且是为位 (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 语句将事务排列到模拟时间。

来自测试用例的波形

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

您可以引入自己的 ror 和整数转换函数来消除类型转换。您自己的 ror 函数可以接受距离作为标准逻辑向量。

于 2013-09-17T01:13:12.257 回答
1

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

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

于 2013-09-16T15:15:34.627 回答