Перейти к содержанию
    

Очистка RAM на SystemVerilog

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

Например, изначально я сделал трехмерную память с по-отчетной записью данных (в том числе и при очистке), при этом чтение происходит областями. Получилось что-то типа byte enabled simple dual port ram, но только отчет равен не байту, а другому заданному значению:

logic [DEEP_BACKET-1:0][WIDTH_RECORD-1:0] ram [0:N_BUCKET-1];

logic [$clog2(N_BUCKET*DEEP_BACKET)-1:0] clear_cnt;
logic clear_val;

always_ff@(posedge clk or posedge clear_table) begin
if (clear_table)
	clear_val <= 1'd1;
else if (clear_cnt == N_BUCKET*DEEP_BACKET - 1)
		clear_val <= 1'd0;
end

always_ff@(posedge clk) begin
if (clear_val)
	clear_cnt <= clear_cnt + 1'd1;
end

always_ff@(posedge clk) begin
if (clear_val) 
	ram[clear_cnt[$clog2(N_BUCKET)-1:0]][clear_cnt[$clog2(N_BUCKET*DEEP_BACKET)-1:$clog2(N_BUCKET)]] <= '0; 	
else
	begin 
	if(we) 
		begin
		ram[waddr][be] <= wdata;
		end
	q <= ram[raddr];
 	end
end

В данном случае Quartus все развел на блоках памяти.
Однако, в таком случае для полной очистки памяти требуется N_BUCKET*DEEP_BACKET тактов.
Чтобы снизить это время, я попытался разбить трехмерную память на несколько двумерных:

logic [$clog2(N_BUCKET)-1:0] clear_cnt;
logic clear_val;

always_ff@(posedge clk or posedge clear_table) begin
if (clear_table)
	clear_val <= 1'd1;
else if (clear_cnt == N_BUCKET - 1)
		clear_val <= 1'd0;
end

always_ff@(posedge clk) begin
if (clear_val)
	clear_cnt <= clear_cnt + 1'd1;
end

genvar i;
generate
for (i = 0; i < DEEP_BACKET; i++) begin: slice_table
	logic [WIDTH_RECORD-1:0] ram [0:N_BUCKET-1];

	always_ff@(posedge clk) begin
	if (clear_val)
		ram[clear_cnt] <= '0;
	else 
		begin
		if (we & be == i) 
			begin
			ram[waddr] <= wdata;
			end
		q[i*WIDTH_RECORD +: WIDTH_RECORD] <= ram[raddr];
 		end
	end

end: slice_table
endgenerate

Здесь очистка будет производится всего за N_BUCKET тактов.
Но Quartus развел все это дело на логике. Почему?
И в том и в другом случае, запись в каждый момент времени ведется только в один адрес.
Пересечения условий быть не может. Аналогично с чтением.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Советую использовать  IP  блоки или примитивы, если не хочется таскать файлы из проекта в проект. Всякие сюрпризы исключены.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 часов назад, DuHast сказал:

Советую использовать  IP  блоки или примитивы, если не хочется таскать файлы из проекта в проект. Всякие сюрпризы исключены.

Обычно я так и делаю, просто беру мегафункции Quartus.
Но в данном случае мне не хотелось бы ставить мультиплексоры на входе портов data и wraddr у модуля RAM. 
Да и просто возник интерес, по каким принципам Quartus определяет, что является памятью, а что нет? Мб какой документ есть, где это затрагивается?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

50 minutes ago, Perdachillo said:

Да и просто возник интерес, по каким принципам Quartus определяет, что является памятью, а что нет? Мб какой документ есть, где это затрагивается?

Recommended HDL Coding Styles в Quartus Handbook возможно поможет

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

21 час назад, Perdachillo сказал:


Пытаюсь реализовать очистку памяти путем последовательной записи во все ячейки нулей.

Однако, в таком случае для полной очистки памяти требуется N_BUCKET*DEEP_BACKET тактов.
Чтобы снизить это время, я попытался разбить трехмерную память на несколько двумерных:

Здесь очистка будет производится всего за N_BUCKET тактов.
 

Я довольно часто сталкивался с тем, что задавались "нестандартные" вопросы, которые и вызывали трудности. Но обычно все сводилось к тому, что не "вопрос" сложный, а "постановка задачи" не верная. Если не трудно, объясните зачем все это нужно. Ведь в рабочем режиме никакой "очистки" уже не требуется. Память обычно используется с дескрипторами, в которых можно прописать "условие" - очищено или нет. Ну и что касается числа тактов. А так ли важно, за сколько именно тактов пройдет инициализация всего устройства. Ну ведь наверняка есть и микроконтроллер. И пока в ПЛИС делается загрузка и инициализация, то и в микроконтроллере делается то же самое. А если есть хост, то и он не мгновенно включается в работу.

Вот я и хочу узнать, есть ли смысл биться лбом в "очистку"...

PS. Кстати, у блочной памяти есть еще биты, которые обычно используются как биты четности. Но ведь их же так же можно использовать и как тэги. Или один из блоков памяти приклеить к основной памяти и использовать как тэги. И если в него писать байтами, то в тегах бит "очищено-не очищено" будет читаться как бит. И весь процесс пойдет как минимум в 8 раз быстрее...  

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 минуты назад, iosifk сказал:

