使用 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_vector
,sll
并未 过载 ,因此您必须使用 unsigned
或 signed
(unsigned
这里说得通)。不仅如此,这些类型的运算符在 VHDL 中做 strange things。所以,如果我是你,我会坚持连接。
此外,您对 q
的分配位置错误。当您执行顺序过程时,您不得分配给 if rising_edge
之外的信号,否则(在这种情况下)q
将在两个时钟边沿分配 - 不可综合的行为。
最后,根据您的合成器的能力,您可以获得 16 个触发器而不是 8 个。这是因为您的变量将合成为 8 个触发器,并且您的信号将合成为另外 8 个("every signal assigned in a clocked process infers a flip-flop").然后,您将回复您的合成器以优化其中的 8 个触发器。
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_vector
,sll
并未 过载 ,因此您必须使用 unsigned
或 signed
(unsigned
这里说得通)。不仅如此,这些类型的运算符在 VHDL 中做 strange things。所以,如果我是你,我会坚持连接。
此外,您对 q
的分配位置错误。当您执行顺序过程时,您不得分配给 if rising_edge
之外的信号,否则(在这种情况下)q
将在两个时钟边沿分配 - 不可综合的行为。
最后,根据您的合成器的能力,您可以获得 16 个触发器而不是 8 个。这是因为您的变量将合成为 8 个触发器,并且您的信号将合成为另外 8 个("every signal assigned in a clocked process infers a flip-flop").然后,您将回复您的合成器以优化其中的 8 个触发器。