Jump to content

    

Переменные окружения в Vivado и инициализация блочной памяти

Привет всем!

Есть такая задача: инициализировать память в верилоговских исходниках через функцию readmemh/readmemb в Vivado, причем так, чтобы файл грамотно подцеплялся не только в Vivado, но и в симуляции в QuestaSim/Modelsim.

module sdp_bram #(
  parameter    P_MEM_SIZE   = 16384                              ,
  parameter    P_DATA_SIZE  = 72                                 ,
  parameter    P_ADDR_WIDTH = 14                                 ,
  parameter    P_NBPIPE     = 1   ,// Number of pipeline Registers in BRAM P_NBPIPE =>1
  parameter    P_INIT_FILE  = ""
) (
  input                           clk   ,
  input                           wea   ,
  input                           rstb  ,
  input                           regceb, // Output Register Enable
  input                           mem_en, // Memory Enable
  input        [ P_DATA_SIZE-1:0] dina  ,
  input        [P_ADDR_WIDTH-1:0] addra ,
  input        [P_ADDR_WIDTH-1:0] addrb ,
  output logic [ P_DATA_SIZE-1:0] doutb
);

(* ram_style="block" *) logic [P_DATA_SIZE-1:0] mem [P_MEM_SIZE];
logic [P_DATA_SIZE-1:0] mem_reg;
logic [P_DATA_SIZE-1:0] mem_pipe [P_NBPIPE - 1:0];
logic mem_en_pipe_reg[P_NBPIPE:0];                // Pipelines for memory enable

