试图在 VHDL 中找到 Fmax 但得到额外的延迟周期
Trying to find Fmax in VHDL but getting extra cycle of delay
我想看看我的 VHDL 设计的速度。据我所知,在Quartus II软件中用Fmax表示。编译我的设计后,它显示 Fmax 为 653.59 MHz。我编写了一个测试平台并进行了一些测试以确保设计按预期工作。我在设计中遇到的问题是,在时钟的上升沿,输入设置正确,但输出仅在一个周期后出现。
我的问题是:如何检查我的设计速度(输入端口和输出端口之间的最长延迟)并在输入为 [=27= 的同时获得加法的输出】 同一个循环?
我的测试台结果如下:
a:0001 和 b:0101 给出 XXXX
a: 1001 和 b: 0001 给出 0110(上一个的预期结果
计算)
a: 1001 和 b: 1001 给出 1010(上一个的预期结果
计算)
等等
代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder is
port(
clk : in STD_LOGIC;
a : in unsigned(3 downto 0);
b : in unsigned(3 downto 0);
sum : out unsigned(3 downto 0)
);
end adder;
architecture rtl of adder is
signal a_r, b_r, sum_r : unsigned(3 downto 0);
begin
sum_r <= a_r + b_r;
process(clk)
begin
if (rising_edge(clk)) then
a_r <= a;
b_r <= b;
sum <= sum_r;
end if;
end process;
end rtl;
测试平台:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity testbench is
end entity;
architecture behavioral of testbench is
component adder is
port(
clk : in STD_LOGIC;
a : in unsigned(3 downto 0);
b : in unsigned(3 downto 0);
sum : out unsigned(3 downto 0)
);
end component;
signal a, b, sum : unsigned(3 downto 0);
signal clk : STD_LOGIC;
begin
uut: adder
port map(
clk => clk,
a => a,
b => b,
sum => sum
);
stim_process : process
begin
wait for 1 ns;
clk <= '0';
wait for 1 ns;
clk <= '1';
a <= "0001";
b <= "0101";
wait for 1 ns;
clk <= '0';
wait for 1 ns;
clk <= '1';
a <= "1001";
b <= "0001";
wait for 1 ns;
clk <= '0';
wait for 1 ns;
clk <= '1';
a <= "1001";
b <= "1001";
end process;
end behavioral;
使用 sum_r 作为输出有什么问题吗?
如果您将此 ALU 视为纯组合逻辑,则不需要输入和输出寄存器。一旦你删除它们,Fmax 就会消失,然后将依赖于它的连接来源和它连接的内容,并且只有当传入来自寄存器并且传出是寄存器时。如果只是从输入到输出以及从输入引脚到输出引脚的逻辑,我认为很难说出传播延迟是什么,而且像 Altera 和其他现代供应商这样的供应商软件没有足够的工具来处理这种情况分析。
这就是为什么你会听到人们谈论设计异步逻辑的困难。
我认为如此精细的分析很难准确无误地进行。因为对你来说,传播延迟将以皮秒为单位。即使是文献也很难找到关于传播延迟的任何定量答案。
为什么难?请记住,传播延迟由总路径电容决定,有一种方法可以估算晶体管的传播延迟,但我不知道有关 LUT 内部构造方式的详细信息,因此我无法给您一个很好的估算。所以这在很大程度上取决于家庭,制造过程,FPGA的结构以及负载是否连接到IO。
然而,您可以通过转到逻辑规划器做出自己的估计,查看路径并假设每个 LUT 传播延迟大约 20-100ps
见下图。
你要设计的是一个ALU。根据定义,ALU 在理论上应该只是一个组合逻辑。
因此,严格来说,你的加法器代码应该只是这样。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder is
port(
a : in unsigned(3 downto 0);
b : in unsigned(3 downto 0);
sum : out unsigned(3 downto 0)
);
end adder;
architecture rtl of adder is
begin
sum <= a + b;
end rtl;
不需要时钟,因为这个函数实际上是一个组合过程。
但是如果你想让你的 ALU 进入我所描述的阶段,你应该做的实际上是这个
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder is
port(
clk : in STD_LOGIC;
a : in unsigned(3 downto 0);
b : in unsigned(3 downto 0);
sum : out unsigned(3 downto 0)
);
end adder;
architecture rtl of adder is
signal a_r, b_r, sum_r : unsigned(3 downto 0);
signal internal_sum : unsigned(3 downto 0);
begin
sum <= sum_r;
internal_sum <= a_r + b_r;
process(clk)
begin
if (rising_edge(clk)) then
a_r <= a;
b_r <= b;
sum_r <= internal_sum;
end if;
end process;
end rtl;
你没有提到执行所以我不会在这里讨论。
最后,如果您使用的是 Altera,他们有一个非常好的 RTL 查看器,您可以查看您的综合设计。在工具->网表查看器->RTL 查看器下。
我想看看我的 VHDL 设计的速度。据我所知,在Quartus II软件中用Fmax表示。编译我的设计后,它显示 Fmax 为 653.59 MHz。我编写了一个测试平台并进行了一些测试以确保设计按预期工作。我在设计中遇到的问题是,在时钟的上升沿,输入设置正确,但输出仅在一个周期后出现。
我的问题是:如何检查我的设计速度(输入端口和输出端口之间的最长延迟)并在输入为 [=27= 的同时获得加法的输出】 同一个循环?
我的测试台结果如下:
a:0001 和 b:0101 给出 XXXX
a: 1001 和 b: 0001 给出 0110(上一个的预期结果
计算)
a: 1001 和 b: 1001 给出 1010(上一个的预期结果
计算)
等等
代码:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder is
port(
clk : in STD_LOGIC;
a : in unsigned(3 downto 0);
b : in unsigned(3 downto 0);
sum : out unsigned(3 downto 0)
);
end adder;
architecture rtl of adder is
signal a_r, b_r, sum_r : unsigned(3 downto 0);
begin
sum_r <= a_r + b_r;
process(clk)
begin
if (rising_edge(clk)) then
a_r <= a;
b_r <= b;
sum <= sum_r;
end if;
end process;
end rtl;
测试平台:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity testbench is
end entity;
architecture behavioral of testbench is
component adder is
port(
clk : in STD_LOGIC;
a : in unsigned(3 downto 0);
b : in unsigned(3 downto 0);
sum : out unsigned(3 downto 0)
);
end component;
signal a, b, sum : unsigned(3 downto 0);
signal clk : STD_LOGIC;
begin
uut: adder
port map(
clk => clk,
a => a,
b => b,
sum => sum
);
stim_process : process
begin
wait for 1 ns;
clk <= '0';
wait for 1 ns;
clk <= '1';
a <= "0001";
b <= "0101";
wait for 1 ns;
clk <= '0';
wait for 1 ns;
clk <= '1';
a <= "1001";
b <= "0001";
wait for 1 ns;
clk <= '0';
wait for 1 ns;
clk <= '1';
a <= "1001";
b <= "1001";
end process;
end behavioral;
使用 sum_r 作为输出有什么问题吗?
如果您将此 ALU 视为纯组合逻辑,则不需要输入和输出寄存器。一旦你删除它们,Fmax 就会消失,然后将依赖于它的连接来源和它连接的内容,并且只有当传入来自寄存器并且传出是寄存器时。如果只是从输入到输出以及从输入引脚到输出引脚的逻辑,我认为很难说出传播延迟是什么,而且像 Altera 和其他现代供应商这样的供应商软件没有足够的工具来处理这种情况分析。
这就是为什么你会听到人们谈论设计异步逻辑的困难。
我认为如此精细的分析很难准确无误地进行。因为对你来说,传播延迟将以皮秒为单位。即使是文献也很难找到关于传播延迟的任何定量答案。
为什么难?请记住,传播延迟由总路径电容决定,有一种方法可以估算晶体管的传播延迟,但我不知道有关 LUT 内部构造方式的详细信息,因此我无法给您一个很好的估算。所以这在很大程度上取决于家庭,制造过程,FPGA的结构以及负载是否连接到IO。
然而,您可以通过转到逻辑规划器做出自己的估计,查看路径并假设每个 LUT 传播延迟大约 20-100ps
见下图。
你要设计的是一个ALU。根据定义,ALU 在理论上应该只是一个组合逻辑。
因此,严格来说,你的加法器代码应该只是这样。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder is
port(
a : in unsigned(3 downto 0);
b : in unsigned(3 downto 0);
sum : out unsigned(3 downto 0)
);
end adder;
architecture rtl of adder is
begin
sum <= a + b;
end rtl;
不需要时钟,因为这个函数实际上是一个组合过程。
但是如果你想让你的 ALU 进入我所描述的阶段,你应该做的实际上是这个
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity adder is
port(
clk : in STD_LOGIC;
a : in unsigned(3 downto 0);
b : in unsigned(3 downto 0);
sum : out unsigned(3 downto 0)
);
end adder;
architecture rtl of adder is
signal a_r, b_r, sum_r : unsigned(3 downto 0);
signal internal_sum : unsigned(3 downto 0);
begin
sum <= sum_r;
internal_sum <= a_r + b_r;
process(clk)
begin
if (rising_edge(clk)) then
a_r <= a;
b_r <= b;
sum_r <= internal_sum;
end if;
end process;
end rtl;
你没有提到执行所以我不会在这里讨论。
最后,如果您使用的是 Altera,他们有一个非常好的 RTL 查看器,您可以查看您的综合设计。在工具->网表查看器->RTL 查看器下。