Вот я и хочу узнать, есть ли смысл биться лбом в "очистку"...

Необходимо сделать, что то типа таблицы коммутации, которую при изменении топологии сети требуется очищать. 

Таблицу я сделал на основе трёхмерного массива. Запись в неё, и соответственно чтение, производится по хэшу, который считается на основе MAC адреса. Как раз для обработки коллизий память и сделана трехмерной.

Другого варианта, как все это сделать я честно говоря не нашёл

 

40 минут назад, DimaG сказал:

Recommended HDL Coding Styles в Quartus Handbook возможно поможет

Спасибо, поищу там

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 минуты назад, Perdachillo сказал:

Необходимо сделать, что то типа таблицы коммутации, которую при изменении топологии сети требуется очищать. 

Таблицу я сделал на основе трёхмерного массива. Запись в неё, и соответственно чтение, производится по хэшу, который считается на основе MAC адреса. Как раз для обработки коллизий память и сделана трехмерной.

Так тем более, там же кроме адреса должны быть признаки валидности. Их то и надо сбрасывать. А сами данные при этом не важны. 

Но еще хочу добавить. Для поисковых таблиц используют обычно не RAM, а CAM... А вот в них и "очищать" ничего не нужно...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, iosifk сказал:

Так тем более, там же кроме адреса должны быть признаки валидности. Их то и надо сбрасывать. А сами данные при этом не важны. 

Но еще хочу добавить. Для поисковых таблиц используют обычно не RAM, а CAM... А вот в них и "очищать" ничего не нужно...

CAM у меня нет, к сожалению, есть только ПЛИС) 

Предположим я добавлю флаг валидности у записей в таблице. При изменении топологии мне придётся у всех записей снимать этот флаг? Чем тогда это в корне отличается от обычного обнуления? То есть в одном случае я получается один бит в ноль сбрасываю, а в другом все. Или я что то не понял? 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, Perdachillo сказал:

CAM у меня нет, к сожалению, есть только ПЛИС) 

CAM (Content-Addressable Memory) делается в ПЛИС.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 минут назад, andrew_b сказал:

CAM (Content-Addressable Memory) делается в ПЛИС.

Я думал имеется в виду готовое решение. А почему cam очищать не нужно? 

Предположим мне пришёл сигнал, который говорит, что топология изменилась данные о местоположение узлов в сети недействительны (в таблице) . А затем пришёл пакет с данными с определённым MAC адресом назначения. Моё устройство начинает адрес назначения искать в таблице и находит запись, но она  же недействительна и использовать её нельзя. 

Изменено пользователем Perdachillo

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

27 minutes ago, iosifk said:

... Для поисковых таблиц используют обычно не RAM, а CAM... А вот в них и "очищать" ничего не нужно...

:shok: Очень смелое утверждение, - то что очищать не нужно. Да и более-менее приличная CAM  обычно строится на RAM.

Нужно ли очищать, как  и что очищать  это обычно зависит от конкретного дизайна и требованиям к его функциональности. 

TC нужно аккуратно просмотреть стиль описания памяти. Увы  правильный синтез  памяти из описания в RTL требует соблюдения неких  паттернов  этого описания.  Синтезаторы   обычно пытаются выделить этот паттерн из  AST дерева в процессе синтеза. И если  этого не получается то лепят память как попало. Так что смотрите  как вам советовали Recommended HDL Coding Styles. 

Ну а если хотите делать переносимый код, не привязанный к конкретному вендору, то выносите память в собственные врапперы  где уже можете расписывать реализацию (RTL, примитивы и атрибуты синтеза) в зависимости от вендора и семейства FPGA 

Удачи! Rob.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только что, RobFPGA сказал:

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

:shok: Очень смелое утверждение, - то что очищать не нужно. Ведь более-менее приличная CAM  обычно строится на RAM.

Нужно ли очищать, как очищать и что это обычно зависит от конкретного дизайна и требованиям к его функциональности. 

TC нужно аккуратно просмотреть стиль описания памяти. Увы  правильный синтез  памяти из описания в RTL требует соблюдения неких  паттернов  этого описания.  Синтезаторы   обычно пытаются выделить этот паттерн из  AST дерева в процессе синтеза. И если  этого не получается то лепят память как попало. Так что смотрите  как вам советовали Recommended HDL Coding Styles. 

Ну а если хотите делать переносимый код, не привязанный к конкретному вендору, то выносите память в собственные врапперы  где уже можете расписывать реализацию (RTL, примитивы и атрибуты синтеза) в зависимости от вендора и семейства FPGA 

Удачи! Rob.

Хорошо, спасибо. Этим и займусь. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 минут назад, Perdachillo сказал:

Моё устройство начинает адрес назначения искать в таблице и находит запись, но она  же недействительна и использовать её нельзя. 

Видимо используется еще и метка времени, ведь свитч умеет определять "устаревание" и умеет делать "обучение"...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, iosifk сказал:

Видимо используется еще и метка времени, ведь свитч умеет определять "устаревание" и умеет делать "обучение"...

В любом случае, записи как то надо похерить, причём не одну конкретную, а все сразу

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 hours ago, Perdachillo said:

В любом случае, записи как то надо похерить, причём не одну конкретную, а все сразу

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...