我有一个实体,它会查看五对开关,并根据这些开关的状态设置7段显示器上的字母(H
00
,E
{ {1}},01
为L
,10
为O
。
我在这个文件的体系结构中有一个进程,它有一个case语句,用于查看switch的值并将正确的字母写入相应的显示。
现在,我还有三个开关,根据它们的状态,将字母移动到相邻的7段显示器(如旋转)。我最初在同一架构中的另一个进程中有这个,但我得到编译错误,因为我在两个不同的地方使用输出(7段显示)。
我对VHDL完全陌生,所以这看起来很简单,但我如何分开这两个功能呢?他们需要在不同的文件中吗?如何让它们同时运行"?
答案 0 :(得分:1)
这样的事情(警告它没有经过调试,它会进行分析和阐述)。
这表明显示数字有寄存器,旋转功能在这些寄存器的输出和驱动显示数字端口之间运行。
当然,rot_select可以与写指针分开。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all; -- TO_INTEGER
entity rot_digits is
port (
-- the 8 7-segment display with defaults for simulation visibility.
dp0: out std_logic_vector (6 downto 0) := "0000001"; -- 0
dp1: out std_logic_vector (6 downto 0) := "1001111"; -- 1
dp2: out std_logic_vector (6 downto 0) := "0010010"; -- 2
dp3: out std_logic_vector (6 downto 0) := "0000110"; -- 3
dp4: out std_logic_vector (6 downto 0) := "1001100"; -- 4
dp5: out std_logic_vector (6 downto 0) := "0100100"; -- 5
dp6: out std_logic_vector (6 downto 0) := "0100000"; -- 6
dp7: out std_logic_vector (6 downto 0) := "0001111"; -- 7
-- rotation select, also used for write pointer
rot_select: in std_logic_vector(2 downto 0);
wr_enab: in std_logic;
reset: in std_logic;
switch: in std_logic_vector(1 downto 0)
);
type display8 is array (integer range 0 to 7) of
std_logic_vector(6 downto 0);
constant H: std_logic_vector (6 downto 0) := "1001000"; -- H
constant E: std_logic_vector (6 downto 0) := "0110000"; -- E
constant L: std_logic_vector (6 downto 0) := "1110001"; -- L
constant O: std_logic_vector (6 downto 0) := "0000001"; -- O (0)
constant ERR: std_logic_vector (6 downto 0) := "0110110"; -- error
constant BLANK: std_logic_vector (6 downto 0) := "1111111";
end entity;
architecture foo of rot_digits is
-- digit is (a,b,c,d,e,f,g) 6 downto 0, '0' for ON (sink)
-- a
-- f b
-- g
-- e c
-- d
-- (d0,d1,d2,d3,d4,d5,d6,d7) are register values for stored digits
signal d0: std_logic_vector (6 downto 0);
signal d1: std_logic_vector (6 downto 0);
signal d2: std_logic_vector (6 downto 0);
signal d3: std_logic_vector (6 downto 0);
signal d4: std_logic_vector (6 downto 0);
signal d5: std_logic_vector (6 downto 0);
signal d6: std_logic_vector (6 downto 0);
signal d7: std_logic_vector (6 downto 0);
function "ror" (l: display8; r: std_logic_vector(2 downto 0))
return display8 is
variable rot: integer range 0 to 7;
begin
if IS_X(TO_X01(r)) then -- unknown defaults to 0 rotation
rot := 0;
else
rot := to_integer(unsigned(r));
end if;
case rot is
when 0 => return l;
when 1 => return
display8'(l(0),l(7),l(6),l(5),L(4),l(3),l(2),l(1));
when 2 => return
display8'(l(1),l(0),l(7),l(6),l(5),L(4),l(3),l(2));
when 3 => return
display8'(l(2),l(1),l(0),l(7),l(6),l(5),L(4),l(3));
when 4 => return
display8'(l(3),l(2),l(1),l(0),l(7),l(6),l(5),L(4));
when 5 => return
display8'(l(4),l(3),l(2),l(1),l(0),l(7),l(6),l(5));
when 6 => return
display8'(l(5),l(4),l(3),l(2),l(1),l(0),l(7),l(6));
when 7 => return
display8'(l(6),l(5),l(4),l(3),l(2),l(1),l(0),l(7));
end case;
end function;
signal selected: std_logic_vector (6 downto 0);
begin
SEL:
selected <= H when switch = "00" else
E when switch = "01" else
L when switch = "10" else
O when switch = "11" else
ERR;
ROTATE:
(dp0,dp1,dp2,dp3,dp4,dp5,dp6,dp7)
<= display8'(d0,d1,d2,d3,d4,d5,d6,d7) ror rot_select;
Display_Registers:
process (wr_enab,reset, switch)
begin
if (reset = '1') then
(d0,d1,d2,d3,d4,d5,d6,d7) <= display8'(others => BLANK);
elsif (wr_enab = '1') then
case rot_select is
when "000" => d0 <= selected;
when "001" => d1 <= selected;
when "010" => d2 <= selected;
when "011" => d3 <= selected;
when "100" => d4 <= selected;
when "101" => d5 <= selected;
when "110" => d6 <= selected;
when "111" => d7 <= selected;
when others =>
(d0,d1,d2,d3,d4,d5,d6,d7) <= display8'(others => ERR);
end case;
end if;
end process;
end architecture;
ERR分配是在rot_select或switch向量中显示除“0”或“1”以外的值。应该是三个横条。
根据定义,对显示数字输出端口的并发信号分配有一个等效的过程。你也可以让这个过程在没有新声明的“ror”移位操作符的情况下执行旋转。
答案 1 :(得分:1)
如果您从两个不同的进程中发出信号,两个驱动程序将“竞争”。
对于bit
和std_ulogic
类型,编译器会抱怨您不允许在信号上有两个驱动程序。如果您使用std_logic
类型,则会有一个“分辨率函数”,用于决定在将两个不同的值驱动到信号上时结果值是什么。例如,如果您驾驶0
和1
,则会获得已定义的未知结果X
。
可以将Z
(高阻抗)驱动到信号上以允许其他信号覆盖它,但是,如果你想要合成它,你需要检查你的工具将用它做什么现在很少有芯片实际上可以在内部信号上实现真正的高阻抗模式。
实现目标的便携,整洁,可合成的方法是将逻辑1
视为强度低于逻辑 - 0
。然后,您可以将两个单独的信号与AND门组合:
process1: process
begin
sig1 <= '1'; -- not driving
-- some statemachine eventually does
sig1 <= '0';
-- and then
sig1 <= '1'; -- when it's finished
end process;
process2: process
begin
sig2 <= '1'; -- not driving
--- similarly...
sig2 <= '0'; -- at some point
end process;
actual_sig <= sig1 and sig2;
如果0
成为'空闲'状态对你的目的更有意义,那么使用'或'代替将信号合并在一起。
答案 2 :(得分:1)
我会更专注于解决你的问题,而不是回答你原来的问题。要想回答你的问题,请参阅Martin的(@ martin-thompson)帖子。
所提出的解决方案的关键是生成中间信号,该信号将保持“旋转”字母。简而言之:
这样,我们可以有一个生成信号#1的过程,另一个生成信号#2。通常最好构建解决方案,以便在单个流程中分配每个信号。
以下代码可以解决您的问题:
entity switches_to_7seg is
port (
-- each switch pair selects one letter from 'H', 'E', 'L', 'O'
switch_pair_0: in bit_vector(1 downto 0);
switch_pair_1: in bit_vector(1 downto 0);
switch_pair_2: in bit_vector(1 downto 0);
switch_pair_3: in bit_vector(1 downto 0);
switch_pair_4: in bit_vector(1 downto 0);
-- the rotation switches select the amount of rotation from 0 to 4
rotate_switches: in bit_vector(2 downto 0);
-- the outputs are five 7-segment displays
lcd_display_0: out bit_vector(6 downto 0);
lcd_display_1: out bit_vector(6 downto 0);
lcd_display_2: out bit_vector(6 downto 0);
lcd_display_3: out bit_vector(6 downto 0);
lcd_display_4: out bit_vector(6 downto 0)
);
end;
architecture dataflow of switches_to_7seg is
-- declare an enumerated type to make it easier working with the output letters
type output_letter_type is ('H', 'E', 'L', 'O');
type output_letter_vector_type is array (natural range <>) of output_letter_type;
-- this comes directly from the switches
signal switch_selected_letters: output_letter_vector_type(0 to 4);
-- this is an intermediary signal, with the letters rotated
signal rotated_letters: output_letter_vector_type(0 to 4);
-- return a letter corresponding to the state of a pair of switches
function output_letter_from_bit_vector(bits: bit_vector) return output_letter_type is
begin
case bits is
when "00" => return 'H';
when "01" => return 'E';
when "10" => return 'L';
when "11" => return 'O';
end case;
end;
-- return a value for driving a 7-segment display to show the corresponding letter
function seven_seg_from_output_letter(letter: output_letter_type) return bit_vector is
begin
case letter is
when 'H' => return "0110111";
when 'E' => return "1001111";
when 'L' => return "0001110";
when 'O' => return "1111110";
end case;
end;
begin
-- this first part reads the input switches and convert them to letters
switch_selected_letters(0) <= output_letter_from_bit_vector(switch_pair_0);
switch_selected_letters(1) <= output_letter_from_bit_vector(switch_pair_1);
switch_selected_letters(2) <= output_letter_from_bit_vector(switch_pair_2);
switch_selected_letters(3) <= output_letter_from_bit_vector(switch_pair_3);
switch_selected_letters(4) <= output_letter_from_bit_vector(switch_pair_4);
-- this first process generates the intermediary signal 'rotated_letters'
rotate_letters: process (all) begin
case rotate_switches is
when "000" =>
rotated_letters <= switch_selected_letters;
when "001" =>
rotated_letters <= switch_selected_letters(1 to 4) & switch_selected_letters(0);
when "010" =>
rotated_letters <= switch_selected_letters(2 to 4) & switch_selected_letters(0 to 1);
when "011" =>
rotated_letters <= switch_selected_letters(3 to 4) & switch_selected_letters(0 to 2);
when "100" =>
rotated_letters <= switch_selected_letters(4) & switch_selected_letters(0 to 3);
when others =>
rotated_letters <= switch_selected_letters;
end case;
end process;
-- this second process outputs the rotated letters to the displays
output_letters: process (all) begin
lcd_display_0 <= seven_seg_from_output_letter( rotated_letters(0) );
lcd_display_1 <= seven_seg_from_output_letter( rotated_letters(1) );
lcd_display_2 <= seven_seg_from_output_letter( rotated_letters(2) );
lcd_display_3 <= seven_seg_from_output_letter( rotated_letters(3) );
lcd_display_4 <= seven_seg_from_output_letter( rotated_letters(4) );
end process;
end;