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 模式下编译才能工作。