我目前正在进行一个项目,我正在尝试设计一个单周期 CPU。我这样做没有任何管道衬里,因为这会大大增加设计的复杂性。当我了解到这一点时,我只是在采取婴儿步骤。我发现自己被困在这部分,我只是尝试使用以前制作的组件编写程序计数器(PC)。
我设计的模型在这里看起来像这张照片。抱歉,不知道为什么它变黑了,但是如果您单击它,它会正确显示。PC 和 theMUX 都是 32 位组件,所以我假设加法器也是如此。
这是我得到的代码,我的实现从第 41 行的 begin 语句开始。暂时不要注意它,它只是我正在尝试的一堆随机乱码。
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
---------------------------------------------------
entity pc_update is
port( clk: in std_logic; -- clock
incH_ldL: in std_logic; -- increment PC = PC + 4 when high,
-- load PCInput when low
PCInput: in std_logic_vector(31 downto 0); -- external input for PC
InstrAddr: out std_logic_vector(31 downto 0) ); -- instruction address
end entity pc_update;
----------------------------------------------------
architecture pc_update_arch of pc_update is
component register32 is
port( clr: in std_logic; -- async. clear
clk: in std_logic; -- clock
ld: in std_logic; -- load
D: in std_logic_vector(31 downto 0); -- data input
Q: out std_logic_vector(31 downto 0) ); -- data output
end component register32;
component mux2to1_32 is
port( sel: in std_logic; -- selection bit input
X0: in std_logic_vector(31 downto 0); -- first input
X1: in std_logic_vector(31 downto 0); -- second input
Y: out std_logic_vector(31 downto 0)); -- output
end component mux2to1_32;
signal PC_current: std_logic_vector(31 downto 0); -- the current state of PC reg
signal PC_add_4: std_logic_vector(31 downto 0); -- output from the adder
signal PC_next: std_logic_vector(31 downto 0); -- output from the MUX
begin
PC: register32 Port Map(
clk, Q, clr, D);
MUX: mux2to1_32 Port Map(
X0,sel,X1,Y);
process (incH_ldL)
begin
wait until (clk = '1');
if incH_1dL = '0' then
InstrAddr <= X0;
else InstrAddr <= X1;
end if;
end process;
end architecture pc_update_arch;
我对此很陌生,所以我对信号的工作原理只有一个模糊的概念,也不知道我应该如何将组件实现到设计中。我也很困惑,我没有被要求提前构建加法器。现在有必要将它用作我猜测的组件吗?
无论如何,我尝试过搜索时偶然发现的不同事物,例如您看到的端口映射。但是我总是遇到某种错误,目前我收到的错误是对象 Q、clr 和 D 已使用但未声明。我如何声明它们?如果我摆脱这些陈述,错误只会重复对象 X0、X1 和 Y。任何正确方向的帮助将不胜感激。多谢你们!
此外,以防万一您需要它们,
library ieee ;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
---------------------------------------------------
entity register32 is port(
clr: in std_logic; -- async. clear
clk: in std_logic; -- clock
ld: in std_logic; -- load
D: in std_logic_vector(31 downto 0); -- data input
Q: out std_logic_vector(31 downto 0) ); -- data output
end entity register32;
----------------------------------------------------
architecture register32_arch of register32 is
begin
process(clk, clr)
begin
if clr = '1' then
q <= x"00000000";
elsif rising_edge(clk) then
if ld = '1' then
q <= d;
end if;
end if;
end process;
END register32_arch;
和多路复用器
library ieee ;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
---------------------------------------------------
entity mux2to1_32 is
port( sel: in std_logic; -- selection bit input
X0: in std_logic_vector(31 downto 0); -- first input
X1: in std_logic_vector(31 downto 0); -- second input
Y: out std_logic_vector(31 downto 0)); -- output
end entity mux2to1_32;
----------------------------------------------------
architecture mux2to1_32_arch of mux2to1_32 is
begin
Y <= X1 when (SEL = '1') else X0;
end architecture mux2to1_32_arch;
编辑 好的,不知道我是否正确执行此操作,但我重写了端口映射。我遇到端口名称(sel、clk、X0、X1..etc)被“使用但未初始化”的错误。这就是为什么 clr、clk 和 ld 具有初始值的原因。再一次,不知道这是否正确,但是它使错误消失了。我还意识到我从未将 register32 和 mux2to1_32 VHDL 文件添加到我的项目中,并且在这样做之后摆脱了我遇到的其他错误。
就目前而言,代码可以编译,我在项目中包含了一个用于测试的 VWF 模拟文件,但我知道结果会不正确。
我还不知道有什么问题,但我知道我需要对 PC_add_4 做点什么。这个值基本上需要是(PC_current + 4),但我不知道该怎么做。
这是代码的更新部分(其他一切都相同)
PC: register32 Port Map(
clr => '0',
clk => '0',
ld => '1',
Q => PC_current,
D => PC_next
);
MUX: mux2to1_32 Port Map(
sel => incH_ldL,
X0 => PCInput ,
X1 => PC_add_4,
Y => PC_next
);
process (incH_ldL)
begin
if (rising_edge(clk)) then
if incH_ldL = '0' then
InstrAddr <= PC_current;
else InstrAddr <= PC_add_4;
end if;
end if;
end process;
而且,如果他们有帮助,我的错误列表..我猜测与引脚相关的错误是因为我还没有进行任何硬件分配。
警告 (10541):pc_update.vhd(38) 处的 VHDL 信号声明警告:使用信号“PC_add_4”的隐式默认值,因为从未为信号分配值或显式默认值。使用隐式默认值可能会引入意外的设计优化。
警告 (10492): pc_update.vhd(61) 处的 VHDL 流程声明警告:在流程声明中读取信号“clk”,但不在流程声明的敏感度列表中
警告:输出引脚卡在 VCC 或 GND
警告:设计包含 34 个不驱动逻辑的输入引脚
警告:发现 32 个输出引脚没有输出引脚负载电容分配
警告:未指定保留所有未使用的引脚设置,默认为“作为输出驱动接地”。
警告:无法生成编程文件,因为您当前正在评估模式下使用 Quartus II 软件
警告:找不到时序分析的路径
严重警告:总共 66 个引脚中的 66 个引脚没有准确的引脚位置分配
第二次编辑 所以是的,我通过添加 PC_add_4 <= (PC_current + 4 ); 来修复我的代码 在端口映射之后,并将“clk”添加到进程敏感度列表中。但是,我相信我在模拟中的波形仍然是错误的,如此处所示。
它似乎将 incH_lDL 视为一个清除信号,而不是简单地将 PCInput 传递给 InstrAddr。这很可能是由于我在端口映射中将其设置为默认的“0”。我之前这样做是因为它给了我“使用但未声明”的错误。生病尝试弄乱它并发布我的发现。
第三次编辑
我已经编辑了我的代码:
process (incH_ldL, clk)
begin
if rising_edge(clk) then
if (incH_ldL = '0') then
InstrAddr <= PCInput ;
else InstrAddr <= PC_add_4;
end if;
end if;
end process;
我的模拟现在显示,当 incH_lDL = 0 时,PCInput 被加载到 InstrAddr,但是,当 incH_lDL = 1 时,它只是加载值“4”,并且不会像它应该的那样在每个时钟周期开始时递增......我需要使用 PC_current,但我不确定如何......因为你不能将一个信号分配给另一个信号,例如“PC_current <= PCInput”。我会尝试更多的东西,同时,任何指针都将不胜感激。
第四次编辑 感谢仍在阅读本文并阅读所有内容的任何人。
我曾尝试在我的实现中使用 PC_next 和 PC_current,但遇到了“用于网络“PC_next”错误的多个常量驱动程序。
我的流程代码:
process (incH_ldL, clk, PC_next, PC_current)
begin
if rising_edge(clk) then
if (incH_ldL = '0') then
PC_next <= PCInput;
else PC_next <= PC_add_4;
end if;
end if;
InstrAddr <= PC_current;
end process;
我知道在循环中进行这些分配时会出现此错误吗?我真的不知道接下来要尝试什么。