VHDL多个常量驱动程序错误,涉及'Z'和'L'



为了学习VHDL,我正在使用VHDL实现自己的自定义CPU。

我正在实现内存映射 IO,从用户代码的角度来看,它以相同的方式访问传统的 RAM 和各种 I/O 外围设备。

这是数据地址空间"根"的实现:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity data_memory_controller is
port (
clock: in std_logic;
addr: in std_logic_vector(31 downto 0);
rq: out std_logic_vector(31 downto 0);
wq: in std_logic_vector(31 downto 0);
re: in std_logic;
we: in std_logic;
ledr: out std_logic_vector(9 downto 0);
sw: in std_logic_vector(9 downto 0)
);
end;
architecture rtl of data_memory_controller is
component onchip_ram
generic (
addr_width: integer;
data_width: integer
);
port (
clock: in std_logic;
addr: in std_logic_vector(addr_width-1 downto 0);
rq: out std_logic_vector(data_width-1 downto 0);
wq: in std_logic_vector(data_width-1 downto 0);
re: in std_logic;
we: in std_logic
);
end component;
component ledr_controller
port (
clock: in std_logic;
rq: out std_logic_vector(31 downto 0);
wq: in std_logic_vector(31 downto 0);
re: in std_logic;
we: in std_logic;
ledr: out std_logic_vector(9 downto 0)
);
end component;
component sw_controller
port (
clock: in std_logic;
rq: out std_logic_vector(31 downto 0);
re: in std_logic;
sw: in std_logic_vector(9 downto 0)
);
end component;
signal c0, c1, c2: std_logic;
signal rq_tri: std_logic_vector(31 downto 0);
begin
c0 <= '1' when std_match(addr, "000000000000000000000000--------") else '0';
c1 <= '1' when std_match(addr, "10000000000000000000000000000000") else '0';
c2 <= '1' when std_match(addr, "10000000000000000000000000000001") else '0';
onchip_ram_c: onchip_ram generic map(
addr_width => 8,
data_width => 32
) port map (
clock => clock,
addr => addr(7 downto 0),
rq => rq_tri,
wq => wq,
re => re and c0,
we => we and c0
);
ledr_controller_c: ledr_controller port map(
clock => clock,
rq => rq_tri,
wq => wq,
re => re and c1,
we => we and c1,
ledr => ledr
);
sw_controller_c: sw_controller port map(
clock => clock,
rq => rq_tri,
re => re and c2,
sw => sw
);
rq <= rq_tri;          -- line 90
rq <= (others => 'L'); -- line 91
end;

这是 I/O 外设之一的实现:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity sw_controller is
port (
clock: in std_logic;
rq: out std_logic_vector(31 downto 0);
re: in std_logic;
sw: in std_logic_vector(9 downto 0)
);
end;
architecture rtl of sw_controller is
begin
process(clock)
begin
if rising_edge(clock) then
if std_match(re, '1') then
rq <= "0000000000000000000000" & sw;
else
rq <= (others => 'Z');
end if;
end if;
end process;
end;

每个外设都接受读使能信号。如果读使能变为高电平,则驱动线路rq;否则保留为高阻抗以允许其他外设可以驱动。

data_memory_controller的第90行和第91行的目的是高阻抗状态不会传播到该实体之外;对于实际硬件,这可以通过下拉电阻来实现。

据我所知,由于std_logic的分辨率规则,如果没有驱动输出的外设(=rq_tri是"Z"(data_memory_controllerrq变为"L";否则,rq复制rq_tri的内容。

但是,分析和合成步骤返回以下错误:

Error (10028): Can't resolve multiple constant drivers for net "rq[31]" at data_memory_controller.vhd(90) Error (10029): Constant driver at data_memory_controller.vhd(91) Error (10028): Can't resolve multiple constant drivers for net "rq[30]" at data_memory_controller.vhd(90) Error (10028): Can't resolve multiple constant drivers for net "rq[29]" at data_memory_controller.vhd(90) ...... [similar Error (10028) messages] ......

是的,我在同一条线上"驱动"多个信号,但我认为这种情况有明确的规则,应该接受这个程序。

如果我说的有什么错误,请纠正我。此外,我想找到替代方法

  1. 每个外设都可以驱动输出,或者"Z"取决于读取使能信号,并且
  2. 不要在data_memory_controller之外传播"Z">

我使用的是 Quartus Prime Lite 版 18.0,此实现将上传到英特尔 MAX 10 系列 FPGA 芯片上。

FPGA 仅支持引脚上的三态驱动器。虽然合成器工具可以将内部三态转换为复用器,但它并没有真正为阅读代码的其他人提供明确的设计意图。三态应仅在真正的输入输出端口上使用,并且仅在顶层使用,三态驱动程序最好也位于顶层(但如果您愿意,可以在层次结构中更深入地移动(

你得到多个司机,因为你正在开车

rq <= rq_tri;          -- line 90
rq <= (others => 'L'); -- line 91

这是从(其他"L"(值中获取rq_tri值和 0。"L"将在内部转换为"0",并针对任何eq_tri应该是什么。虽然这可能适用于仿真,但它不符合合成器中的预期设计模式。

如果你真的希望它起作用,你可以向英特尔提出增强请求,但我怀疑它会被忽略,因为它与事实上的编码风格不匹配,即对所有信号(输入或输出(都有明确的指示。

最新更新