使用 VHDL 移位运算符左移寄存器:sll 故障


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;

我已经使用"切片"实现了具有串行输入和并行输出的左移寄存器来实现移位;但是我不知道如何使用重载的移位运算符实现相同的逻辑:"sll"(左移逻辑(运算符。谢谢大家提供的任何帮助。

下面是如何使用 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输入。但是,sll 不会重std_logic_vector,因此您必须使用 unsignedsigned(unsigned在这里有意义(。不仅如此,这些类型的运算符在VHDL中做奇怪的事情。所以,如果我是你,我会坚持串联。

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

最后,根据合成器的能力,你可以得到 16 个人字拖而不是 8 个。这是因为您的变量将合成为 8 个触发器,而您的信号将合成另外 8 个触发器("在时钟过程中分配的每个信号都推断出一个触发器"(。然后,您在合成器上回复以优化其中的 8 个人字拖。

我可以为您提供这种方法来向左/向右移动或使用旋转(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 ;

最新更新