Darky777 0 26 ноября, 2018 Опубликовано 26 ноября, 2018 (изменено) · Жалоба Привет всем! Есть такая задача: инициализировать память в верилоговских исходниках через функцию 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. Изменено 26 ноября, 2018 пользователем Darky777 дополнить Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 26 ноября, 2018 Опубликовано 26 ноября, 2018 · Жалоба Я брал инстанс из libguide, там для каждого варианта применения блочной памяти все расписано. И далее пример, в котором для блока параметров инициализации памяти, один для симуляции, второй - для синтеза. Эти блоки генерил самодельной программкой, не руками... Нет readmemh, нет путей к файлу инициализации. Все довольно компактно... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 26 ноября, 2018 Опубликовано 26 ноября, 2018 · Жалоба Приветствую! Вариант с $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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darky777 0 26 ноября, 2018 Опубликовано 26 ноября, 2018 · Жалоба 40 minutes ago, iosifk said: Я брал инстанс из libguide, там для каждого варианта применения блочной памяти все расписано. И далее пример, в котором для блока параметров инициализации памяти, один для симуляции, второй - для синтеза. Эти блоки генерил самодельной программкой, не руками... Нет readmemh, нет путей к файлу инициализации. Все довольно компактно... Если честно, не совсем понял решения.. Через инстанс примитива или самописный вериложный файл суть не меняется - нужно указать путь к файлу инициализации, будь то .hex или .mem. Речь же идет об этом документе? 37 minutes ago, RobFPGA said: IMHO - проще будет задавать базу для файлов в через глобальный `define BASE_DIR ... определяя его соответственно в ModelSim или в Vvivado относительно папки симуляции/компиляции в cmd параметрах. О дефайнах я не думал.. Надо попробовать. Если что-то получится - отпишу в этой теме Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 26 ноября, 2018 Опубликовано 26 ноября, 2018 · Жалоба 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), вот вместо нулей и пишите коды справо-налево... И никаких файлов инициализации после этого не нужно... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darky777 0 26 ноября, 2018 Опубликовано 26 ноября, 2018 · Жалоба 10 minutes ago, iosifk said: И никаких файлов инициализации после этого не нужно... Действительно, для этого нужно будет софт писать.. Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 26 ноября, 2018 Опубликовано 26 ноября, 2018 · Жалоба 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" совсем не сложно... И при таком подходе запускать что с сервера, что с рабочего компьютера - все равно. Здесь один блок инитов - для компиляции, второй для симуляции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Darky777 0 26 ноября, 2018 Опубликовано 26 ноября, 2018 · Жалоба 21 minutes ago, iosifk said: Вот кусок от старого проекта. Отлично, идею я понял. еще раз спасибо. Осталось еще разобраться, насколько это "переносимый" вариант для других семейств зайлинска. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
iosifk 3 26 ноября, 2018 Опубликовано 26 ноября, 2018 · Жалоба 12 минут назад, Darky777 сказал: Отлично, идею я понял. еще раз спасибо. Осталось еще разобраться, насколько это "переносимый" вариант для других семейств зайлинска. Так в либгайдах, где начинается описание инстанса, всегда давали табличку, в которой говорилось о том, в каких сериях этот инстанс присутствует и работает... Скачайте либгайды на эти серии и смотрите... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 26 ноября, 2018 Опубликовано 26 ноября, 2018 · Жалоба Приветствую! 9 minutes ago, Darky777 said: Отлично, идею я понял. еще раз спасибо. Осталось еще разобраться, насколько это "переносимый" вариант для других семейств зайлинска. Такая инициализация требует ручного разбиения большой памяти на примитивы - соответственно делать универсальное решение будет непросто. Хотя в отдельных случаях такое разбиение может позволит выжать последние "5 капель" памяти в забитом под завязку проекте. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexadmin 0 26 ноября, 2018 Опубликовано 26 ноября, 2018 · Жалоба Если уж инлайнить инициализацию вовнутрь файла, так лучше взять VHDL и там описать переменную-массив в явном виде. По-крайней мере не придется валять дурака с ручным разбиением памяти на примитивы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Doka 1 8 января, 2019 Опубликовано 8 января, 2019 · Жалоба поинтересуюсь у более опытных коллег: можно ли в описанном ТС кейсе применить мощь и красоту SV? ------------- PS: конкретно с предъинициализацией ОЗУ пока не сталкивался (для асика самое простое - обернуть простым FSM, которое по ресету инитит нужными значениями), а вот для ПЗУ в Vivado очень полюбилась конструкция: localparam bit [63:0] RNDC [0:255] = { 64'h0000000000000001, 64'h0000000000008082, 64'h800000000000808a, 64'h8000000080008000, ..... вместо создания на классическом верилог функции с громоздким case Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 27 8 января, 2019 Опубликовано 8 января, 2019 · Жалоба Приветствую! 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
egorman44 0 19 февраля, 2019 Опубликовано 19 февраля, 2019 · Жалоба А еще при особом желании и острой необходимости можно замутить переинициализацию вашей блочной памяти прямо в bit файл. Для этого надо найти географическое положении памяти после имплемента, вынуть его и положить в mmi файл , скормить все утилитке updatemem от Xilinx и радоваться жизни. ООоочень помогает если билд процесс длиться безобразно долгое количество времени. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Doka 1 20 февраля, 2019 Опубликовано 20 февраля, 2019 · Жалоба 15 hours ago, egorman44 said: географическое положении памяти после имплемента а как это можно реализовать автоматическим/полуавтоматическим способом Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться