我正在编写一小部分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);
或任何更有意义的东西。
答案 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语句将事务排列为模拟时间。
最后的rot_select分配和随后的旋转表明,通过完成下一个模数8的换档位置换档,(d0,d1,d2,d3,d4,d5,d6,d7)的值没有被改变。
您可以引入自己的ror和整数转换函数来消除类型转换。你自己的ror函数可以接受distance_logic_vector。