要学习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
的{{1}}变为'L'(= {data_memory_controller
是“ Z”);否则,rq_tri
复制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'我使用的是Quartus Prime Lite Edition 18.0版,该实现将上传到Intel MAX 10系列FPGA芯片上。
答案 0 :(得分:1)
FPGA仅在引脚上支持三态驱动器。尽管synth工具可以将内部三态转换为多路复用器,但实际上并没有为其他阅读代码的人提供明确的设计意图。三态只能在真正的inout端口上使用,并且只能在顶层使用,三态驱动程序最好也位于顶层(但如果需要,可以在层次结构中更深地移动)
您得到了多个驱动程序,因为您正在驾驶
rq <= rq_tri; -- line 90
rq <= (others => 'L'); -- line 91
这是从(其他“ L”)值中获取rq_tri值和0。 'L'会在内部被转换为'0',并驱动给定的eq_tri。尽管这可能在仿真中可行,但它不符合合成器中预期的设计模式。
如果您真的希望这样做,可以向Intel提出增强请求,但是我怀疑它会被忽略,因为它与事实上的编码样式不匹配,后者将为所有信号(输入或输出)提供明确的方向)。