VHDL:为什么输出延迟这么多?
VHDL: Why is output delayed so much?
我正在学习 VHDL,以描述和演示具有危险检测和分支预测等功能的超标量流水线 CPU 的工作
我从小做起,所以为了练习,我尝试制作一个非常简单的 "calculator" 设计,如下所示:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_signed.all;
entity calculator is
port(
in_A : in std_logic_vector(3 downto 0);
in_B : in std_logic_vector(3 downto 0);
add : in std_logic;
sub : in std_logic;
out_C : out std_logic_vector(3 downto 0)
);
end entity calculator;
architecture RTL of calculator is
signal next_output : std_logic_vector(3 downto 0);
begin
process(in_A, in_B, add, sub)
variable temp_x, temp_y, temp_z : integer;
begin
temp_x := conv_integer(in_A);
temp_y := conv_integer(in_B);
if(add = '1') and (sub = '0') then
temp_z := temp_x + temp_y;
next_output <= std_logic_vector(to_unsigned(temp_z, 4));
elsif(add = '0') and (sub = '1') then
temp_z := temp_x - temp_y;
next_output <= std_logic_vector(to_unsigned(temp_z,4));
else
temp_z := 0;
next_output <= std_logic_vector(to_unsigned(temp_z,4));
end if;
out_C <= next_output;
end process;
end architecture RTL;
但是,我不明白为什么只有在输入更改后才设置输出,如此处所示(我猜测试台代码无关紧要):
我想知道我应该怎么做才能使输出正确并立即可用。如果add是1,那么输出应该根据输入来设置,没有延迟(好吧,我希望它是,我写的方式,它不是:))
此外,有人可以向我解释一下何时会在触发器中记住输出,以及是否按照我写描述的方式在触发器中记住它。
我也非常感谢所有帮助我的建议、批评和指导。这只是一个简单的 ADD/SUB 计算器,我要在大约两个月内用一个指令集描述一个完整的处理器!也许你可以给我指出好的学习教程,因为我的 类 没用:(
提前致谢! :)
最简单的方法是移动作业
out_C <= next_output;
进程外(使其成为并发信号分配)。
您还可以使 next_output 成为过程中声明的变量,并将信号赋值保留在原处。
延迟的发生是因为信号分配在它们发生的模拟周期中没有生效。如果没有对 next_output 敏感的进程,它的新值将在下一次进程以其他方式执行时看到。
并发信号分配语句具有等效过程,其中右侧的信号在敏感列表中。
将 next_output 设为变量使其值立即可用。
你也可以重写你的过程:
process(in_A, in_B, add, sub)
variable temp_x, temp_y, temp_z : integer;
begin
temp_x := conv_integer(in_A);
temp_y := conv_integer(in_B);
if(add = '1') and (sub = '0') then
temp_z := temp_x + temp_y;
elsif(add = '0') and (sub = '1') then
temp_z := temp_x - temp_y;
else
temp_z := 0;
end if;
out_C <= std_logic_vector(to_unsigned(temp_z,4));
end process;
并消除next_output。
信号分配 <=
到中间信号 next_output
不是
在同一个 运行 的进程中可见,所以它需要另一个 运行 的进程
直到 out_C <= next_output
看到新值,因此延迟。
正如 David Koontz 所写,那么您可以将 out_C <= next_output
移到
过程。
另一种方法是获取所有中间信号和变量的脊线,并且
重写代码如下,包括只使用IEEE标准包
numeric_std
,并跳过 Synopsys 专有包
std_logic_signed
.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
...
architecture RTL of calculator is
begin
process(in_A, in_B, add, sub)
begin
if(add = '1') and (sub = '0') then
out_C <= std_logic_vector(signed(in_A) + signed(in_B));
elsif(add = '0') and (sub = '1') then
out_C <= std_logic_vector(signed(in_A) - signed(in_B));
else
out_C <= std_logic_vector(to_signed(0, out_C'length));
end if;
end process;
end architecture RTL;
我看到 David 提出了类似的建议,但无论如何你都可以得到我的 :-)
我正在学习 VHDL,以描述和演示具有危险检测和分支预测等功能的超标量流水线 CPU 的工作
我从小做起,所以为了练习,我尝试制作一个非常简单的 "calculator" 设计,如下所示:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_signed.all;
entity calculator is
port(
in_A : in std_logic_vector(3 downto 0);
in_B : in std_logic_vector(3 downto 0);
add : in std_logic;
sub : in std_logic;
out_C : out std_logic_vector(3 downto 0)
);
end entity calculator;
architecture RTL of calculator is
signal next_output : std_logic_vector(3 downto 0);
begin
process(in_A, in_B, add, sub)
variable temp_x, temp_y, temp_z : integer;
begin
temp_x := conv_integer(in_A);
temp_y := conv_integer(in_B);
if(add = '1') and (sub = '0') then
temp_z := temp_x + temp_y;
next_output <= std_logic_vector(to_unsigned(temp_z, 4));
elsif(add = '0') and (sub = '1') then
temp_z := temp_x - temp_y;
next_output <= std_logic_vector(to_unsigned(temp_z,4));
else
temp_z := 0;
next_output <= std_logic_vector(to_unsigned(temp_z,4));
end if;
out_C <= next_output;
end process;
end architecture RTL;
但是,我不明白为什么只有在输入更改后才设置输出,如此处所示(我猜测试台代码无关紧要):
我想知道我应该怎么做才能使输出正确并立即可用。如果add是1,那么输出应该根据输入来设置,没有延迟(好吧,我希望它是,我写的方式,它不是:))
此外,有人可以向我解释一下何时会在触发器中记住输出,以及是否按照我写描述的方式在触发器中记住它。
我也非常感谢所有帮助我的建议、批评和指导。这只是一个简单的 ADD/SUB 计算器,我要在大约两个月内用一个指令集描述一个完整的处理器!也许你可以给我指出好的学习教程,因为我的 类 没用:(
提前致谢! :)
最简单的方法是移动作业
out_C <= next_output;
进程外(使其成为并发信号分配)。
您还可以使 next_output 成为过程中声明的变量,并将信号赋值保留在原处。
延迟的发生是因为信号分配在它们发生的模拟周期中没有生效。如果没有对 next_output 敏感的进程,它的新值将在下一次进程以其他方式执行时看到。
并发信号分配语句具有等效过程,其中右侧的信号在敏感列表中。
将 next_output 设为变量使其值立即可用。
你也可以重写你的过程:
process(in_A, in_B, add, sub)
variable temp_x, temp_y, temp_z : integer;
begin
temp_x := conv_integer(in_A);
temp_y := conv_integer(in_B);
if(add = '1') and (sub = '0') then
temp_z := temp_x + temp_y;
elsif(add = '0') and (sub = '1') then
temp_z := temp_x - temp_y;
else
temp_z := 0;
end if;
out_C <= std_logic_vector(to_unsigned(temp_z,4));
end process;
并消除next_output。
信号分配 <=
到中间信号 next_output
不是
在同一个 运行 的进程中可见,所以它需要另一个 运行 的进程
直到 out_C <= next_output
看到新值,因此延迟。
正如 David Koontz 所写,那么您可以将 out_C <= next_output
移到
过程。
另一种方法是获取所有中间信号和变量的脊线,并且
重写代码如下,包括只使用IEEE标准包
numeric_std
,并跳过 Synopsys 专有包
std_logic_signed
.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
...
architecture RTL of calculator is
begin
process(in_A, in_B, add, sub)
begin
if(add = '1') and (sub = '0') then
out_C <= std_logic_vector(signed(in_A) + signed(in_B));
elsif(add = '0') and (sub = '1') then
out_C <= std_logic_vector(signed(in_A) - signed(in_B));
else
out_C <= std_logic_vector(to_signed(0, out_C'length));
end if;
end process;
end architecture RTL;
我看到 David 提出了类似的建议,但无论如何你都可以得到我的 :-)