2016-08-18 2 views
0

VHDL에 2 차원 블록 램을 추측하려고합니다. 그러나 정교한 회로는 레지스터와 MUX의 회로로 밝혀졌습니다. 램에 관한 코드의 주요 파일은 다음과 같습니다 사용하는 정수를 포함한자일링스 비바도 VHDL에 2 차원 블록 RAM을 추론

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 
use work.shared_resources.all; 

entity weight_ram is 
    port (clk : in std_logic; 
      write_enable : in std_logic; 
      row_addr : in natural range 0 to max_NR-1; 
      data_in : in neuron_weight_array; 
      data_out : out neuron_weight_array); 
end weight_ram; 

architecture rtl of weight_ram is 
    signal ram : weight_ram_array; 
begin 
    ram_process : process (clk) 
     variable f : integer; 
    begin 
     if (rising_edge (clk)) then 
      if (write_enable = '1') then 
       for f in 0 to n_feature-1 loop 
        ram (row_addr, f) <= data_in (f); 
       end loop; 
      end if; 
      for f in 0 to n_feature-1 loop 
       data_out (f) <= ram (row_addr, f); 
      end loop; 
     end if; 
    end process; 
end rtl; 

파일은 다음과 같습니다

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 

package shared_resources is 
    constant n_feature : integer := 24; 
    constant max_NR : integer := 10; -- maximum number of neurons allowed 
    constant weightw : integer := 10; -- width of the weight (1:0:9) 

    subtype weight_type is signed (weightw-1 downto 0); 
    type neuron_weight_array is array (0 to n_feature-1) of weight_type; 
    type weight_ram_array is array (0 to max_NR-1, 0 to n_feature-1) of weight_type; 
end shared_resources; 

어떻게 코드 블록 RAM으로 추정됩니다 보장 할 수 있는가?

업데이트 : morten zilmer의 답변에 따라 2 차원 배열에서 단일 요소를 읽도록 코드가 업데이트되었습니다. 그러나 여전히 블록 RAM으로 추측되지는 않습니다. 블록 RAM에 액세스 할 때

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 
use work.shared_resources.all; 

entity weight_ram is 
    port (clk : in std_logic; 
      write_enable : in std_logic; 
      row_addr : in natural range 0 to max_NR-1; 
      col_addr : in natural range 0 to n_feature-1; 
      data_in : in weight_type; 
      data_out : out weight_type); 
end weight_ram; 

architecture rtl of weight_ram is 
    signal ram : weight_ram_array; 
begin 
    ram_process : process (clk) 
     variable f : integer; 
    begin 
     if (rising_edge (clk)) then 
      if (write_enable = '1') then 
       ram (row_addr, col_addr) <= data_in; 
      end if; 
      data_out <= ram (row_addr, col_addr); 
     end if; 
    end process; 
end rtl; 
+0

. RAM 추론은 까다 롭습니다. 공급 업체 템플릿을 완벽하게 따르지 않으면 신디사이저가 원하는대로 작동 할 가능성이 거의 없습니다. –

답변

0

후 각 클록 번의 주소 데이터 워드의 판독을 가능하게하고, 각 클록은 단일 어드레스에서 데이터 워드의 기록을 허용한다.

제공되는 디자인에서 모든 위치는 각 클럭에서 읽혀지며 write_enable = '1'이면 모든 위치가 각 클록에 기록됩니다.

따라서 디자인은 블록 RAM을 구현하지 않으므로이 도구는 블록 RAM을 사용할 수 없습니다.

+0

RAM의 단일 요소를 읽으려고해도 회로는 블록 RAM으로 추측되지 않습니다. 위 질문에 업데이트 된 회로를 추가했습니다. – user3575732

+0

이 도구는 제한에 따라 최적화를 허용하므로 블록 RAM 또는 분산 FF와 mux를 사용하여 디자인을 구현할 자유가 있습니다. 어떤 이유로 블록 RAM을 원한다면 직접 인스턴스를 생성하십시오. –

0

