|
M9K Altera не записывает некоторые данные, Cyclone 4 память через altsyncram |
|
|
|
Oct 9 2015, 15:36
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Всем привет! Надо было сделать параметризуемую память, собираемую из банков М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 клокового врайтенайбла за такт выставить данные и адрес, запись пройдет, и это только по порту В
|
|
|
|
|
Oct 9 2015, 19:08
|

Местный
  
Группа: Свой
Сообщений: 314
Регистрация: 13-07-06
Из: Москва
Пользователь №: 18 797

|
Метастабильность? Уверен, что если, для теста, будете писать и читать одним клоком, то всё будет Ок. У меня была похожая проблема, с FIFO, но там Мегавизард предлагал улучшить исполнение за счёт увеличения используемых элементов, что и помогло. Тригеров, что ли напихайте до и после памяти  Нет, с метастабильностью я погорячился. В RAM, в отличии от FIFO, клоковые домены чётко разделены. Но тест с одним клоком я бы всё равно провёл.
|
|
|
|
|
Oct 9 2015, 19:37
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
клок один (входа 2 подано одно и тоже), запись и чтение четко разделены сначала много пишем, потом много читаем. Если выставить адрес, а в след клоке дернуть на 1 такт WE запись проходит. Если в одном такте это сделать запись проходит только в четные адреса. Был вариант когда писалась память почти вся кроме 1 ячейки, то есть 0 и 2,3,4,5.... писались, а 1 пропускалась.
Если WE стоит, а данные и адрес меняются каждый такт все записывается нормально...
Есть серъезное подозрение на ошибку симулятора или модели памяти. Хотя и какое-то упущение в доках тоже возможно. По докам память должна быть из 2 плиток (тру дуал порт 32 бита), и вроде альт синк рам это и должен сам сделать... но в техноложик вью на нижнем уровне просто 32 квадратика, и фиг его знает сколько это плиток...
|
|
|
|
|
Oct 12 2015, 06:46
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Да проблема на симуляции, сейчас в железе трудно достоверно проверить, но не думаю что альтеровская мегафункция сделанная через визард будет так себя вести в железе. тестбенч вот такой 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
|
|
|
|
|
Oct 12 2015, 12:07
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
В общем и целом наблюдаем следующую вещь
Берем 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 тактовыми, но чтобы строб был в след такте после выставления адреса
|
|
|
|
|
Oct 12 2015, 20:31
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
Симулятор был квеста, пробовали что за зверь Модел сим альтера попробовали - отработал все корректно. Цитата Зачем "#2;" внутри синхронный воздействий? явно сдвигали фронты, обычно чтобы глазом было удобнее смотреть. Ну и была теория что в библиотеках элементов что-то есть чего мы не знаем, и какие-то задержки... почему то значение которое должно было появиться по фронту при @(posedge clk) считывалось с прошлого такта, и только после #2 стало новым..... Думаю скорее всего мы что-то не так настроили, или даже не настроили... что все идет не так как хочется это очевидно.... а вот как поправить хз
|
|
|
|
|
Oct 13 2015, 07:59
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
--- upd нашел странный варнинг в консоли Цитата Port type is incompatible with connection (port 'wren_b'). и что это значит? ссылается на несуществующую строку. при этом именно с портом б проблемы, ругается на 4 блока памяти моих, на блок из визарда не ругается, но он тоже не работает...
|
|
|
|
|
Oct 13 2015, 10:11
|
Местный
  
Группа: Свой
Сообщений: 375
Регистрация: 9-10-08
Из: Таганрог, Ростовская обл.
Пользователь №: 40 792

|
Цитата(Golikov A. @ Oct 13 2015, 09:48)  принт в консоли ничего особенного не пишет. Модуль 100% рабочий, ну не будет же корка мегавизардом сделанная лажать? Да и моделсим-альтера правильно отработал. Сто пудово что-то в квесте не нстроили... вот что в info писать не понятно, на что смотреть?
timescale - что-то мне говорит что должен быть порядка 1ps, как убедиться что квеста на таком работает? Прописать для квесты timescale в 1 пс должен пользователь. Смотреть - на последовательность выполнения команд в ТБ. После каждой строки ТБ ставите и смотрите что и когда и в каком порядке отработало. Явно сперва скушался клок, а потом WR_en. Или что-то в этом роде. В своих ТБ в части драйверов по взаимодействию с синхронными интерфейсами ПЛИС давно перешли на синхронный режим по клоку.
--------------------
Глупцы игнорируют сложность. Прагматики терпят ее. Некоторые могут избегать ее. Гении ее устраняют.
|
|
|
|
|
Oct 13 2015, 10:37
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
прописал в настройках квартуса, в части симулятора, для 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 МГц....
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|