Сброс Preg среза Dsp в virtex 6 FPGA
Вот код VHDL, где я использовал DSP в качестве единицы MACC (умножение с накоплением) с использованием примитивов, которые доступны в языковых шаблонах. На каждом 7-м тактовом цикле я сбрасываю Preg, когда я делаю так, что умноженный выход этого цикла теряется. Как мне сбросить 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;
1 ответ
Давайте поместим мой комментарий в ответ.
Из вашего описания кажется, что вы не хотите сбрасывать регистр P. Вместо этого, кажется, вы хотите накапливать каждые 8 значений.
Если вы сбросите регистр, вы всегда получите эффект, который видите. Вместо этого вы хотите динамически изменить режим работы DSP:
- 1 цикл режима умножения
P_out = A*B (+0)
- 7 циклов режима MAC
P_out = A*B+P_in
Как показано в руководстве пользователя Xilinx DSP48E1, используемый вами OPMODE: "0100101"
из которых биты 6-4 важны для вашей цели (таблица 2-9). "010"
означает, что выход регистра P является входом для пост-сумматора. Вы хотите установить это "000"
установите вход на "ноль"(0).
Поэтому простым решением было бы изменить ваш код:
OPMODE => "0100101",
RSTP =>Reset_p
Для того, чтобы:
OPMODE => "0"¬(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;