Jump to content

    
Sign in to follow this  
Perdachillo

Очистка RAM на SystemVerilog

Recommended Posts

Всем привет.
Пытаюсь реализовать очистку памяти путем последовательной записи во все ячейки нулей.
Возникли трудности в понимании того, чем руководствуется 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 развел все это дело на логике. Почему?
И в том и в другом случае, запись в каждый момент времени ведется только в один адрес.
Пересечения условий быть не может. Аналогично с чтением.

Share this post


Link to post
Share on other sites
16 часов назад, DuHast сказал:

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

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

Share this post


Link to post
Share on other sites
50 minutes ago, Perdachillo said:

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

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

Share this post


Link to post
Share on other sites
21 час назад, Perdachillo сказал:


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

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

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

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

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

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

Share this post


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

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

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

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

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

 

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

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

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

Share this post


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

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

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

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

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

Share this post


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

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

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

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

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

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

Share this post


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

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

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

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

Edited by Perdachillo

Share this post


Link to post
Share on other sites

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

27 minutes ago, iosifk said:

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

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

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

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

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

Удачи! Rob.

Share this post


Link to post
Share on other sites
Только что, RobFPGA сказал:

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

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

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

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

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

Удачи! Rob.

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

Share this post


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

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

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

Share this post


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

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

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

Share this post


Link to post
Share on other sites
3 hours ago, Perdachillo said:

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

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this