我想使用四个按钮作为输入,三个七段LED显示器作为输出。两个按钮应在16个RAM位置上下移动;另外两个应该递增和递减当前显示的内存位置的内容。一个七段显示应该显示当前地址(0-F),另外两个应该以十六进制(00-FF)显示该位置的内容。这是我尝试执行此操作的代码(我还没有实现显示):
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity raminfr is
port (
clk : in std_logic;
we : in std_logic;
do : out unsigned(7 downto 0)
);
end raminfr;
architecture rtl of raminfr is
type ram_type is array (0 to 15) of unsigned(7 downto 0);
signal RAM : ram_type;
signal read_a : unsigned(3 downto 0);
signal a : unsigned(3 downto 0);
signal di : unsigned(7 downto 0);
signal clock : std_logic;
signal key : std_logic_vector(3 downto 0);
begin
U1: entity work.lab1 port map (
clock =>clock,
key => key,
register_counter => a,
value_counter => di
);
process (clk)
begin
if rising_edge(clk) then
if we = '1' then
RAM(to_integer(a)) <= di;
end if;
read_a <= a;
end if;
end process;
do <= RAM(to_integer(read_a));
end rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity lab1 is
port(
clock : in std_logic;
key : in std_logic_vector(3 downto 0);
value_counter : buffer unsigned(7 downto 0) ;
register_counter : buffer unsigned(3 downto 0)
);
end lab1;
architecture up_and_down of lab1 is
signal value_in_ram : unsigned(7 downto 0);
signal clk : std_logic;
signal we : std_logic;
begin
U1: entity work.raminfr port map (
do=>value_in_ram,
clk=>clk,
we=>we
);
process(clock, value_counter, register_counter)
begin
if rising_edge(clock) then
if (key(3)='0' and key(2)='0' and key(1)='1' and key(0)='0') then
value_counter <= value_counter + "1";
elsif (key(3)='0' and key(2)='0' and key(1)='0' and key(0)='1') then
value_counter <= value_counter - "1";
elsif (key(3)='1' and key(2)='0' and key(1)='0' and key(0)='0') then
register_counter<= register_counter + "1";
value_counter <= value_in_ram;
elsif (key(3)='0' and key(2)='1' and key(1)='0' and key(0)='0') then
register_counter<= register_counter - "1";
value_counter <= value_in_ram;
end if;
end if;
end process;
end architecture up_and_down;
当我尝试编译时,我会反复重复以下错误:
Error (12051): Project too complex: hierarchy path is too long
Error (12052): Entity "lab1" is instantiated by entity "raminfr"
Error (12052): Entity "raminfr" is instantiated by entity "lab1"
这显然是因为我有端口映射另一个实体的每个实体,但我不知道任何其他方式来实现我想要完成的任务。有人可以提出替代方案吗?
答案 0 :(得分:2)
这是一个猜测因为它不太清楚你想做什么。似乎问题是设计问题:你很清楚最终结果应该做什么,但是不清楚如何将其分解为以最简单的方式实现目标的组件。
我基于这样的猜测:“raminfr”中的活动代码存储并加载数据,与其他已经悄悄进入的东西无关。
所以我建议将“raminfr”清理为只是一个内存组件而不用任何其他东西。然后它可以嵌入到处理键的“lab1”组件中,并存储和显示来自正确寄存器的值。它也可以在你需要记忆的任何地方重复使用。
让我们看一下raminfr。
entity raminfr is
port (
clk : in std_logic;
we : in std_logic;
do : out unsigned(7 downto 0)
);
end raminfr;
它有一个时钟,一个写使能输入和一个数据输出。但奇怪的是,没有地址或数据输入!现在,记忆是一种标准的“设计模式”,偏离它可能是不明智的,所以让我们添加它们......
entity raminfr is
port (
clk : in std_logic;
we : in std_logic;
addr : in unsigned(3 downto 0);
di : in unsigned(7 downto 0);
do : out unsigned(7 downto 0)
);
end raminfr;
内存模式的某些变体具有其他功能;读取使能,输出使能,分离读写时钟等,但这个简单的将在这里做。
您还可以使用泛型来自定义其大小,修改其数据和寻址总线宽度以匹配。这使它更有用,并节省了类似但不同模块的扩散......
让我们清理架构以匹配。
architecture rtl of raminfr is
type ram_type is array (0 to 15) of unsigned(7 downto 0);
signal RAM : ram_type;
signal read_a : unsigned(3 downto 0);
begin
process (clk)
...
end process;
do <= RAM(to_integer(read_a));
end rtl;
现在我们可以在“lab1”模块中实例化它,连接其新端口
U1: entity work.raminfr port map (
addr => register_counter, -- was "a", typo
di => value_counter,
do => value_in_ram,
clk => clk,
we => we
);
并对lab1的其余部分进行任何支持性更改。
这不是唯一合理的分解:您还可以将“lab1”设置为没有自己存储的简单组件,并将其他必要信号作为端口。那么你需要第三个“顶级”实体,其架构互连lab1和raminfr。