2013-10-24 1 views
0

Что такое правильный способ вывода ОЗУ с некоторыми неиспользуемыми более высокими адресами (с использованием блоков RAM)?
Используя приведенный ниже код (значения по умолчанию для дженерик, Xilinx синтезаторов и карты) я получаю ОЗУ размер такие же, как если бы глубина была установлен 2**ADDRWIDTH:Вывод BRAM с неиспользуемыми адресами эффективно

entity foo is 
    generic (
     DATAWIDTH : positive := 8; 
     DATADEPTH : positive := 5000; 
     ADDRWIDTH : positive := 13 
    ); 
    port (
     clk_a : in std_logic; 
     we_a : in std_logic; 
     addr_a : in std_logic_vector(ADDRWIDTH-1 downto 0); 
     di_a : in std_logic_vector(DATAWIDTH-1 downto 0); 
     do_a : out std_logic_vector(DATAWIDTH-1 downto 0) 
    ); 
end foo; 

architecture bar of foo is 
    type myram_type is array (DATADEPTH-1 downto 0) of std_logic_vector(DATAWIDTH-1 downto 0); --! type for ram content 
    shared variable myram : myram_type; --! ram 
begin 
    process (clk_a) 
    begin 
     if rising_edge(clk_a) then 
      if we_a = '1' then 
       myram(conv_integer(addr_a)) := di_a; 
      end if; 
      do_a <= myram(conv_integer(addr_a)); 
     end if; 
    end process; 
end bar; 

Например, я хочу RAM с DATAWIDTH = 8 и DATADEPTH = 5000 , поэтому адрес должен быть ADDRWIDTH = 13, потому что ADDRWIDTH = 12 разрешил бы только адреса 4096 RAM. Предположим, что один блок RAM-ресурса на моем FPGA может содержать 8192 бит. Если бы я закодировал это вручную, мне потребовалось 5000 * 8/8192, округленное вверх = 5 блоков памяти RAM. Однако с помощью кода, приведенного выше, синтез и карта Xilinx приводят к использованию 8-разрядных операционных ресурсов, потому что это то, что может быть адресовано адресами с 13-битным ширмом ...
Тем не менее, это не очень эффективное использование ресурсов с 3 из 8 блоков RAM никогда не будут использоваться.
Я попытался проверить, больше ли адрес на входе больше DATADEPTH, а затем назначить, не заботясь о данных, но это приводит к тому, что весь ПЗУ реализуется как распределенная RAM/LUTRAM.
Я пропустил что-то важное или мне нужно использовать один большой уродливый генератор для этого?

+0

Попробуйте использовать натуральный не SLV для типа адреса.Это может быть conv_integer (который в любом случае нестандартен), что заставляет синтезатор быть чрезмерно осторожным. –

+0

Причина, по которой я использую slv, заключается в том, что это часть смешанного проекта Verilog/VHDL. По соглашению мы не используем другие типы на интерфейсах, чем slv и integer, чтобы избежать проблем с печатанием. – damage

ответ

2

Принцип отдельной ширины адресной шины (ADDRWIDTH) и количество RAM записи (DATADEPTH) в порядке, и даст свободу синтеза инструмент для реализовать конструкцию без использования большего количества битов, чем RAM требуется.

Причина, по которой вы можете увидеть больше бит RAM, используемых, чем требуемый минимум, то, что инструмента синтеза может выбрать реализацию, которая использует больше внутренней память примитивов, чем абсолютный минимум, который, как правило, происходит, если есть много свободных примитивов RAM или если это необходимо для закрытия синхронизации.

Если попробовать поэкспериментировать с настройками DATAWIDTH, DATADEPTH и ADDRWIDTH, вы увидите, что инструмент синтеза действительно используется меньше внутренних RAM примитивы, чем простое округление DATADEPTH к новым 2 ** N потребуется .

Использование DATAWIDTH = 72, DATADEPTH = 17 * 1024 и ADDRWIDTH = 16 требует минимум 72 * 17 Kib = 1224 Kib. В одном эксперименте по синтезу это может вписываться в 76 RAMB16 Spartan6, таким образом, общее количество 76 * 18 Kib = 1368 Kib. Ниже приведен синтез из .

enter image description here

Если DATADEPTH была округлена до ближайшего 2 * краевым было бы 32 * 1024, таким образом требует 72 * 32 = 2304 KiB KiB. Таким образом, инструмент синтеза Xilinx делает интеллектуальную посадку .

Кстати, тогда сигнал должен использоваться для ОЗУ, а не для общей переменной , так как я ожидаю, что общая переменная может вызвать проблемы в некотором синтезе .

Предложение для кода, включая использование положений:

library ieee; 
use ieee.std_logic_1164.all; 

entity foo is 
    generic (
    DATAWIDTH : positive := 72; 
    DATADEPTH : positive := 17 * 1024; 
    ADDRWIDTH : positive := 16 
    ); 
    port (
    clk_a : in std_logic; 
    we_a : in std_logic; 
    addr_a : in std_logic_vector(ADDRWIDTH-1 downto 0); 
    di_a : in std_logic_vector(DATAWIDTH-1 downto 0); 
    do_a : out std_logic_vector(DATAWIDTH-1 downto 0) 
    ); 
end foo; 

library ieee; 
use ieee.std_logic_unsigned.all; 

architecture bar of foo is 
    type myram_type is array (DATADEPTH-1 downto 0) of std_logic_vector(DATAWIDTH-1 downto 0); --! type for ram content 
    signal myram : myram_type;                 --! ram 
begin 
    process (clk_a) 
    begin 
    if rising_edge(clk_a) then 
     if we_a = '1' then 
     myram(conv_integer(addr_a)) <= di_a; 
     end if; 
     do_a <= myram(conv_integer(addr_a)); 
    end if; 
    end process; 
end bar; 
+0

Спасибо, что поделились своими наблюдениями и предлагаемым кодом! Я сделаю это как можно скорее. – damage

Смежные вопросы