Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: M9K Altera не записывает некоторые данные
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
Golikov A.
Всем привет!

Надо было сделать параметризуемую память, собираемую из банков М9К циклона. Сделали через altsyncram

CODE
altsyncram #(
.operation_mode ("BIDIR_DUAL_PORT"),
.width_a (DATA_WIDTH_A),
.width_byteena_a (DATA_WIDTH_A / BYTE_SIZE),
.width_b (DATA_WIDTH_B),
.widthad_a (ADDR_WIDTH_A),
.widthad_b (ADDR_WIDTH_B),
.numwords_a (2**ADDR_WIDTH_A),
.numwords_b (2**ADDR_WIDTH_B),
.outdata_reg_a ("UNREGISTERED"),
.outdata_reg_b ("UNREGISTERED"),
.ram_block_type ("M9K"),
.intended_device_family ("Cyclone IV E"),
.lpm_type ("altsyncram"),
.read_during_write_mode_mixed_ports ("DONT_CARE")
)
altsyncram_inst (
.address_a (addra),
.clock0 (clka),
.clocken0 (1'b1),
.data_a (dina),
.wren_a (wea),
.byteena_a (true_bea),
.q_a (douta) ,

.address_b (addrb),
.clock1 (clkb),
.clocken1 (1'b1),
.data_b (dinb),
.wren_b (true_web),
.q_b (doutb)
);


На тестах вот какая штука вылезла, если писать по порту А и читать по порту В все ОК, как это не делай.
Если писать по порту В удерживая врайт енайбл и каждый такт выдавая новые данные, а читать это по порту А, то же все хорошо.
Если писать по порту В, выдавая сигнал данные и адрес на 1 такт, а потом 2 такта пауза, то каждые вторые данные не записываются в память.
То есть в 0, 2, 4, 6, ... ячейки данные сохраняются а в 1, 3, 5, остаются старыми...

И в чем прикол я так и не понял... есть у кого какие мысли?

Повторили опыт с памятью генерированной мегавизордом, таже фигня,
Если до 1 клокового врайтенайбла за такт выставить данные и адрес, запись пройдет, и это только по порту В
DuHast
Метастабильность?
Уверен, что если, для теста, будете писать и читать одним клоком, то всё будет Ок.
У меня была похожая проблема, с FIFO, но там Мегавизард предлагал улучшить исполнение за счёт увеличения используемых элементов, что и помогло.
Тригеров, что ли напихайте до и после памяти sm.gif

Нет, с метастабильностью я погорячился. В RAM, в отличии от FIFO, клоковые домены чётко разделены. Но тест с одним клоком я бы всё равно провёл.
Golikov A.
клок один (входа 2 подано одно и тоже), запись и чтение четко разделены сначала много пишем, потом много читаем.
Если выставить адрес, а в след клоке дернуть на 1 такт WE запись проходит. Если в одном такте это сделать запись проходит только в четные адреса.
Был вариант когда писалась память почти вся кроме 1 ячейки, то есть 0 и 2,3,4,5.... писались, а 1 пропускалась.

Если WE стоит, а данные и адрес меняются каждый такт все записывается нормально...

Есть серъезное подозрение на ошибку симулятора или модели памяти. Хотя и какое-то упущение в доках тоже возможно.
По докам память должна быть из 2 плиток (тру дуал порт 32 бита), и вроде альт синк рам это и должен сам сделать... но в техноложик вью на нижнем уровне просто 32 квадратика, и фиг его знает сколько это плиток...
DuHast
Цитата(Golikov A. @ Oct 9 2015, 22:37) *
Есть серъезное подозрение на ошибку симулятора или модели памяти.

Так у Вас проблема при симуляции. А можно посмотреть, как Вы формируете входные сигналы для памяти.
Golikov A.
Да проблема на симуляции, сейчас в железе трудно достоверно проверить, но не думаю что альтеровская мегафункция сделанная через визард будет так себя вести в железе.

тестбенч вот такой


CODE
module Mem4KTest;

// Inputs
reg clka;
reg wea;
reg [3:0] bea;
reg [10:0] addra;
reg [31:0] dina;
reg clkb;
reg web;
reg [10:0] addrb;
reg [31:0] dinb;

// Outputs
wire [31:0] douta;
wire [31:0] doutb;

// Instantiate the Unit Under Test (UUT)
TestMem_4K
uut (
.clka(clka),
.wea(wea),
.bea(bea),
.addra(addra),
.dina(dina),
.douta(douta),
.clkb(clkb),
.web(web),
.addrb(addrb),
.dinb(dinb),
.doutb(doutb)
);

initial begin
// Initialize Inputs
clka = 0;
clkb = 0;

// Wait 100 ns for global reset to finish
#103;

// Add stimulus here
forever begin
clka = ~clka;
clkb = ~clkb;
#1;
#4;
end

end


integer i;
integer Correct;
integer InCorrect;

initial begin
// Initialize Inputs
wea = 0;
bea = 0;
addra = 0;
dina = 0;
web = 0;
addrb = 0;
dinb = 0;

// Wait 100 ns for global reset to finish
#100;

// Add stimulus here

bea = 4'b1111;

$display("Start write");

for(i = 0; i < 2048; i = i + 1)
begin
@(posedge clka)
begin
addra = i;
dina = i;
wea = 1;
end
@(posedge clka)
wea = 0;
@(posedge clka);
@(posedge clka);
end

@(posedge clka)
wea = 0;

$display("Start Read");


Correct = 0;
InCorrect = 0;

for(i = 0; i < 2049; i = i + 1)
begin
@(posedge clkb)
begin
if(i < 2048)
addrb = i;
#2;
if(i >= 1)
begin
if(doutb != (i-1))
begin
$display("Error %d: write %d - read %d", i , (i-1), doutb);
InCorrect = InCorrect + 1;
end
else
Correct = Correct + 1;
end
end
end



$display("Part 1, Correct %d - InCorrect %d", Correct, InCorrect);



$display("Start write");

for(i = 0; i < 2048; i = i + 1)
begin
@(posedge clkb)
begin
addrb = i;
dinb = 100*i;
@(posedge clkb)
//#2;
web = 1;
end
@(posedge clkb)
begin
//#2;
web = 0;
end
@(posedge clkb);
@(posedge clkb);
end

@(posedge clkb)
web = 0;

$display("Start Read");

Correct = 0;
InCorrect = 0;

for(i = 0; i < 2049; i = i + 1)
begin
@(posedge clka)
begin
if(i < 2048)
addra = i;
#2;
if(i >= 1)
begin
if(douta != 100*(i-1))
begin
$display("Error %d: write %d - read %d", i , 100*(i-1), douta);
InCorrect = InCorrect + 1;
end
else
Correct = Correct + 1;
end
end
end

$display("Part 2, Correct %d - InCorrect %d", Correct, InCorrect);

end


endmodule


в таком виде он работает


вот этот кусок

Код
for(i = 0; i < 2048; i = i + 1)
         begin
            @(posedge clkb)
               begin
                  addrb = i;
                  dinb = 100*i;
                  @(posedge clkb)                    -  если убрать этот такт задержки, пишутся только четные адреса, но только для порта B, для А работает и так и сяк
                  web = 1;
               end
            @(posedge clkb)
               begin
                  //#2;                                    - эта задержка не влияет
                  web = 0;
               end  
            @(posedge clkb);
            @(posedge clkb);                
         end
Golikov A.
В общем и целом наблюдаем следующую вещь

Берем 2 памяти, соединяем их портами В, и делаем перекидку всей памяти из 1 в другую и обратно по команде, прямо внутри блока железный конечный автомат который сливает. При этом делает это 1 тактовыми стробами по we.

Пишем в 1 память по порту А из симулятора.
Запускаем перекидку из 1 во 2.
Читаем из 2 памяти по порту А через симулятор.
и обратно
Пишем во 2 память по порту А из симулятора.
Запускаем перекидку из 2 в 1.
Читаем из 1 памяти по порту А через симулятор.

Данные совпадают, запись опять однотактовыми стробами WE


Теперь делаем все тоже самое, но соединяем памяти портами А-В, то есть для 2 памяти через симулятор будет идти запись уже в порт В.
и первый тест
Пишем в 1 память по порту А из симулятора.
Запускаем перекидку из 1 во 2.
Читаем из 2 памяти по порту В через симулятор.

проходит, а обратный

Пишем во 2 память по порту В из симулятора.
Запускаем перекидку из 2 в 1.
Читаем из 1 памяти по порту А через симулятор.

Провал, опять каждая 2 запись не проходит. Изменяем процесс записи в порт В с 1 тактовых стробов на 2 тактовые, и опять все работает...


То есть получается симулятор не может писать 1 тактовыми стробами по порту В памяти, ну что за бред то? Даже можно 1 тактовыми, но чтобы строб был в след такте после выставления адреса
warrior-2001
А что за симулятор? Сдается мне, что наблюдается асинхронный процесс у тестового окружения. Проще говоря микротакты ТБ некорректно отрабатываются.
Зачем "#2;" внутри синхронный воздействий?
Golikov A.
Симулятор был квеста, пробовали что за зверь
Модел сим альтера попробовали - отработал все корректно.
Цитата
Зачем "#2;" внутри синхронный воздействий?

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

почему то значение которое должно было появиться по фронту при @(posedge clk) считывалось с прошлого такта, и только после #2 стало новым.....

Думаю скорее всего мы что-то не так настроили, или даже не настроили... что все идет не так как хочется это очевидно.... а вот как поправить хз
warrior-2001
Если квеста - то принт в консоли вас спасет. В первый раз, когда такое наблюдал - обклеил все $display и $info. Нашел что и когда срабатывает, потом почитал теорию и понял, отчего именно так. Тогда стало ясно что править. И ещё - timescale какой установлен?
Golikov A.
принт в консоли ничего особенного не пишет. Модуль 100% рабочий, ну не будет же корка мегавизардом сделанная лажать? Да и моделсим-альтера правильно отработал.
Сто пудово что-то в квесте не нстроили... вот что в info писать не понятно, на что смотреть?

timescale - что-то мне говорит что должен быть порядка 1ps, как убедиться что квеста на таком работает?

Golikov A.
---
upd нашел странный варнинг в консоли
Цитата
Port type is incompatible with connection (port 'wren_b').

и что это значит? ссылается на несуществующую строку. при этом именно с портом б проблемы, ругается на 4 блока памяти моих, на блок из визарда не ругается, но он тоже не работает...
Golikov A.
на что ругается понятно, Questa не осилила wand с подключаемыми сигналами по генерайту, переписал на wire, ситуация не изменилась.
warrior-2001
Цитата(Golikov A. @ Oct 13 2015, 09:48) *
принт в консоли ничего особенного не пишет. Модуль 100% рабочий, ну не будет же корка мегавизардом сделанная лажать? Да и моделсим-альтера правильно отработал.
Сто пудово что-то в квесте не нстроили... вот что в info писать не понятно, на что смотреть?

timescale - что-то мне говорит что должен быть порядка 1ps, как убедиться что квеста на таком работает?


Прописать для квесты timescale в 1 пс должен пользователь.
Смотреть - на последовательность выполнения команд в ТБ. После каждой строки ТБ ставите и смотрите что и когда и в каком порядке отработало. Явно сперва скушался клок, а потом WR_en. Или что-то в этом роде.
В своих ТБ в части драйверов по взаимодействию с синхронными интерфейсами ПЛИС давно перешли на синхронный режим по клоку.
Golikov A.
прописал в настройках квартуса, в части симулятора, для VHDL был зажат на 100 ps, сказал делать верилог выходным файлом и поставил 1 ps
прописал `timesacle 1ns / 1ps в файле тестбенча

писать по порту B все так же нельзя...


Код
@(posedge clkb)
      begin
         addrb = i;
         dinb = 100*i;
         web = 1;
     end
@(posedge clkb)
     web = 0;


что из за блокирующих присвоений все ломается? Да не может того быть, до следующего фронта по которому все защелкниться еще как до луны... там частота то детская 100 МГц....
warrior-2001
оба @(posedge clkb) - это один момент времени!
И что произойдет раньше, web = 0; или web = 1; одной квесте ведомо.
Golikov A.
почему один и тот же момент? @(posedge clkb) - запуск по событию, отработали идем на следующую строчку, там опять @(posedge clkb) - снова ждем события, разве не так? Мой мир ошибочен?
на графиках то правильно рисуется...
warrior-2001
Хочется посмотреть весь ТБ. Не хочется по кускам кода рушить целый мир sm.gif
Советую всетаки попробовать "web <= 0; "
Golikov A.
да он в первом сообщении вроде как есть...

web <= 0 - похоже на танец с бубуном.

почему нет проблем с портом А, и почему с портом В проблемы только с каждой 2 записью, и почему в моделсиме проблем нет?
Golikov A.
Во всем тестбенче блокирующие присвоения переписал на неблокирующие и все модели ксалинкса стали работать. А альтера продолжает кривляться....

Ну вот и какого? А почему об этом нет большой надписи красными буквами? Кто-то знает что произошло? Тестбенч в начале темы приведен (6 сообщение)
XVR
Видимо потому что все присваивания и сэмплинг сигналов хотя и производится в один и тот же логический момент времени, внутри этот 'момент' не по детски порезан аж на 17 частей (стандарт IEEE1800 параграф 4.4 картинка 4.1). А блокирующие и неблокирующие присваивания отрабатываются в разных частях этой мозаики sm.gif
Golikov A.
возможно... то есть видать я разошелся с моделью, то есть у меня все присвоения были блокирующими, теперь все не блокирующие, а вот как оно обрабатывается в модели блока памяти фиг знает.

Но на самом деле альтера не сдается, по прежнему не могу писать по порту В в нечетные адреса выставляя адрес и врайт енайбл в один такт.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.