VHDL shift_left/shift_right 停止工作
VHDL shift_left/shift_right stopped working
我让这个 alu 使用 shift left/right 函数,并且在 rd_data2 上发送了 shift 量,一个 16 位 std_logic_vector。然而,我被迫将其更改为 4 位 std_logic_vector,称为 'shift',现在它不再移动了。
这是我的代码。我不知道我哪里出错了。有什么想法吗?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
--use IEEE.STD_LOGIC_ARITH.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity alu_v2 is
Port ( rd_data1 : in STD_LOGIC_VECTOR (15 downto 0);
rd_data2 : in STD_LOGIC_VECTOR (15 downto 0);
alu_mode : in STD_LOGIC_VECTOR (2 downto 0);
result : out STD_LOGIC_VECTOR (15 downto 0);
clk : in std_logic;
shift : in std_logic_vector (3 downto 0);
rst : in STD_LOGIC;
z_flag : out STD_LOGIC;
n_flag : out STD_LOGIC);
end alu_v2;
architecture Behavioral of alu_v2 is
begin
process(rd_data1,rd_data2,alu_mode,rst)
variable temp : STD_LOGIC_VECTOR(15 downto 0):=X"0000";
variable m_temp : std_logic_vector(31 downto 0);
begin
if (rst = '1' ) then
n_flag <= '0';
z_flag <= '0';
result <= X"0000";
else if (rst = '0') then
case alu_mode(2 downto 0) is
when "000" => NULL;
when "001" => temp := rd_data1 + rd_data2 ;
when "010" => temp := rd_data1 - rd_data2 ;
when "011" => m_temp := rd_data1 * rd_data2;
temp := m_temp(15 downto 0);
when "100" => temp := rd_data1 NAND rd_data2 ;
when "101" => temp := std_logic_vector(shift_left(unsigned(rd_data1),to_integer(unsigned(shift))));
when "110" => temp := std_logic_vector(shift_right((unsigned(rd_data1)),to_integer(unsigned(shift))));
when "111" => z_flag <= '0';
n_flag <= '0';
when others => NULL;
end case;
if (temp = X"0000" ) then z_flag <= '1';
n_flag <= '0';
end if;
if (temp(15) = '1' ) then n_flag <= '1';
z_flag <= '0';
else if(temp(15) = '0')and(temp > 0) then n_flag <= '0';
z_flag <= '0';
end if;
end if;
end if;
end if;
result <= temp;
end process;
end Behavioral;
您的进程敏感度列表中没有 "shift"。
是的,有很多地方是错误的。首先,即使您有一个时钟输入端口,您的设计也是异步的。这可能是错误的。
您应该有一个带有异步重置的同步进程
main_proc: process(rst, clk)
begin
if rst='1' then
-- reset stuff
elsif rising_edge(clk) then
-- do stuff
end if;
end process;
或者 - 最好 - 具有同步重置的同步过程
main_proc: process(clk)
begin
if rising_edge(clk) then
if rst='1' then
-- reset stuff
else
-- do stuff
end if;
end if;
end process;
这样,灵敏度列表中缺少信号将不再是一个问题。
其次,你的flag设置搞砸了。如果 alu_mode(2 downto 0)="111"
您首先设置了两个标志,但 立即 覆盖它们 if (temp = x"0000" )
或 if (temp(15) = '1' )
。之前设置没用。
尽量避免使用变量。在这种情况下,您可以通过检测过程语句的零和 n-flag 外部 来避免变量。
signal result_int : unsigned(result'range) := (others => '0');
begin
-- main_process
result <= std_logic_vector(result_int);
z_flag <= '1' when to_integer(result_int) = 0 else '0';
n_flag <= result_int(result_int'length-1);
第三 else if
--> elsif
...不需要额外的 end if;
...如果您输入 if rst='1'
那么您永远不必跟在 elsif rst='0'
:当然 rst='0'
如果它不是'1'...
最后,不要使用 STD_LOGIC_unsigned
包。它不是标准化的。您需要的一切都在 NUMERIC_STD
.
p.s。如果您不想担心灵敏度列表中缺少信号,可以使用 VHDL-2008 方法 process(all)
。这将自动包括所有相关信号。你必须在 VHDL-2008 模式下编译才能工作。
我让这个 alu 使用 shift left/right 函数,并且在 rd_data2 上发送了 shift 量,一个 16 位 std_logic_vector。然而,我被迫将其更改为 4 位 std_logic_vector,称为 'shift',现在它不再移动了。
这是我的代码。我不知道我哪里出错了。有什么想法吗?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
--use IEEE.STD_LOGIC_ARITH.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity alu_v2 is
Port ( rd_data1 : in STD_LOGIC_VECTOR (15 downto 0);
rd_data2 : in STD_LOGIC_VECTOR (15 downto 0);
alu_mode : in STD_LOGIC_VECTOR (2 downto 0);
result : out STD_LOGIC_VECTOR (15 downto 0);
clk : in std_logic;
shift : in std_logic_vector (3 downto 0);
rst : in STD_LOGIC;
z_flag : out STD_LOGIC;
n_flag : out STD_LOGIC);
end alu_v2;
architecture Behavioral of alu_v2 is
begin
process(rd_data1,rd_data2,alu_mode,rst)
variable temp : STD_LOGIC_VECTOR(15 downto 0):=X"0000";
variable m_temp : std_logic_vector(31 downto 0);
begin
if (rst = '1' ) then
n_flag <= '0';
z_flag <= '0';
result <= X"0000";
else if (rst = '0') then
case alu_mode(2 downto 0) is
when "000" => NULL;
when "001" => temp := rd_data1 + rd_data2 ;
when "010" => temp := rd_data1 - rd_data2 ;
when "011" => m_temp := rd_data1 * rd_data2;
temp := m_temp(15 downto 0);
when "100" => temp := rd_data1 NAND rd_data2 ;
when "101" => temp := std_logic_vector(shift_left(unsigned(rd_data1),to_integer(unsigned(shift))));
when "110" => temp := std_logic_vector(shift_right((unsigned(rd_data1)),to_integer(unsigned(shift))));
when "111" => z_flag <= '0';
n_flag <= '0';
when others => NULL;
end case;
if (temp = X"0000" ) then z_flag <= '1';
n_flag <= '0';
end if;
if (temp(15) = '1' ) then n_flag <= '1';
z_flag <= '0';
else if(temp(15) = '0')and(temp > 0) then n_flag <= '0';
z_flag <= '0';
end if;
end if;
end if;
end if;
result <= temp;
end process;
end Behavioral;
您的进程敏感度列表中没有 "shift"。
是的,有很多地方是错误的。首先,即使您有一个时钟输入端口,您的设计也是异步的。这可能是错误的。
您应该有一个带有异步重置的同步进程
main_proc: process(rst, clk)
begin
if rst='1' then
-- reset stuff
elsif rising_edge(clk) then
-- do stuff
end if;
end process;
或者 - 最好 - 具有同步重置的同步过程
main_proc: process(clk)
begin
if rising_edge(clk) then
if rst='1' then
-- reset stuff
else
-- do stuff
end if;
end if;
end process;
这样,灵敏度列表中缺少信号将不再是一个问题。
其次,你的flag设置搞砸了。如果 alu_mode(2 downto 0)="111"
您首先设置了两个标志,但 立即 覆盖它们 if (temp = x"0000" )
或 if (temp(15) = '1' )
。之前设置没用。
尽量避免使用变量。在这种情况下,您可以通过检测过程语句的零和 n-flag 外部 来避免变量。
signal result_int : unsigned(result'range) := (others => '0');
begin
-- main_process
result <= std_logic_vector(result_int);
z_flag <= '1' when to_integer(result_int) = 0 else '0';
n_flag <= result_int(result_int'length-1);
第三 else if
--> elsif
...不需要额外的 end if;
...如果您输入 if rst='1'
那么您永远不必跟在 elsif rst='0'
:当然 rst='0'
如果它不是'1'...
最后,不要使用 STD_LOGIC_unsigned
包。它不是标准化的。您需要的一切都在 NUMERIC_STD
.
p.s。如果您不想担心灵敏度列表中缺少信号,可以使用 VHDL-2008 方法 process(all)
。这将自动包括所有相关信号。你必须在 VHDL-2008 模式下编译才能工作。