在 Virtex 6 FPGA 中重置 Dsp 切片的 Preg

Resetting Preg of Dsp slice in virtex 6 FPGA

这是 VHDL 代码,其中我使用语言模板中可用的原语将 DSP 用作 MACC 单元(乘法累加)。在每第 7 个时钟周期,我重置 Preg,当我这样做时,该周期的乘法输出是 lost.How 我是否重置 Preg 而不会丢失任何数据?

附上输出波形截图。

--------------------------------代码------------ --------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


library UNISIM;
use UNISIM.VComponents.all;

use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity dsp12 is
    Port ( clk1 : in  STD_LOGIC;
           a_in1 : in  STD_LOGIC_vector(29 downto 0);
           b_in1 : in  STD_LOGIC_vector(17 downto 0);
           p_out : out  STD_LOGIC_vector(47 downto 0);
              reset_p: inout  std_logic;
              count :inout std_logic_vector(3 downto 0):="0000"
);
end dsp12;

architecture Behavioral of dsp12 is
signal reset: std_logic:='0';

begin
dsp1: DSP48E1

generic map(

-- Feature Control Attributes: Data Path Selection
A_INPUT => "DIRECT", 
B_INPUT => "DIRECT", 
USE_DPORT => FALSE, 
USE_MULT => "MULTIPLY",


AUTORESET_PATDET => "NO_RESET", 
MASK => X"ffffffffffff" , 
PATTERN => X"000000000000", 
SEL_MASK => "MASK", 
SEL_PATTERN => "PATTERN", 
USE_PATTERN_DETECT => "NO_PATDET", 


ACASCREG => 1, 
ADREG => 0,
ALUMODEREG => 1, 
AREG => 1,
BCASCREG => 1,
BREG => 1,
CARRYINREG => 1, 
CARRYINSELREG => 1, 
CREG =>0, 
DREG => 0, 
INMODEREG => 1, 
MREG => 1,
OPMODEREG => 1, 
PREG => 1, 
USE_SIMD => "ONE48" 
)


port map (


ACOUT =>open ,--ACOUT(i) ,
BCOUT =>open,--1,--BCOUT(i) , 
CARRYCASCOUT => open, 
MULTSIGNOUT => open,
PCOUT => open , 


OVERFLOW => open, 
PATTERNBDETECT => open, 
PATTERNDETECT => open, 
UNDERFLOW => open, 

-- Data: 4-bit (each) Data Ports
CARRYOUT => open, 
P => P_out,--P(i) , 

-- Cascade: 30-bit (each) Cascade Ports
ACIN =>"000000000000000000000000000000",
BCIN =>"000000000000000000", 
CARRYCASCIN => '0', 
MULTSIGNIN => '0', 
PCIN => X"000000000000" ,

-- Control: 4-bit (each) Control Inputs/Status Bits
ALUMODE => "0000", 
CARRYINSEL => "000", 
CEINMODE => '0', 
CLK => clk1, 
INMODE => "00000", 
OPMODE => "0100101", 
RSTINMODE => '0', 

-- Data: 30-bit (each) Data Ports
A => A_in1,
B => B_in1,
C => X"000000000000", 
CARRYIN => '0',
D => "0000000000000000000000000", 

-- Reset/Clock Enable: 1-bit (each) Reset/Clock Enable Inputs
CEA1 => '1', 
CEA2 => '1',
CEAD =>'0',
CEALUMODE => '1',
CEB1 => '1', 
CEB2 => '1', 
CEC => '0', 
CECARRYIN => '1',
CECTRL => '1',
CED =>'0' ,
CEM => '1', 
CEP => '1', 
RSTA => Reset, 
RSTALLCARRYIN => Reset, 
RSTALUMODE => Reset, 
RSTB => Reset,
RSTC => Reset,
RSTCTRL => Reset, 
RSTD =>Reset, 
RSTM =>Reset,
RSTP =>Reset_p
);


process(clk1)
begin

if clk1' event and clk1='1' then
count<=count+"0001";


if count(2 downto 0)="111" then
reset_p<='1';
else reset_p<='0';
end if;
end if;
end process;

end Behavioral;

让我们把我的评论变成一个答案。

从你的描述来看,你似乎不想重置寄存器P。相反,你似乎想每8个值累加一次。

如果您重置寄存器,您将始终获得您所看到的效果。相反,您想将 DSP 的操作模式动态更改为:

  • 乘法模式的 1 个周期 P_out = A*B (+0)
  • MAC 模式的 7 个周期P_out = A*B+P_in

Xilinx DSP48E1 user guide所示,您现在使用的OPMODE是"0100101",其中第6-4位对您的目的很重要(table 2-9)。 "010" 表示寄存器 P 的输出是 post-加法器的输入。您想将其设置为 "000",将输入设置为 "zero"(0).

因此,一个简单的解决方案是修改您的代码:

OPMODE => "0100101", 
RSTP =>Reset_p

收件人:

OPMODE => "0"&not(Reset_p)&"00101", 
RSTP =>Reset

但你或许可以清理它。


不同的解决方案

除了将 DSP 实例化为组件,您还可以进行 RTL 描述。综合工具将理解这一点并生成您的 MAC。示例:这是一个 VHDL-2008 描述。会合成。

library ieee;
use ieee.std_logic_1164.all;

entity Accumulate8 is
    port(
        clk : in std_logic;
        rst : in std_logic;
        A : in std_logic_vector(29 downto 0);
        B : in std_logic_vector(17 downto 0);
        P : out std_logic_vector(47 downto 0)
    );
end entity;

architecture rtl of Accumulate8 is
    signal count : integer range 0 to 7 := 7;
    use ieee.numeric_std.all;
begin
    mac: process(clk)
    begin
        if rising_edge(clk) then
            if count = 0 then
                count <= 7;
                P <= std_logic_vector(unsigned(A)*unsigned(B));
            else
                count <= count - 1;
                P <= std_logic_vector(unsigned(A)*unsigned(B)+unsigned(P));
            end if;
            if rst = '1' then
                count <= 7;
                P <= (others => '0');
            end if;
        end if;
    end process;
end architecture;

测试台

entity Accumulate8_tb is end entity;

library ieee;

architecture rtl of Accumulate8_tb is
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    signal clk : std_logic;
    signal rst : std_logic;
    signal A : unsigned(29 downto 0) := (others => '0');
    signal B : unsigned(17 downto 0) := (others => '0');
    signal P : std_logic_vector(47 downto 0);
begin

    clk_proc: process begin
        clk <= '0', '1' after 1 ns;
        wait for 2 ns;
    end process;

    rst_proc: process begin
        rst <= '1';
        wait for 4 ns;
        rst <= '0';
        wait;
    end process;

    cnt_proc : process(clk) begin
        if rising_edge(clk) then
            A <= A + 3;
            B <= B + 7;
        end if;
    end process;

    DUT: entity work.Accumulate8
        port map(
            clk => clk,
            rst => rst,
            A => std_logic_vector(A),
            B => std_logic_vector(B),
            P => P
        );
end architecture;