【发布时间】:2018-09-01 00:31:27
【问题描述】:
为了学习 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 的分辨率规则,如果没有驱动输出的外围设备,data_memory_controller 的rq 变为'L'(= rq_tri 是'Z');否则,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] ......
是的,我在同一条线路上“驱动”多个信号,但我认为对于这种情况有明确定义的规则,应该接受这个程序。
如果我说的有问题,请纠正我。此外,我想找到替代方法
- 每个外设都可以驱动输出或“Z”取决于读使能信号,并且
- 不要在
data_memory_controller之外传播“Z”
我使用的是 Quartus Prime Lite Edition 18.0 版,这个实现将上传到 Intel MAX 10 系列 FPGA 芯片上。
【问题讨论】:
-
IEEE Std 1076-2008 16.8.2.4.2 强制和弱值的解释('0'、'1'、'L'、'H'、FALSE、TRUE)。 ..综合工具应将以下值解释为表示逻辑值 0: ... — STD_ULOGIC 值“0”和“L”。您可能比通读 16.8.2.4 逻辑值的完整解释更糟糕。您的办法是遵循英特尔关于何时何地可以使用多个高阻抗驱动网络的指导方针。
-
您确定您的目标 FPGA 支持内部三态缓冲器吗?
-
@RenaudPacalet :: 当我尝试删除第 91 行时,我没有收到错误,但
Warning (13046): Tri-state node(s) do not directly drive top-level pin(s)和Warning (13048): Converted tri-state node "data_memory_controller:data_memory_controller_c|rq[31]" into a selector。 (警告 13048 重复 32 次)。我的理解是该工具会将“Z”信号转换为等效元素。 -
虽然删除第 91 行编译成功(带有一些警告),但这会在 data_memory_controller 外部泄漏“Z”信号,我想阻止它。
-
@Venusaur:“警告 (13046):三态节点不直接驱动顶层引脚”看起来您的目标 FPGA 具有三-state 仅在主 IO 引脚中缓冲...