|
Pipelined MAC, You can improve the performance of the multiplier by adding 2 register |
|
|
|
Jan 26 2015, 12:22
|
Местный
  
Группа: Свой
Сообщений: 310
Регистрация: 28-01-13
Из: Лондон
Пользователь №: 75 384

|
Делаю простенькое ALU на операции типа О=О+(А*В), О=С+(А*В) которое должно синтезироваться в Xilinxoвый DSP48. Код довольно стандартный, входящие сигналы и выходящий имеют по регистру. Синтезатор мне пишет: "Xst:2385 - HDL ADVISOR - You can improve the performance of the multiplier alu_module/Mmult_i_result_mult0000 by adding 2 register level(s)." Ну и скорость удручающая.. Где именно надо пихнуть эти регистры? А - это вход от BRAM, C-результат от предыдущего DSP48 блока, поэтому важна синхронная скорость BRAM и DSP48. Насколько я знаю, Xilinx специально делает эти блоки максимально совместимыми. Код library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity ALU is generic( MIN:integer:=-255; -- не всегда совпадает с 2**DATA_WIDTH MAX:integer:=255; DATA_WIDTH:integer:=9 ); Port ( RST : in STD_LOGIC; CLK : in STD_LOGIC; A : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); B : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); C : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); R : out STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); OPCODE : in STD_LOGIC_VECTOR (2 downto 0)); end ALU;
architecture Behavioral of ALU is signal i_result,i_rmul: signed(DATA_WIDTH*2-1 downto 0); signal i_A,i_B,i_C: STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); begin process (CLK,RST) begin if RST='1' then i_result<=(others=>'0'); i_rmul<=(others=>'0'); i_A<=(others=>'0'); i_B<=(others=>'0'); i_C<=(others=>'0'); else if (rising_edge(CLK)) then i_A<=A; i_B<=B; i_C<=C; case OPCODE is when "000" => --- R=0 i_result<=to_signed(0,DATA_WIDTH*2); i_rmul<=to_signed(0,DATA_WIDTH*2); when "001" => --- R=R+(A*B) i_rmul<=(signed(i_A)*signed(i_B)); i_result<=resize(i_result+i_rmul,DATA_WIDTH*2); when "010" => --- R=C+(A*B) i_rmul<=(signed(i_A)*signed(i_B)); i_result<=resize(signed(i_C)+i_rmul,DATA_WIDTH*2); when "011" => --- R=R+(A+B) i_rmul<=(signed(i_A)+signed(i_B)); i_result<=resize(i_result+i_rmul,DATA_WIDTH*2); when "100" => --- R=C+(A+B) i_rmul<=(signed(i_A)+signed(i_B)); i_result<=resize(signed(i_C)+i_rmul,DATA_WIDTH*2); when others => --- default do nothing i_result<=i_result; i_rmul<= i_rmul; end case; end if; end if;
if i_result<MIN then R <=std_logic_vector(to_signed(MIN,DATA_WIDTH)); elsif i_result>MAX then R <=std_logic_vector(to_signed(MAX,DATA_WIDTH)); else R<=std_logic_vector(i_result(DATA_WIDTH-1 downto 0)); end if;
end process; end Behavioral;
|
|
|
|
|
 |
Ответов
(1 - 7)
|
Jan 26 2015, 15:06
|
Местный
  
Группа: Свой
Сообщений: 310
Регистрация: 28-01-13
Из: Лондон
Пользователь №: 75 384

|
Подумал и решил что операция типа A+B+C мне не особо и нужна, а если очень надо то можно ее сконструировать из МАСов. Код -- -- Sequential Complex Multiplier -- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity alu_pipelined is generic(DATA_WIDTH:positive:=18; MAX:integer :=255; MIN:integer :=-255; RES_WIDTH:positive:=48); port( CLK:in std_logic; RST:in std_logic; A:in signed(DATA_WIDTH-1 downto 0); B:in signed(DATA_WIDTH-1 downto 0); C:in signed(DATA_WIDTH-1 downto 0); OPCODE:in std_logic_vector(1 downto 0); RES:out signed(DATA_WIDTH-1 downto 0) ); end alu_pipelined; architecture beh of alu_pipelined is constant P_WIDTH: integer:=DATA_WIDTH+DATA_WIDTH; signal oper_load0: std_logic:='0'; signal oper_addsub0: std_logic:='0'; signal p1: signed(P_WIDTH-1 downto 0):=(others=>'0'); signal oper_load1: std_logic:='0'; signal oper_addsub1: std_logic:='0'; signal res0, res1: signed(RES_WIDTH-1 downto 0); begin process (clk) variable acc: signed(RES_WIDTH-1 downto 0); begin if rising_edge(clk) then if RST='1' then acc:=(others=>'0'); res0<=(others=>'0'); p1<=(others=>'0'); else oper_load0<= OPCODE(1); oper_addsub0 <= OPCODE(0); p1 <= A*B; oper_load1<= oper_load0; oper_addsub1 <= oper_addsub0; if (oper_load1='1') then acc := res0; else acc := resize(signed(C),RES_WIDTH); end if; if (oper_addsub1='1') then res0 <= acc-p1; else res0 <= acc+p1; end if; end if; end if; if res0>MAX then res1<=to_signed(MAX,RES_WIDTH); elsif res0<MIN then res1<=to_signed(MIN,RES_WIDTH); else res1<=res0; end if; end process; RES <= resize(res1,DATA_WIDTH); end architecture;
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|