某些操作波形不能正常工作
waveform does not work properly for some operations
我是 vhdl、modelsim、waveform 等方面的新手。我开发了一个简单的操作流程和一个测试台来在 modelsim 波形上逐一测试我的操作。
当我 运行 在模拟器上时,我发现有一些问题;尽管在临时变量 (uQ2) 中计算正确,但乘法运算结果未放入输出变量 (result_out1)。此外 mod 和 rem 操作不提供任何输出。
虽然 add、sub 和 div 操作按预期工作为什么 mul、mod 和 rem 操作失败?
我在下面分享我的代码和波形结果。
我的代码和测试台在下面;
rns.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity rns is
port(
en: in std_logic;
op: in std_logic_vector(2 downto 0);
reg_a_in: in std_logic_vector(7 downto 0);
reg_b_in: in std_logic_vector(7 downto 0);
reg_c_in: in std_logic_vector(7 downto 0);
result_out1: out std_logic_vector(7 downto 0);
result_out2: out std_logic_vector(7 downto 0)
);
end entity;
architecture behave of rns is
signal uA, uB, uC, uQ, uR: unsigned(8 downto 0);
signal uQ2: unsigned(17 downto 0);
signal result: std_logic_vector(8 downto 0);
begin
process(reg_a_in, reg_b_in, op)
begin
uA <= unsigned('0' & reg_a_in);
uB <= unsigned('0' & reg_b_in);
if op = "000" then
uQ <= uA + uB;
elsif op = "001" then
uQ <= uA - uB;
elsif op = "010" then
uQ2 <= uA * uB;
uQ <= resize(uQ2, uQ'length); --uQ2(8 downto 0);
elsif op = "011" then
uQ <= uA / uB;
elsif op = "100" then
uQ <= uA mod uB;
elsif op = "101" then
uQ <= uA rem uB;
end if;
end process;
result <= std_logic_vector(uQ) when en = '1' else (others=>'Z');
result_out1 <= result(7 downto 0) when en = '1' else (others=>'Z');
end behave;
rns_tb.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity rns_tb is
end entity;
architecture behave of rns_tb is
component rns is
port(
en: in std_logic;
op: in std_logic_vector(2 downto 0);
reg_a_in: in std_logic_vector(7 downto 0);
reg_b_in: in std_logic_vector(7 downto 0);
reg_c_in: in std_logic_vector(7 downto 0);
result_out1: out std_logic_vector(7 downto 0);
result_out2: out std_logic_vector(7 downto 0)
);
end component;
signal en_sig: std_logic;
signal op_sig: std_logic_vector(2 downto 0);
signal reg_a_in_sig: std_logic_vector(7 downto 0);
signal reg_b_in_sig: std_logic_vector(7 downto 0);
signal reg_c_in_sig: std_logic_vector(7 downto 0);
signal result_out1_sig: std_logic_vector(7 downto 0);
signal result_out2_sig: std_logic_vector(7 downto 0);
constant wait_period: time :=10 ns;
begin
rns1 : rns port map(en=>en_sig, op=>op_sig, reg_a_in=>reg_a_in_sig, reg_b_in=>reg_b_in_sig,
reg_c_in=>reg_c_in_sig, result_out1=>result_out1_sig, result_out2=>result_out2_sig);
process
begin
op_sig <= (others => 'Z');
wait for wait_period * 3;
reg_a_in_sig <= "00000011";
reg_b_in_sig <= "00000010";
reg_c_in_sig <= "00000101";
wait for wait_period;
en_sig <= '1';
op_sig <= "000";
wait for wait_period * 5;
op_sig <= "001";
wait for wait_period * 5;
op_sig <= "010";
wait for wait_period * 5;
op_sig <= "011";
wait for wait_period * 5;
op_sig <= "100";
wait for wait_period * 5;
op_sig <= "101";
wait;
end process;
end behave;
提前致谢。
老实说,我建议您只使用时钟进程,直到您完全了解它们的工作原理。但让我们看看是否可以解决您的问题。
问题出在您的进程的敏感度列表上。每当敏感列表中的信号发生变化时,模拟工具将评估过程的结果。对于所有操作,这是信号 op
发生变化并且流程重新评估 uQ
.
重要说明:敏感度列表仅用于模拟目的,并且在过程评估完成后分配信号。
上面的意思是,在乘法的情况下,op
变为 010
并且过程求值
uQ2 <= uA * uB;
uQ <= resize(uQ2, uQ'length); --uQ2(8 downto 0);
但是因为信号是在求值之后分配的,所以uQ2
会有乘法的结果但是uQ
是之前uQ2
的调整大小。要解决此问题,您可以...
- 不用
uQ2
直接写uQ <= resize(uA * uB, uQ'length)
- 使用
uQ2
扩展敏感度列表,以便在 uQ2
更新后重新评估 uQ
。
- 正如评论中正确提到的那样,如果您需要立即评估的
process
中的“信号”,请使用 variables
而不是 signal
类型。
结果分配可以优化,老实说,在这种情况下我不会使用Z
。
--result <= std_logic_vector(uQ) when en = '1' else (others=>'Z');
result_out1 <= std_logic_vector(uQ(7 downto 0)) when en = '1' else (others=>'0');
总的来说,这个实现有一些缺陷,你可能应该添加一些额外的控制信号,甚至让它成为一个时钟进程。检查这是否解决了您的问题,我没有测试它并且我的大脑仍处于圣诞节模式。
我是 vhdl、modelsim、waveform 等方面的新手。我开发了一个简单的操作流程和一个测试台来在 modelsim 波形上逐一测试我的操作。
当我 运行 在模拟器上时,我发现有一些问题;尽管在临时变量 (uQ2) 中计算正确,但乘法运算结果未放入输出变量 (result_out1)。此外 mod 和 rem 操作不提供任何输出。
虽然 add、sub 和 div 操作按预期工作为什么 mul、mod 和 rem 操作失败?
我在下面分享我的代码和波形结果。
我的代码和测试台在下面;
rns.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity rns is
port(
en: in std_logic;
op: in std_logic_vector(2 downto 0);
reg_a_in: in std_logic_vector(7 downto 0);
reg_b_in: in std_logic_vector(7 downto 0);
reg_c_in: in std_logic_vector(7 downto 0);
result_out1: out std_logic_vector(7 downto 0);
result_out2: out std_logic_vector(7 downto 0)
);
end entity;
architecture behave of rns is
signal uA, uB, uC, uQ, uR: unsigned(8 downto 0);
signal uQ2: unsigned(17 downto 0);
signal result: std_logic_vector(8 downto 0);
begin
process(reg_a_in, reg_b_in, op)
begin
uA <= unsigned('0' & reg_a_in);
uB <= unsigned('0' & reg_b_in);
if op = "000" then
uQ <= uA + uB;
elsif op = "001" then
uQ <= uA - uB;
elsif op = "010" then
uQ2 <= uA * uB;
uQ <= resize(uQ2, uQ'length); --uQ2(8 downto 0);
elsif op = "011" then
uQ <= uA / uB;
elsif op = "100" then
uQ <= uA mod uB;
elsif op = "101" then
uQ <= uA rem uB;
end if;
end process;
result <= std_logic_vector(uQ) when en = '1' else (others=>'Z');
result_out1 <= result(7 downto 0) when en = '1' else (others=>'Z');
end behave;
rns_tb.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity rns_tb is
end entity;
architecture behave of rns_tb is
component rns is
port(
en: in std_logic;
op: in std_logic_vector(2 downto 0);
reg_a_in: in std_logic_vector(7 downto 0);
reg_b_in: in std_logic_vector(7 downto 0);
reg_c_in: in std_logic_vector(7 downto 0);
result_out1: out std_logic_vector(7 downto 0);
result_out2: out std_logic_vector(7 downto 0)
);
end component;
signal en_sig: std_logic;
signal op_sig: std_logic_vector(2 downto 0);
signal reg_a_in_sig: std_logic_vector(7 downto 0);
signal reg_b_in_sig: std_logic_vector(7 downto 0);
signal reg_c_in_sig: std_logic_vector(7 downto 0);
signal result_out1_sig: std_logic_vector(7 downto 0);
signal result_out2_sig: std_logic_vector(7 downto 0);
constant wait_period: time :=10 ns;
begin
rns1 : rns port map(en=>en_sig, op=>op_sig, reg_a_in=>reg_a_in_sig, reg_b_in=>reg_b_in_sig,
reg_c_in=>reg_c_in_sig, result_out1=>result_out1_sig, result_out2=>result_out2_sig);
process
begin
op_sig <= (others => 'Z');
wait for wait_period * 3;
reg_a_in_sig <= "00000011";
reg_b_in_sig <= "00000010";
reg_c_in_sig <= "00000101";
wait for wait_period;
en_sig <= '1';
op_sig <= "000";
wait for wait_period * 5;
op_sig <= "001";
wait for wait_period * 5;
op_sig <= "010";
wait for wait_period * 5;
op_sig <= "011";
wait for wait_period * 5;
op_sig <= "100";
wait for wait_period * 5;
op_sig <= "101";
wait;
end process;
end behave;
提前致谢。
老实说,我建议您只使用时钟进程,直到您完全了解它们的工作原理。但让我们看看是否可以解决您的问题。
问题出在您的进程的敏感度列表上。每当敏感列表中的信号发生变化时,模拟工具将评估过程的结果。对于所有操作,这是信号 op
发生变化并且流程重新评估 uQ
.
重要说明:敏感度列表仅用于模拟目的,并且在过程评估完成后分配信号。
上面的意思是,在乘法的情况下,op
变为 010
并且过程求值
uQ2 <= uA * uB;
uQ <= resize(uQ2, uQ'length); --uQ2(8 downto 0);
但是因为信号是在求值之后分配的,所以uQ2
会有乘法的结果但是uQ
是之前uQ2
的调整大小。要解决此问题,您可以...
- 不用
uQ2
直接写uQ <= resize(uA * uB, uQ'length)
- 使用
uQ2
扩展敏感度列表,以便在uQ2
更新后重新评估uQ
。 - 正如评论中正确提到的那样,如果您需要立即评估的
process
中的“信号”,请使用variables
而不是signal
类型。
结果分配可以优化,老实说,在这种情况下我不会使用Z
。
--result <= std_logic_vector(uQ) when en = '1' else (others=>'Z');
result_out1 <= std_logic_vector(uQ(7 downto 0)) when en = '1' else (others=>'0');
总的来说,这个实现有一些缺陷,你可能应该添加一些额外的控制信号,甚至让它成为一个时钟进程。检查这是否解决了您的问题,我没有测试它并且我的大脑仍处于圣诞节模式。