generate
  if (P_INIT_FILE != "") begin: use_init_file
    initial
      $readmemh(P_INIT_FILE, mem, 0, P_MEM_SIZE-1);
  end else begin: init_bram_to_zero
    integer ram_index;
    initial
      for (ram_index = 0; ram_index < P_MEM_SIZE; ram_index = ram_index + 1)
        mem[ram_index] = {P_DATA_SIZE{1'b0}};
  end
endgenerate

....

 

Эта память - часть проекта, в котором участвует несколько человек. У всех разные операционки Linux Windows, разные пути до проектов.

У меня была идея: выцепить из вивадо какую-нибудь переменную окружения, сообщающая о расположении проекта и через относительный путь указывать файл данных для памяти. Основывалась она на том, что в файле проекта .xpr я встретил кучу вот таких строк:

      <File Path="$PPRDIR/../my_module.v">
        <FileInfo>
          <Attr Name="UsedIn" Val="synthesis"/>
          <Attr Name="UsedIn" Val="implementation"/>
          <Attr Name="UsedIn" Val="simulation"/>
        </FileInfo>
      </File>

Вивадо осознает, что она находится в какой-то директории.

Однако если в tcl консоль в виваде ввести :

puts "$PPRDIR"

то удачно идешь куда подальше он тебе сообщит, что такой переменной не объявлено.

Далее я расуждал так: Если где-то получить таки знание о переменной, а потом попробовать  проиниализировать память например вот так

parameter P_INIT_FILE = "$PPRDIR/../file.hex";
sdp_bram #(
           .P_MEM_SIZE(P_MEM_SIZE),
           .P_DATA_SIZE(P_DATA_SIZE), 
           .P_ADDR_WIDTH(P_ADDR_WIDTH), 
           .P_NBPIPE(P_NBPIPE),
           .P_INIT_FILE(P_INIT_FILE)
) i_sdp_bram (
        .clk   (clk  ),
        .rstb  (1'b0 ),
        .mem_en(1'b1 ),
        .wea   (wea  ),
        .regceb(reb  ),
        .dina  (dina ),
        .addra (addra),
        .addrb (addrb),
        .doutb (doutb)
      );

То должно сработать. По правде не говоря я не знаю, прокатило ли бы это.

 

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

 

Проще говоря, прошу вас поделиться опытом и идеями.

 

Гуглить пытался, но тщетно.

 

Vivado 2018.2.

Edited by Darky777
дополнить

Share this post


Link to post
Share on other sites

Я брал инстанс из libguide, там для каждого варианта применения блочной памяти все расписано. И далее пример, в котором для блока параметров инициализации памяти, один для симуляции, второй - для синтеза. Эти блоки генерил самодельной программкой, не руками... Нет readmemh, нет путей к файлу инициализации. Все довольно компактно...

Share this post


Link to post
Share on other sites

Приветствую!

Вариант с $PPRDIR/... не прокатит так как в верилог переменные из tcl напрямую не подставишь. 

IMHO - проще будет задавать базу для файлов в  через глобальный `define BASE_DIR ... определяя его соответственно в ModelSim или в Vvivado  относительно папки симуляции/компиляции  в  cmd параметрах.

Ну и учтите что для база для relative path разные для разных процессов (sim, synthesis и P&R) :( и это а не папка проекта 

Для syn  это папка .../project_name/project_name.runs/synth_N,  при P&R в Vivado  это папка .../project_name/project_name.runs/impl_N

что добавляет своей  "радости"  

Удачи! Rob.

Share this post


Link to post
Share on other sites
40 minutes ago, iosifk said:

Я брал инстанс из libguide, там для каждого варианта применения блочной памяти все расписано. И далее пример, в котором для блока параметров инициализации памяти, один для симуляции, второй - для синтеза. Эти блоки генерил самодельной программкой, не руками... Нет readmemh, нет путей к файлу инициализации. Все довольно компактно...

Если честно, не совсем понял решения.. Через инстанс примитива или самописный вериложный файл суть не меняется - нужно указать путь к файлу инициализации, будь то .hex или .mem. Речь же идет об этом документе?

37 minutes ago, RobFPGA said:

IMHO - проще будет задавать базу для файлов в  через глобальный `define BASE_DIR ... определяя его соответственно в ModelSim или в Vvivado  относительно папки симуляции/компиляции  в  cmd параметрах. 

О дефайнах я не думал.. Надо попробовать. Если что-то получится - отпишу в этой теме

Share this post


Link to post
Share on other sites
9 минут назад, Darky777 сказал:

Если честно, не совсем понял решения.. Через инстанс примитива или самописный вериложный файл суть не меняется - нужно указать путь к файлу инициализации, будь то .hex или .mem. Речь же идет об этом документе?

https://www.xilinx.com/support/documentation/sw_manuals/xilinx2012_2/ug953-vivado-7series-libraries.pdf

стр12 Verilog Instantiation Template и далее на стр.13 строки

.INIT_00(256'h0000000000000000000000000000000000000000000000000000000000000000), вот вместо нулей и пишите коды справо-налево... И никаких файлов инициализации после этого не нужно...

 

Share this post


Link to post
Share on other sites
10 minutes ago, iosifk said:

И никаких файлов инициализации после этого не нужно...

 

Действительно, для этого нужно будет софт писать..

Спасибо!

Share this post


Link to post
Share on other sites
11 минут назад, Darky777 сказал:

Действительно, для этого нужно будет софт писать..

Вот кусок от старого проекта.

// ROM starts here
RAMB16_S18 ROMA   
                 // program space                     
                       ( .WE (1'b0),                          
                                 .EN (ram_rd_ena),                    
                                 .SSR (1'b0),                                         // signal to command memory,   
                                 .CLK (clk),                                           // signal to memory,           
                                 .ADDR (ps_cnt[9:0]),                 
                     .DI (16'h00),                        
                     .DIP (2'b00),                        
                 .DOP (),                             
                 .DO (ps_data[31:16])                 
                 );


RAMB16_S18 ROMB                                      
                // program space                     
                       ( .WE (1'b0),                          
                                 .EN (ram_rd_ena),                    
                                 .SSR (1'b0),                                         // signal to command memory,  
                                 .CLK (clk),                                           // signal to memory,          
                                 .ADDR (ps_cnt[9:0]),                 
                     .DI (16'h00),                        
                     .DIP (2'b00),                        
                 .DOP (),                             
                 .DO (ps_data[15:0])                  
                 );


//    Date, Time - 15.11.2004 18:14:16
//    1K   word  2 x 1024 x 18
//    A - Hi  word
//    B - Low word
//
//synthesis attribute INIT_00 of ROMA is "80008000800080008000800080000000A8004304800000008000980000008000"
//synthesis attribute INIT_00 of ROMB is "017A00CB00AC0089002F007F029A000000090A00000100000006000B0000002F"
//synthesis attribute INIT_01 of ROMA is "0000000000000000000000000000800080008000800080008000800080008000"

...
//synthesis attribute INIT_29 of ROMB is "000000000808000000000000029F0000029400000298000A00000000FFFFFFFF"
//synthesis attribute INIT_2A of ROMA is "0000000000000000000000000000000000008000000090009800420D80004A10"
//synthesis attribute INIT_2A of ROMB is "00000000000000000000000000000000000002A30000000000040A050001080A"

//synthesis translate_off

defparam ROMA.INIT  = 18'h0;
defparam ROMA.SRVAL = 18'h0;
defparam ROMA.WRITE_MODE = "WRITE_FIRST";

defparam ROMB.INIT  = 18'h0;
defparam ROMB.SRVAL = 18'h0;
defparam ROMB.WRITE_MODE = "WRITE_FIRST";

defparam ROMA.INIT_00 = 256'h80008000800080008000800080000000A8004304800000008000980000008000;
defparam ROMB.INIT_00 = 256'h017A00CB00AC0089002F007F029A000000090A00000100000006000B0000002F;
.....

defparam ROMA.INIT_29 = 256'h000000004A10000000000000800000008000000080009800521100005129510C;
defparam ROMB.INIT_29 = 256'h000000000808000000000000029F0000029400000298000A00000000FFFFFFFF;
defparam ROMA.INIT_2A = 256'h0000000000000000000000000000000000008000000090009800420D80004A10;
defparam ROMB.INIT_2A = 256'h00000000000000000000000000000000000002A30000000000040A050001080A;

//synthesis translate_on
// ROM stops here
 

У меня был самодельный ассеблер, который в файле искал строку:

// ROM starts here

и потом до строки

// ROM stops here

врезал кусок описания памяти... Собственно собрать данные в строки и к ним добавить куски "defparam ROMA.INIT_29 = 256'h" совсем не сложно... И при таком подходе запускать что с сервера, что с рабочего  компьютера - все равно.

Здесь один блок инитов - для компиляции, второй для симуляции. 

Share this post


Link to post
Share on other sites
21 minutes ago, iosifk said:

Вот кусок от старого проекта.

Отлично, идею я понял. еще раз спасибо. Осталось еще разобраться, насколько это "переносимый" вариант для других семейств зайлинска.

Share this post


Link to post
Share on other sites
12 минут назад, Darky777 сказал:

Отлично, идею я понял. еще раз спасибо. Осталось еще разобраться, насколько это "переносимый" вариант для других семейств зайлинска.

Так в либгайдах, где начинается описание инстанса, всегда давали табличку, в которой говорилось о том, в каких сериях этот инстанс присутствует и работает...

Скачайте либгайды на эти серии и смотрите...

Share this post


Link to post
Share on other sites

Приветствую!

9 minutes ago, Darky777 said:

Отлично, идею я понял. еще раз спасибо. Осталось еще разобраться, насколько это "переносимый" вариант для других семейств зайлинска.

Такая инициализация требует ручного разбиения большой памяти на примитивы - соответственно делать универсальное решение будет непросто. Хотя в отдельных случаях такое разбиение может позволит выжать последние "5 капель" памяти в забитом под завязку проекте.

Удачи! Rob.

Share this post


Link to post
Share on other sites

Если уж инлайнить инициализацию вовнутрь файла, так лучше взять VHDL и там описать переменную-массив в явном виде. По-крайней мере не придется валять дурака с ручным разбиением памяти на примитивы.

Share this post


Link to post
Share on other sites

поинтересуюсь у более опытных коллег: можно ли в описанном ТС кейсе применить мощь и красоту SV?

 

 

-------------

PS:

конкретно с предъинициализацией ОЗУ пока не сталкивался (для асика самое простое - обернуть простым FSM, которое по ресету инитит нужными значениями),

а вот для ПЗУ в Vivado очень полюбилась конструкция:

localparam bit [63:0] RNDC [0:255] = {
    64'h0000000000000001,
    64'h0000000000008082,
    64'h800000000000808a,
    64'h8000000080008000,
    .....

вместо создания на классическом верилог функции с громоздким  case

 

 

Share this post


Link to post
Share on other sites

Приветствую!

2 hours ago, Doka said:

конкретно с предъинициализацией ОЗУ пока не сталкивался (для асика самое простое - обернуть простым FSM, которое по ресету инитит нужными значениями),

а вот для ПЗУ в Vivado очень полюбилась конструкция:


localparam bit [63:0] RNDC [0:255] = {
    64'h0000000000000001,
    64'h0000000000008082,
    64'h800000000000808a,
    64'h8000000080008000,
    .....

вместо создания на классическом верилог функции с громоздким  case

 

Увы задача описания и оптимальной инициализации блока памяти  чаще всего зависит от реализации этого в  конкретной среде (ISE, Vicado, ...), а не сколько от особенностей языка. Вопрос поднятый TC  затрагивает только проблемы среды разработки. Вбивать абсолютные пути нехорошо, а относительные пути требуют дополнительных телодвижений тазом - так как база для них разная в разных процессах и в разных IDE.

 

Инициализация же массива константами ROM в verilog возможна несколькими способами - как через case так и в цикле в блоках always или generate.  Все зависит от корректной поддержки  этих конструкций при синтезе.

Иногда прикольно получается - скорость синтеза может зависит от стиля описания констант в несколько раз. 

 

А вот с пред-инициализация RAM  при синтезе бывает засада - так как вызывать таск для инициализации из под initial не всегда возможно - не все синтезаторы поддерживают что то кроме readmem* в initial.  

Удачи! Rob.

 

Share this post


Link to post
Share on other sites

А еще при особом желании и острой необходимости можно замутить переинициализацию вашей блочной памяти прямо в bit файл. Для этого надо найти географическое положении памяти после имплемента, вынуть его и положить в mmi файл , скормить все утилитке updatemem от Xilinx и радоваться жизни. ООоочень помогает если билд процесс длиться безобразно долгое количество времени. 

Share this post


Link to post
Share on other sites
15 hours ago, egorman44 said:

географическое положении памяти после имплемента

а как это можно реализовать автоматическим/полуавтоматическим способом

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now