FPGA에서 특정 하드웨어를 추정하려는 경우 사용중인 모든 장치 및/또는 툴 체인의 합성 사용자 가이드를 보는 것이 가장 좋습니다. Vivado의 경우 "Vivado Design Suite 사용자 가이드 : 합성 (UG901)"입니다. Vivado의 새 버전이있을 때마다 URL이 변경되므로 여기에 링크하지 않지만 the Xilinx web site으로 이동하여 UG901을 검색하면 최신 버전이 최고의 결과 여야합니다.

이 문서 (또는 Xilinx ISE, Altera Quartus 등의 해당 문서)에는 다양한 FPGA 요소를 추론하는 방법에 대한 예제가있는 섹션이 있으며이를 "추론 템플릿"이라고합니다. 이 경우 3 장에는 "RAM HDL 코딩 지침"섹션이 있으며 "단일 포트 블록 RAM"이라는 요구 사항을 비롯하여 다양한 RAM 스타일을 추정하는 모든 방법의 예가 있습니다.

내가 추론 템플릿 중 일부에 대해 말하고자하는 한 가지는 그들이 ieee.numeric_std.all을 사용하지 않는다는 것입니다. conv_integer과 같은 '이전'스타일 함수를 사용하는 경우 문제없이 해당 numeric_std 개 (즉, to_integer)를 사용할 수 있습니다.

2 차원 배열로 다시 돌아 오면 너비가 10 인 메모리에 쓸 때 행 번호와 열 번호를 연결하여 하나의 주소를 구성하고 address <= column & row 행을 따라이 값을 관리해야합니다.

다른주의 사항은 메모리 깊이가 작은 경우 도구가 자동으로 추정 된 블록 RAM을 분산 RAM으로 변환 할 수 있다는 것입니다. 내 경험에 따르면 도구가이를 수행하는 경우 최상의 결과를 얻었지만 Vivado의 "정교한 디자인"을 열고 설계도를 살펴봄으로써 적어도 '메모리 블록'이 추측 된 것을 쉽게 확인할 수 있습니다 . 이 안에는 확장 할 수없는 단일 블록으로 그려진 메모리를 찾을 수 있어야합니다. 메모리 깊이에 따라 합성 중에 분산 또는 블록 RAM을 사용할 수 있습니다.

0

이는 :

subtype weight_type is signed (weightw-1 downto 0); 
type weight_ram_array is array (0 to max_NR-1, 0 to n_feature-1) of weight_type; 

자일링스 장치에 BRAM으로 합성되지 않는다."BRAM에 매핑되지 않습니다. 너무 희박합니다" 또는 그와 비슷한 메시지가 표시된다고 가정합니다. 그러나, 당신이 할 수있는 작은 트릭이 있습니다. 당신이 당신의 주소 계산에 별도의 row_addrcol_addr을 사용하고자하는 경우에 당신은 당신의 기억을 변경하고 같은 주소를 연결할 수 있습니다 :

architecture rtl of weight_ram is 

type my_weight_type_array is array(0 to max_NR*n_feature-1) of weight_type; 
signal ram : my_weight_type_array; 

signal row_and_col : natural range 0 to max_NR*n_feature-1 ; 

begin 
    row_and_col <= to_integer(to_unsigned(row_addr,4) & to_unsigned(col_addr,5));                              

    ram_process : process (clk) 
     variable f : integer; 
    begin 
     if (rising_edge (clk)) then 
      if (write_enable = '1') then 
       ram (row_and_col) <= data_in; 
      end if; 
      data_out <= ram (row_and_col); 
     end if; 
    end process; 
end rtl; 

참고 : 나는 지난 5 년 정도 VHDL에 아무것도 작성하지 않은 당신은 그것을 시뮬레이트하고 그것이 올바르게 작동하는지 확인해야합니다. 특히이 부분 :

row_and_col <= to_integer(to_unsigned(row_addr,4) & to_unsigned(col_addr,5)); 

Ekhm ... 강력하게 형식화 된 언어 ... 당신은 아마 한 차원 배열을 사용하려고한다

+0

'row_and_col <= ((2 ** 5) * row_addr) + col_addr;은 어떨까요? 내가 보는 유형 변환의 대부분의 긴 사슬은 쉽게 피할 수 있습니다. –

+0

@scary_jeff 네,이 일을해야합니다. –

관련 문제