使用 VHDL 移位运算符左移寄存器:麻烦

Shift left register using VHDL shift operator : sll trouble

library IEEE;
use IEEE.std_logic_1164.all;    
use IEEE.numeric_std.all;

entity shift_reg is 
    port(
    d : in std_logic;
    clk : in std_logic;
    rst_bar : in std_logic;
    q : out std_logic_vector(7 downto 0)
    );
end shift_reg;

architecture post_vhdl_08 of shift_reg is   
begin

    process(clk, rst_bar)  

    variable q_int : std_logic_vector(7 downto 0);

    begin
        if rst_bar = '0' then
            q_int := (others => '0');
        elsif rising_edge(clk) then
            q_int := q_int(6 downto 0) & d;
        end if; 

        q <= q_int;

    end process;

end post_vhdl_08;

我已经使用 "slice" 实现了一个具有串行输入和并行输出的左移寄存器来实现移位;但我无法弄清楚如何使用重载的移位运算符实现相同的逻辑:'sll'(左移逻辑)运算符。 谢谢大家提供的任何帮助。

我可以为您提供这种移动方法 left/right 或使用旋转 (VHDL '87!) ..

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity Barrelshifter is

  generic (gSize : natural := 3);
  port (
    iPortA : in std_ulogic_vector(2**gSize-1 downto 0);
    oPortQ : out std_ulogic_vector(2**gSize-1 downto 0);
    iShiftDigits : in std_ulogic_vector(gSize-1 downto 0);
    iModeSelect : in std_ulogic_vector(1 downto 0)
    );

end Barrelshifter;

architecture Rtl of Barrelshifter is

begin   -- architecture Rtl 

  Comb: process (iPortA, iShiftDigits, iModeSelect)

  -- component variables
    variable Count : integer;  

  begin  -- process Comb


    Count := to_integer(unsigned(iShiftDigits));

    if iModeSelect = "00" then
        oPortQ <= std_ulogic_vector(shift_left(unsigned(iPortA), Count));

    elsif iModeSelect = "01" then
        oPortQ <= std_ulogic_vector(shift_right(unsigned(iPortA), Count));

    elsif iModeSelect = "10" then
        oPortQ <= std_ulogic_vector(rotate_left(unsigned(iPortA), Count));

    else
        oPortQ <= std_ulogic_vector(rotate_right(unsigned(iPortA), Count));

    end if;

  end process Comb;

end Rtl ;

以下是如何使用 sll 运算符的示例。正如您所看到的,这很痛苦,因为它无法满足您的要求,而且还有其他麻烦事要做:

process(clk, rst_bar)  

variable q_int : unsigned(7 downto 0);
subtype  st is unsigned(7 downto 0);

begin
    if rst_bar = '0' then
        q_int := (others => '0');
    elsif rising_edge(clk) then
        q_int := q_int sll 1;
        q_int := q_int or st'(0=>d,others=>'0');
        q <= std_logic_vector(q_int);
    end if; 
end process;

http://www.edaplayground.com/x/3YGu

因此,对于初学者来说,sll 转变为 '0',这不是您想要的。因此,您需要一个 or 操作来包含 d 输入。但是,对于 std_logic_vectorsll 并未 过载 ,因此您必须使用 unsignedsignedunsigned这里说得通)。不仅如此,这些类型的运算符在 VHDL 中做 strange things。所以,如果我是你,我会坚持连接。

此外,您对 q 的分配位置错误。当您执行顺序过程时,您不得分配给 if rising_edge 之外的信号,否则(在这种情况下)q 将在两个时钟边沿分配 - 不可综合的行为。

最后,根据您的合成器的能力,您可以获得 16 个触发器而不是 8 个。这是因为您的变量将合成为 8 个触发器,并且您的信号将合成为另外 8 个("every signal assigned in a clocked process infers a flip-flop").然后,您将回复您的合成器以优化其中的 8 个触发器。