Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: mt32 под EP3C25 не работает в режиме Burst
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
xxxmatrixxx
Здравствуйте

У меня такая проблема:
Сделал программу на Verilog, которая принимает данные из вне, а потом перекидывает их на сторону PCI(работал, как таргет, считывали с меня по прерыванию)... но такой вариант был слишком затратен по времени, т.к. верхнее ПО было написано под Linux, а сам чипсет компа не давал возможности с меня считывать пакетно... что только не пробовал, ничего не выходило, прочитал на форуме ELECTRONIX, подсказали, что придется реализовывать мастера...

Так вот поставил mt32 core для Альтеры с возможностью работы в режиме 66Мгц...

Прога под Linux пока не подправлена, но я попробовал выходить на шину мастером и писать данные в меня... я увидел, что я пишу так же, т.е. одиночными посылками, а не пакетно....

Вопрос: что необходимо указать в установках core(я пробовал менять конфигурацию баров с non - prefetchable на prefetchable), либо как организовывать обмен по PCI так, чтобы я работал в пакетном режиме???

Спасибо...
Serhiy_UA
Цитата(xxxmatrixxx @ Jun 19 2012, 16:25) *
...я увидел, что я пишу так же, т.е. одиночными посылками, а не пакетно....

Похоже, что Ваш FSM не верно обслуживает mt32 с локальной стороны.
Чтобы разобраться, выложите *.pdf PCI Megacore с которым работаете (их много), и ссылку на страницу и диаграмму. А также кратко, что выдается с локальной стороны в mt32 и что по диаграмме не так получается.
Есть еще и SignalTap II Logic Analyzer, который всегда поможет разобраться, покажите и его диаграммы.
Какой QII применяете?
xxxmatrixxx
Цитата(Serhiy_UA @ Jun 20 2012, 09:30) *
Похоже, что Ваш FSM не верно обслуживает mt32 с локальной стороны.
Чтобы разобраться, выложите *.pdf PCI Megacore с которым работаете (их много), и ссылку на страницу и диаграмму. А также кратко, что выдается с локальной стороны в mt32 и что по диаграмме не так получается.
Есть еще и SignalTap II Logic Analyzer, который всегда поможет разобраться, покажите и его диаграммы.
Какой QII применяете?


Спасибо, что откликнулись)))

Применяю Quartus 9.1

Описание Core и диаграммы с SignalTab тоже выложил...

не смотрите на сигналы lt_ackn и lt_dxfrn, похоже неправильно нарисовал сигналтаб, т.к. lt_rdyn выставляется на них...

Адрес БАР0 именно 0xF8F0_0000

// выставление готовности при совпадении бар0
always @(posedge ClkPCI or negedge Reset)
begin
if(Reset == 0) ltrdyn <= 1;
else ltrdyn <= !(( bar0_hit) & cycle_start );
end

////////////// выставление с локальной стороны lt_framen ////////////
reg lt_framen_q;
always @ (posedge ClkPCI or negedge Reset)
begin
if (!Reset) lt_framen_q <= 1'b1;
else lt_framen_q <= !lt_framen;
end

//////////////////////////////////////////////////////////////////////////////
//установившийся сигнал обмена
wire cycle_start = (lt_framen_q & !lt_framen);
wire bar0_hit = lt_tsr[0]; // отслеживаем бит 0

// сигнал ответа готовности к обмену
reg ltrdyn;
assign lt_rdyn = ltrdyn;

Serhiy_UA
lm_tsr[9..0] от SignalTap показывает, что что-то не так...

Однако, этого не достаточно:
wire bar0_hit = lt_tsr[0]; // отслеживаем бит 0

Повторюсь "...и ссылку на страницу и диаграмму", с которой работаете...
xxxmatrixxx
Цитата(Serhiy_UA @ Jun 21 2012, 13:10) *
lm_tsr[9..0] от SignalTap показывает, что что-то не так...

Однако, этого не достаточно:
wire bar0_hit = lt_tsr[0]; // отслеживаем бит 0

Повторюсь "...и ссылку на страницу и диаграмму", с которой работаете...


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

// запись
wire wrFromPci = (!lt_dxfrn & (l_cmdo[3:0] == 4'h7) & bar0_hit); // запись информации
//чтение служебной информации
wire rdWorkInf = (!lt_ackn & (l_cmdo[3:0] == 4'h6) & bar1_hit); //чтение служебной инфы

похоже кора просто не выставляет сигналы lt_dxfrn и lt_ackn... надо будет разбираться почему...
Serhiy_UA
Цитата(xxxmatrixxx @ Jun 22 2012, 09:12) *
стр 188 данного руководства... насчет выставления lt_rdyn вы правы... я принимаю данные на чтение или запись вот так

// запись
wire wrFromPci = (!lt_dxfrn & (l_cmdo[3:0] == 4'h7) & bar0_hit); // запись информации
//чтение служебной информации
wire rdWorkInf = (!lt_ackn & (l_cmdo[3:0] == 4'h6) & bar1_hit); //чтение служебной инфы

похоже кора просто не выставляет сигналы lt_dxfrn и lt_ackn... надо будет разбираться почему...

на стр.188 (Burst Memory Write) нет сигналов l_cmdo[3:0]. Возможно, надо привязаться к чему-то другому... например, l_cbeni[3..0]...
xxxmatrixxx
Цитата(Serhiy_UA @ Jun 22 2012, 13:08) *
на стр.188 (Burst Memory Write) нет сигналов l_cmdo[3:0]. Возможно, надо привязаться к чему-то другому... например, l_cbeni[3..0]...


l_cbeni[3..0] - сигналы выдачи команды с локальной стороны во время фазы адреса, а так же признаки разрешения байтов во время чтения/записи по PCI, т.е. это входной сигнал с локальной стороны PCIcore...

Изучая этут тему и когда с отпуска вернулся программист под Linux обнаружились следующие результаты...

Когда я выхожу как мастер на шину и пишу в себя.... Здесь моя таргет сторона выставляет сигнал STOP и прекращает обмен, хотя по статусу видно, что мастер ведет именно мультизапись(статусный регистр lt_tsr[9] = 1)... после более подробного изучения спецификации и документации на шину PCI, выяснил, что если мастер ведет обмен с мультизаписью или мультичтением, а устройство, с которым оно связывается не поддерживает мультизапись (мультичтение), то это устройство выставляет сигнал STOP для окончания транзакции... т.е. вынужденно передается все по одному слову....

Вопрос: получается, что сторона target в megacore вообще не поддерживает мультизапись или мультичтение, либо это результат того, что я пишу сам в себя, либо в настройках не так что-то ставлю(выделяю 2 бар prefecheable)

Сейчас обмен между мною и ПК осуществляется следующим образом: в момент инициализации(вкл модуля) ПК пишет в меня физический адрес памяти на шине PCI, который выделяет в процессе загрузки драйвера под Linux... при обращении к ней все виснет))) выяснилось, что я выставляю адрес на шину, а затем пытаюсь передать данные... причем ответа от устройства я не могу дождаться(сигнал trdy висит в 1), но и сигналы Framen и Irdy висят в 0, т.е. я занимаю шину PCI постоянно, поэтому виснет вся система.....

Вопрос: как необходимо вести обмен между мною и ПК? какой адрес памяти ПК, выделенный для меня, должен передаваться мне(просто там 64 бита, а мне передается старшая часть 64го слова)

Может у кого-нибудь есть опыт по разработке мастера для реализации мультизаписи???

1я картинка(слева направо) попытка обмена с ПК, после чего все виснет))))
2я картинка работа меня, как мастера, и запись в меня, кстати, комп при этом не виснет...
XVR
Цитата
Вопрос: как необходимо вести обмен между мною и ПК? какой адрес памяти ПК, выделенный для меня, должен передаваться мне(просто там 64 бита, а мне передается старшая часть 64го слова)
Если там 64 бита, то вы и должны передавать 64 бита. Т.е. у вас должна быть PCI64. Если же у вас PCI32, то со стороны Linux'а вы должны заказывать себе буфер для обмена в нижней части памяти (в 32х битах)

Скажите своему програмисту, что бы позвал pci_set_dma_mask(pdev, DMA_32BIT_MASK) перед pci_alloc_consistent
Отдавать на плату нужно будет младшую часть 64х битного адреса (от pci_alloc_consistent)
xxxmatrixxx
Цитата(XVR @ Jun 29 2012, 12:35) *
Если там 64 бита, то вы и должны передавать 64 бита. Т.е. у вас должна быть PCI64. Если же у вас PCI32, то со стороны Linux'а вы должны заказывать себе буфер для обмена в нижней части памяти (в 32х битах)

Скажите своему програмисту, что бы позвал pci_set_dma_mask(pdev, DMA_32BIT_MASK) перед pci_alloc_consistent
Отдавать на плату нужно будет младшую часть 64х битного адреса (от pci_alloc_consistent)


Спасибо, за помощь, но такой вариант так же не помог...

Может у кого-нибудь есть проект под Q9.1 для реализации мастера для записи от меня во внешнее устройство по шине PCI, если можно код, как конкретно и когда выставляете сигналы...

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

Когда пишу в память ПК, выделенную программистом под Linux, все виснет... причем я не понимаю, почему сигналы framen и irdy остаются постоянно в активном уровне(фиически 0) и не реагирует на сигналы с локальной стороны(lm_last - по утому сигналу должен заершаться обмен(framen должен выстависться физически в 1), lm_rdyn - сигнал готовности с моей стороны, который управляет сигналом irdy на шине PCI ), хотя по стандарту обмена по шине PCI я должен ждать сигнал trdy максимум 4 такта после выставления irdy c моей стороны(кстати, по этим тактам определяем насколько быстрое устройство)...

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

CODE

//==========================================================================

////////////// выставление с локальной стороны lt_framen ////////////
reg lt_framen_q;
always @ (posedge ClkPCI or negedge Reset)
begin
if (!Reset) lt_framen_q <= 1'b1;
else lt_framen_q <= !lt_framen;
end

//////////////////////////////////////////////////////////////////////////////
//установившийся сигнал обмена
wire cycle_start = (lt_framen_q & !lt_framen);
wire bar0_hit = lt_tsr[0]; // отслеживаем бит 0
wire bar1_hit = lt_tsr[1]; // отслеживаем бит 1

// сигнал ответа готовности к обмену
reg ltrdyn;
assign lt_rdyn = ltrdyn;

// выставление готовности при совпадении бар0 и
always @(posedge ClkPCI or negedge Reset)
begin
if(Reset == 0) ltrdyn <= 1;
else ltrdyn <= !(( bar0_hit | bar1_hit) & cycle_start );
end

//reg ltdiscn;
assign lt_discn = 1'b1;//ltdiscn;


wire [31:0] WorkDataForPCI;
wire [31:0] DataForPCI;
reg [31:0] SumOfCountForPCI;

// запись
wire wrFromPci = (!lt_dxfrn & (l_cmdo[3:0] == 4'h7) & bar0_hit); // запись информации
//чтение служебной информации
wire rdWorkInf = (!lt_ackn & (l_cmdo[3:0] == 4'h6) & bar1_hit); //чтение служебной инфы

//прерывание
reg set_irq; // регистр отвечающий за выставление прерывания
assign lirqn = !set_irq;//выставляем прерывание

reg [11:0] CountOfData;
reg [11:0] CountOfWorkData;


wire DataWrfull;
wire DataRdempty;
wire WorkDataWrfull;
wire WorkDataDataRdempty;
//Очередь для данных, считанных с шины Е, для записи по шине PCI
//Очередь для данных, считанных с шины Е, для записи по шине PCI
dcfifo FifoData(
.wrclk (Clk50),
.rdreq (rdreqFifoData),
.aclr (~Res),
.rdclk (ClkPCI),
.wrreq (SI_EN),
.data (data),
.rdempty (DataRdempty),
.wrfull (DataWrfull),
.wrusedw (CountOfData),
.q (DataForPCI)
// synopsys translate_off
,
.rdfull (),
.rdusedw (),
.wrempty ()
// synopsys translate_on
);
defparam
FifoData.intended_device_family = "Cyclone III",
FifoData.lpm_numwords = 4096,
FifoData.lpm_showahead = "ON",
FifoData.lpm_type = "dcfifo",
FifoData.lpm_width = 32,
FifoData.lpm_widthu = 12,
FifoData.overflow_checking = "ON",
FifoData.rdsync_delaypipe = 4,
FifoData.underflow_checking = "ON",
FifoData.use_eab = "ON",
FifoData.write_aclr_synch = "OFF",
FifoData.wrsync_delaypipe = 4;


//Очередь для чтения на шину PCI и записи с шины МПИ
dcfifo FifoWorkData (
.wrclk (Clk50),//+
.rdreq (rdreqFifoWorkData),//+
.aclr (~Res),//+
.rdclk (ClkPCI),//со стороны мпи
.wrreq (fldone_en), //+
.data (workdata),//+
.rdempty (WorkDataDataRdempty),
.wrfull (WorkDataWrfull),
.wrusedw (CountOfWorkData),
.q (WorkDataForPCI)//+
// synopsys translate_off
,
.rdfull (),
.rdusedw (),
.wrempty ()
// synopsys translate_on
);
defparam
FifoWorkData.intended_device_family = "Cyclone III",
FifoWorkData.lpm_numwords = 4096,
FifoWorkData.lpm_showahead = "ON",
FifoWorkData.lpm_type = "dcfifo",
FifoWorkData.lpm_width = 32,
FifoWorkData.lpm_widthu = 12,
FifoWorkData.overflow_checking = "ON",
FifoWorkData.rdsync_delaypipe = 4,
FifoWorkData.underflow_checking = "ON",
FifoWorkData.use_eab = "ON",
FifoWorkData.write_aclr_synch = "OFF",
FifoWorkData.wrsync_delaypipe = 4;

//----------------------------------------------------
reg ResetFromPci;
reg InitFromPci;
wire Res; //общий сброс
assign Res = Reset & ResetFromPci & InitFromPci;

localparam ns40 = 2'h2;
reg [1:0] kk;
// генерация внутреннего сброса при приеме соответствующего пакета по PCI
always @(posedge ClkPCI or negedge Reset)
begin
if (Reset == 0) ResetFromPci <= 1;
else if(wrFromPci && l_dato[15:0] == 16'hE00F)
ResetFromPci <= 0;
else if(kk == ns40) ResetFromPci <= 1;
end

always @(posedge Clk50 or negedge Reset)
begin
if (Reset == 0) kk <= 0;
else if(ResetFromPci == 0) kk <= kk + 1'b1;
else kk <= 0;
end
///---------------------------------------------------

//отключение и включение модуля
always @(posedge ClkPCI or negedge Reset)
begin
if (Reset == 0) InitFromPci <= 0;
else if(wrFromPci && l_dato[15:0] == 16'hE000)
InitFromPci <= 0;
else if(wrFromPci && l_dato[15:0] == 16'hE001)
InitFromPci <= 1;
end

//-----------------------------------------------------

reg set_irq_clear; // флаг снятия прерывания со стороны PCI
//снятие прерывания
always @(posedge ClkPCI or negedge Reset)
begin
if (Reset == 0) set_irq_clear <= 0;
else if(wrFromPci && l_dato[15:0] == 16'hE00C) //если производится запись с PCI
set_irq_clear <= 1;
else if(set_irq == 0) set_irq_clear <= 0;
end

reg mode_r;
//выбор режима
//0 - прерывание выставляется при окончании одиночной пачки
//1 - при достижении очереди > 4000 отсчетов(т.е. зафиксировали, дождались конца всей пачки, выдали прерывание)
always @(posedge ClkPCI or negedge Reset)
begin
if (Reset == 0) mode_r <= 0;
else if(wrFromPci && l_dato[15:0] == 16'hE00E)
if (l_dato[31:16] == 16'h0000) mode_r <= 0;
else mode_r <= 1;
end

//регистр статуса
reg [31:0] RegStatus;
always @(posedge ClkPCI or negedge Res)
begin
if (Res == 0) RegStatus <= 32'hF0F0_0F00;
else
begin
RegStatus[0] <= set_irq; // прерывание
end
end

//формирование служебных пакетов на сторону PCI
reg [31:0] WorkInf;
always @(posedge ClkPCI or negedge Res)
begin
if (Res == 0) WorkInf <= 32'h0000_0000;
else if(rdWorkInf)
case (l_adro[15:0])
16'h0000: WorkInf <= CountOfData;
16'h0004: WorkInf <= CountOfWorkData;
16'h0030: WorkInf <= RegStatus;
16'h0034: WorkInf <= ver;
16'h0038: WorkInf <= date;
endcase
end


//сигнал разрешения записи по PCI со стороны мастера
wire EnableWritePCIMaster = WriteEnableFromE & EnableMaster;

// разрешение записи на стороне PCI
reg EnableMaster;
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) EnableMaster <= 1'b1;
else if(set_irq_posedge == 1) EnableMaster <= 1'b0; //выставили прерывание
else if(wrFromPci && l_dato[15:0] == 16'hE00D) EnableMaster <= 1'b1; //получили команду на разрешение работы как мастера
end

//фиксируем перепад для выставления прерывания
wire set_irq_posedge = set_irq & ! set_irqN;

reg set_irqN;
always @(posedge Clk50 or negedge Res)
begin
if(Res == 0) set_irqN <= 1'b0;
else set_irqN <= set_irq;
end

//выставление прерывания
always @(posedge Clk50 or negedge Res)
begin
if(Res == 0) set_irq <= 1'b0;
else if(StatePCI == 6) set_irq <= 1'b1;
else if(set_irq_clear == 1) set_irq <= 1'b0;
end

//общее количество отсчетов в очередях
always @(posedge Clk50 or negedge Res)
begin
if(Res == 0) SumOfCount <= 32'h0000_0000;
else if(fldone_en_2T_negedge) SumOfCount <= CountOfData + CountOfWorkData;
end

//ресинхронизируем для шины PCI количества сформированных пачек
always @(posedge ClkPCI or negedge Res)
begin
if (Res == 0) SumOfCountForPCI <= 32'h0000_0000;
else SumOfCountForPCI <= SumOfCount;
end

//*****************************____PCI_MASTER____*********************************
*

//промежуточные регистры для передачи данных
reg [31:0] localMaxSumOfCount;// количество передаваемых на шину PCI отсчетов за одну транзакцию
reg [31:0] localIndexSumOfCounting; // текущий индекс отсчетов относительно пачек
reg [31:0] localMaxCounting; // количество отсчетов в текущей пачке
reg [31:0] CurrentIndexOfCounting; // текущий индекс отсчета в пачке

//сигналы разрешения выталкивания отсчетов из очередей
reg rdreqFifoWorkData;
reg rdreqFifoData;
reg rdrFifoWorkData; // промежуточный сигнал для машины автомата

//присвоение текущего количества отсчетов за транзакцию
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) localMaxSumOfCount <= 32'h0000_0000;
else if(StatePCI_Wr == 4 && StatePCI == 0) localMaxSumOfCount <= SumOfCountForPCI;
end

//отслеживание текущего индекса внутри пачки
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) localIndexSumOfCounting <= 32'h0000_0000;
else if(StatePCI == 3) localIndexSumOfCounting <= localIndexSumOfCounting + WorkDataForPCI + 4;
else if(StatePCI == 6) localIndexSumOfCounting <= 32'h0000_0000;
end

//отслеживание текущего индекса внутри пачки
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) localMaxCounting <= 32'h0000_0000;
else if(StatePCI == 3) localMaxCounting <= WorkDataForPCI;
end

//импульс выталкивания из очереди, где данные
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) rdreqFifoData <= 0;
else if(StatePCI == 4 && CurrentIndexOfCounting >= localMaxCounting) rdreqFifoData <= 0;
else if(StatePCI == 4 || StatePCI == 5/*&& lm_ackn == 0*/ ) rdreqFifoData <= 1;
else rdreqFifoData <= 0;
end

//отслеживание текущего индекса отсчетов относительно пачек
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) CurrentIndexOfCounting <= 32'h0000_0000;
else if(StatePCI != 4 /* && lm_ackn == 0*/) CurrentIndexOfCounting <= 32'h0000_0001;
else CurrentIndexOfCounting <= CurrentIndexOfCounting + 1'b1;
end


//сигнал выталкивания из очереди рабочих данных
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) rdreqFifoWorkData <= 0;
else /*if( lm_ackn == 0)*/
case (StatePCI)
//передача служебной инфы (не обращаем внимание на цифры, главное последовательность)
// т.к. работаем по синхросигналу сразу, то начинаем работать на опережение
1: if(localIndexSumOfCounting < localMaxSumOfCount) rdreqFifoWorkData <= 1; // передаем номер кадра из служебной очереди
7: rdreqFifoWorkData <= 1; // передаем номер пачки из служебной очереди
2: rdreqFifoWorkData <= 1; // передаем количество отсчетов в данной пачке из служебной очереди
3: rdreqFifoWorkData <= 1; // передаем количество ошибок ЗИНП
default: rdreqFifoWorkData <= 0;
endcase
/*else rdreqFifoWorkData <= 0;*/
end

//выставление данных на шину АД PCI
assign l_adi = (rdWorkInf == 1)? WorkInf: (fl_adr == 1)? adress: (EnableWritePCIMaster == 1 && StatePCI == 0)? SumOfCountForPCI: (StatePCI == 4)? DataForPCI:(StatePCI == 6)? 32'hFACE_DEAD: ( StatePCI == 7 || StatePCI == 2 || StatePCI == 3 || StatePCI == 5)? WorkDataForPCI: 32'h0000_0000;

//**************************************************************************
//********Работа автомата по шине PCI при записи от меня********************
//**************************************************************************

//переход в 32битный режим
reg lm_req32r;
assign lm_req32n = lm_req32r;

//выставление запроса работы по 32й шине
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) lm_req32r <= 1;
else if(StatePCI_Wr == 0 && EnableWritePCIMaster == 1) lm_req32r <= 0; // пытаемся перейти в 32битный режим
else lm_req32r <= 1;
end

//задержка перед проверкой, в каком режиме работаем
reg [4:0] delay;
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) delay <= 0;
else if(StatePCI_Wr == 1) delay <= delay + 1'b1; // пытаемся перейти в 64битный режим
else delay <= 0;
end

//адрес записи с моей стороны
reg [31:0] adress ;
//команда для записи по PCI
localparam comand = 4'h07;
assign l_cbeni = comand;

//определяем адрес
always @(posedge ClkPCI or negedge Reset)
begin
if(Reset == 0) adress = 32'h0000_0000;
else if(wrFromPci && l_dato[15:0] == 16'hE00A) adress[31:16] <= l_dato[31:16]; //старшее слово
else if(wrFromPci && l_dato[15:0] == 16'hE00B) adress[15:0] <= l_dato[31:16]; //младшее слово
end


//флаг выставления адреса или данных
reg fl_adr;
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) fl_adr <= 0;
else case(StatePCI_Wr)
0: if (EnableWritePCIMaster == 1) fl_adr <= 1;// выставляем адрес
3: if (lm_adr_ackn_ne == 1) fl_adr <= 0; //выставляем данные
endcase
end

reg lm_adr_acknN;
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) lm_adr_acknN <= 1;
else lm_adr_acknN <= lm_adr_ackn;
end

wire lm_adr_ackn_ne = !lm_adr_ackn & lm_adr_acknN;

localparam t2 = 1; // считаем количество тактов

//выставление сигнала готовности на стороне мастера PCI

assign lm_rdyn = (StatePCI == 1 )? 1'b1: (StatePCI_Wr == 4)? 1'b0: 1'b1;
/*reg lmrdyn;

// выставление сигнала готовности на стороне мастера
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) lmrdyn <= 1;
else if(StatePCI == 1) lmrdyn <= 1; // ставим задержку в передаче при передаче на сторону PCI
else case(StatePCI_Wr)
0: lmrdyn <= 1; // в самом начале неактивно устройство(на всякий случай)
3: if(lm_adr_ackn_ne == 1) lmrdyn <= 0; // начала обмена после выставления адреса
4: if(StatePCI == 7) lmrdyn <= 0;
else if(StatePCI == 6) lmrdyn <= 1;
endcase
end */

//выставление сигнала, определяющего последний переданный пакет(извещение о последней посылке)
reg lmlastn;
assign lm_lastn = lmlastn;
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) lmlastn <= 1;
else case(StatePCI)
1: if(localIndexSumOfCounting >= localMaxSumOfCount) lmlastn <= 0; //последняя пачка
default: lmlastn <= 1;
endcase
end


// автомат для передачи данных на сторону PCI (обслуживание стороны мастера)
reg [3:0] StatePCI_Wr;
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) StatePCI_Wr <= 0;
else case(StatePCI_Wr)
0: if(EnableWritePCIMaster == 1) StatePCI_Wr <= 1; //сформировали пачку начинаем ее передавать
1: if(delay >= t2) StatePCI_Wr <= 2; // ставим задержку
2: if ( lm_tsr[0] == 1) StatePCI_Wr <= 3; // если подтвердился обмен по 32битной шине
else StatePCI_Wr <= 0;
// отправили адрес
3: if (lm_adr_ackn_ne == 1) StatePCI_Wr <= 4; //работа по 32битной шине
//собственно передача управления для работы алгоритма выдачи информации
4: if(StatePCI == 6) StatePCI_Wr <= 0;
endcase
end

//алгоритм работы выставления данных на шину АД шины PCI
reg [2:0] StatePCI;
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) StatePCI <= 0;
else case (StatePCI)
0: if(StatePCI_Wr == 4) StatePCI <= 1; // передаем количество считываемых пакетов за 1 цикл обмена
1: if(localIndexSumOfCounting >= localMaxSumOfCount) StatePCI <= 6;
else StatePCI <= 7;
//передача служебной инфы (не обращаем внимание на цифры, главное последовательность)
7: StatePCI <= 2; // передаем номер кадра из служебной очереди
2: StatePCI <= 3; // передаем номер пачки из служебной очереди
3: StatePCI <= 5; // передаем количество отсчетов в данной пачке из служебной очереди
5: StatePCI <= 4; // передаем количество ошибок ЗИНП
//сами отсчеты
4: if(CurrentIndexOfCounting >= localMaxCounting) StatePCI <= 1;// передаем данные
//передаем концевик
6: StatePCI <= 0; //после окончания транзакции( п)
endcase
end

endmodule
608
А запись одного слова в память компьютера, по выделенному адресу, получается?
xxxmatrixxx
Цитата(608 @ Jul 4 2012, 16:38) *
А запись одного слова в память компьютера, по выделенному адресу, получается?


Нет, сразу виснет
xxxmatrixxx
Цитата(XVR @ Jun 29 2012, 12:35) *
Если там 64 бита, то вы и должны передавать 64 бита. Т.е. у вас должна быть PCI64. Если же у вас PCI32, то со стороны Linux'а вы должны заказывать себе буфер для обмена в нижней части памяти (в 32х битах)

Скажите своему програмисту, что бы позвал pci_set_dma_mask(pdev, DMA_32BIT_MASK) перед pci_alloc_consistent
Отдавать на плату нужно будет младшую часть 64х битного адреса (от pci_alloc_consistent)


XVR, Не мог бы скинуть код под Линукс, если есть конечно, где ты работаешь как таргет, а в тебя пишут.... буду очень признателен
мыло: petrov3372@yandex.ru
XVR
Цитата(xxxmatrixxx @ Jul 6 2012, 13:25) *
XVR, Не мог бы скинуть код под Линукс, если есть конечно, где ты работаешь как таргет, а в тебя пишут.... буду очень признателен

Запись в таргет под управлением CPU возможна только словами. Для записи блоками нужен мастер.
xxxmatrixxx
Цитата(XVR @ Jul 6 2012, 17:57) *
Запись в таргет под управлением CPU возможна только словами. Для записи блоками нужен мастер.


Так комп работает как таргет, а я со стороны своего модуля как мастер...

У меня виснет, когда я захватываю шину, становлюсь мастером на шине и пишу в ПК... вероятнее всего, что проблема в работе со стороны ПК,
либо адрес, который определяет linux и мне выдает, неверный, либо сконфигурирована память на стороне ПК не правильно...

Просто я грешу на неправильную работу проги под Linux...
Serhiy_UA
У меня mt32 на Cyclone III работает как в Линук, так и в ДОС.
BAR0 и BAR1 проецируются на память ПК, а BAR2 и BAR3 на регистры ввода-вывода в mt32. Один из последних используется для приема начального адреса (через запрос на прерывание), по которому потом в память ПК начинает записываться массив. Правда я записываю в память ПК последовательно по слову, может быть и для того, чтобы не занимать надолго PCI-шину, были сомнения, что иначе ограничивается производительность программы на ПК…
Заметил, что Ваша программа работает с ClkPCI и Clk50. У меня тоже две частоты, обошел коллизии тем, что работаю с внутренним ОЗУ на одной более высокой в процессе подготовки данных, а потом при работе с шиной переключаю на ClkPCI. Ну и соответственно два банка для подготовки данных, работающих по принципу «пинг-понг»…
XVR
Цитата(xxxmatrixxx @ Jul 9 2012, 11:50) *
У меня виснет, когда я захватываю шину, становлюсь мастером на шине и пишу в ПК...
Тогда тебе нужен пример настройки DMA из под Linux
Вот схематично процесс
Код
pci_register_driver() // -> Linux зовет вашу probe функцию
probe()
{
pci_enable_device()
pci_set_master()
pci_request_regions()
pci_resource_start() // -> Возвращает физ адрес вашего пространства (в BAR0)
BAR0=ioremap() // -> Возвращает вирт. адрес BAR0
pci_set_dma_mask(pdev, DMA_32BIT_MASK)
pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
DMA=pci_alloc_consistent(pdev,length,&dma_buffer_ph); // -> Возвращает виртуальный адрес DMA
  // В dma_buffer_ph возвращается физ адрес для DMA
BAR0[your_dma_address]=dma_buffer_ph; // В регистр на вашей плате (доступный через BAR0) пишете адрес для DMA
  // Стартуете DMA
}

xxxmatrixxx
Цитата(Serhiy_UA @ Jul 9 2012, 13:01) *
У меня mt32 на Cyclone III работает как в Линук, так и в ДОС.
BAR0 и BAR1 проецируются на память ПК, а BAR2 и BAR3 на регистры ввода-вывода в mt32. Один из последних используется для приема начального адреса (через запрос на прерывание), по которому потом в память ПК начинает записываться массив. Правда я записываю в память ПК последовательно по слову, может быть и для того, чтобы не занимать надолго PCI-шину, были сомнения, что иначе ограничивается производительность программы на ПК…
Заметил, что Ваша программа работает с ClkPCI и Clk50. У меня тоже две частоты, обошел коллизии тем, что работаю с внутренним ОЗУ на одной более высокой в процессе подготовки данных, а потом при работе с шиной переключаю на ClkPCI. Ну и соответственно два банка для подготовки данных, работающих по принципу «пинг-понг»…


Я использую очередь для согласования частот, а так же по функциональности она больше подходит....

У меня просьба, не смогли бы скинуть код, часть кода, где видно, как работаете с корой как с мастером,
какие настройки для коры ставите, чтобы работать как мастер....

Может у вас будет код под Линукс, где выделяете память, конфигурируете ее под линукс...

Я буду очень благодарен... просто мучаюсь уже 2ю неделю, а копать не очень понимаю где...
Serhiy_UA
Цитата(xxxmatrixxx @ Jul 9 2012, 12:25) *
..какие настройки для коры ставите, чтобы работать как мастер....

По поводу корки PCI_bb, как черного ящика. Не нашел в Вашей программе определения параметров для mt32. Мои, в приложении. Правда, в предыдущем посте я ошибся по BAR3, но это не принципиально...
Программы на ПК под PCI-шину не пишу, пока только синтез ПЛИС...
xxxmatrixxx
Цитата(Serhiy_UA @ Jul 9 2012, 14:00) *
По поводу корки PCI_bb, как черного ящика. Не нашел в Вашей программе определения параметров для mt32. Мои, в приложении. Правда, в предыдущем посте я ошибся по BAR3, но это не принципиально...
Программы на ПК под PCI-шину не пишу, пока только синтез ПЛИС...


вот параметры:
CODE
pci_mt32_inst.CLASS_CODE = 24'hff0000,
pci_mt32_inst.DEVICE_ID = 16'h0005,
pci_mt32_inst.REVISION_ID = 8'h01,
pci_mt32_inst.SUBSYSTEM_ID = 16'h0000,
pci_mt32_inst.SUBSYSTEM_VENDOR_ID = 16'h0000,
pci_mt32_inst.TARGET_DEVICE = "NEW",
pci_mt32_inst.VENDOR_ID = 16'h1172,
pci_mt32_inst.MIN_GRANT = 8'h00,
pci_mt32_inst.MAX_LATENCY = 8'h00,
pci_mt32_inst.CAP_PTR = 8'h40,
pci_mt32_inst.CIS_PTR = 32'h00000000,
pci_mt32_inst.BAR0 = 32'hfff00008,
pci_mt32_inst.BAR1 = 32'hfff00008,
pci_mt32_inst.BAR2 = 32'hfff00000,
pci_mt32_inst.BAR3 = 32'hfff00000,
pci_mt32_inst.BAR4 = 32'hfff00000,
pci_mt32_inst.BAR5 = 32'hfff00000,
pci_mt32_inst.NUMBER_OF_BARS = 32'h00000002,
pci_mt32_inst.HARDWIRE_BAR0 = 32'h00000000,
pci_mt32_inst.HARDWIRE_BAR1 = 32'h00000000,
pci_mt32_inst.HARDWIRE_BAR2 = 32'h00000000,
pci_mt32_inst.HARDWIRE_BAR3 = 32'h00000000,
pci_mt32_inst.HARDWIRE_BAR4 = 32'h00000000,
pci_mt32_inst.HARDWIRE_BAR5 = 32'h00000000,
pci_mt32_inst.HARDWIRE_EXP_ROM = 32'h00000001,
pci_mt32_inst.EXP_ROM_BAR = 32'hfff00000,
pci_mt32_inst.PCI_66MHZ_CAPABLE = "YES",
pci_mt32_inst.INTERRUPT_PIN_REG = 8'h01,
pci_mt32_inst.ENABLE_BITS = 32'h00000000;
Serhiy_UA
Цитата(xxxmatrixxx @ Jul 9 2012, 15:08) *
pci_mt32_inst.BAR0 = 32'hfff00008,
pci_mt32_inst.BAR1 = 32'hfff00008,

попробуйте эти параметры упростить: запросить поменьше памяти и без "Prefetchable"

Цитата(xxxmatrixxx @ Jul 9 2012, 15:08) *
pci_mt32_inst.PCI_66MHZ_CAPABLE = "YES",

тоже, пока бы с "NO"...
И еще, Вы уже работали с прямым доступом к памяти, хотя бы без режима Burst?

...Еще, вставьте регистр в пространство ввода/вывода и попробуйте записать в него что либо из программы ПК, с выдачей на светодиод. А также считать в ПК... Чтобы увидеть работу корки mt32.
Потом в подобном стиле подергать прерываниями....

...Да, и главное. Регистры в пространстве вводв/вывода должны обязательно быть. Иначе как корка (и за ней FSM) может получить адрес памяти в ПК, назначенный и зарезервированный при инициализации BIOSом, к которому можно обращаться. В заданных Вами параметрах этих регистров нет....
xxxmatrixxx
Цитата(Serhiy_UA @ Jul 9 2012, 16:33) *
попробуйте эти параметры упростить: запросить поменьше памяти и без "Prefetchable"


тоже, пока бы с "NO"...
И еще, Вы уже работали с прямым доступом к памяти, хотя бы без режима Burst?

...Еще, вставьте регистр в пространство ввода/вывода и попробуйте записать в него что либо из программы ПК, с выдачей на светодиод. А также считать в ПК... Чтобы увидеть работу корки mt32.
Потом в подобном стиле подергать прерываниями....

...Да, и главное. Регистры в пространстве вводв/вывода должны обязательно быть. Иначе как корка (и за ней FSM) может получить адрес памяти в ПК, назначенный и зарезервированный при инициализации BIOSом, к которому можно обращаться. В заданных Вами параметрах этих регистров нет....


Сделал, как посоветовал, все равно та же тема...

А какие настройки у вас установлены в окне выбора Advanced PCI MegaCore Function Features(3е окно при конфигурировании коры)???
Serhiy_UA
Цитата(xxxmatrixxx @ Jul 10 2012, 09:22) *
А какие настройки...

См.приложение...Нажмите для просмотра прикрепленного файла
xxxmatrixxx
Цитата(Serhiy_UA @ Jul 10 2012, 10:39) *


Спасибо, похоже дело не в настройках коры...

Не могли бы скинуть код, как работаете с корой,т.е. где видно, когда и какие сигналы выставляются на PCIcore...
Serhiy_UA
Цитата(xxxmatrixxx @ Jul 10 2012, 10:01) *
Не могли бы скинуть код, ...

Не могу. Труд оказался немалый...
xxxmatrixxx
Цитата(Serhiy_UA @ Jul 10 2012, 11:24) *
Не могу. Труд оказался немалый...


так мне не весь код нужен)))

а именно часть код, где видно только когда выставляются lm_framen, lm_rdyn, lm_last...

интересен сам алгоритм работы с корой, как с мастером... просто хочется сравнить, понять, что я делаю не так... а если все верно, то выкатить программисту под linux...
xxxmatrixxx
Нашел в чем ошибка)))))))Причем только сейчас))))

Всем спасибо, кто откликнулся на мою просьбу!!! ОЧень помогли!!!

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

Короче, очень глупая ошибка,которую начинаешь рассматривать только когда все перероешь)))

Но слава Богу хоть так - 2 недели работы и 2 мин после того, как обнаружил ошибку))))

Всем спасибо)))
xxxmatrixxx
Извините за поспешные выводы...

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

Возникли следующие проблемы:

1. Почему-то передается только 64 32х битных слова... потом lm_ackn защелкивается на 1 и заканчивает работу... это по станларту так положено, что при мультизаписи передается только 64 слова???

2. Программист под линукс читает только 0... хотя видно, что от меня все данные уходят, сопровождаемые соответствующими сигналами...

Кто-нибудь сталкивался с такими проблемами?????
Serhiy_UA
Цитата(xxxmatrixxx @ Jul 12 2012, 14:57) *
1. Почему-то передается только 64 32х битных слова...

pci_mt32_inst.MAX_LATENCY = 8'h00, попробуйте этот параметр поменять...

Цитата(xxxmatrixxx @ Jul 12 2012, 14:57) *
Программист под линукс читает только 0...
...для начала передавайте по одному-два слова...
xxxmatrixxx
Цитата(Serhiy_UA @ Jul 12 2012, 16:16) *
pci_mt32_inst.MAX_LATENCY = 8'h00, попробуйте этот параметр поменять...


Пробовал менять этот параметр - не помогло, а когда отключил его вообще(latency timer off), то заработало....

Спасибо

Цитата(Serhiy_UA @ Jul 12 2012, 16:16) *
...для начала передавайте по одному-два слова...


а вот на сторону ПК от PCI приходит похоже что-то, но затирается... т.е. я организовал мультизапись, выставил адрес, установил соединение, и считаю, что адрес с каждым тактом будет на стороне ПК увеличиваться на 4(кажется), а похоже вся инфа долбит в 1у ячейку, т.е. по одному и тому же адресу... получается должно быть записано последнее значение, что я кидал... по опытам так и происходит...

Вопрос:
программист под линукс может отслеживать, что приходит ему по PCI за такт???
однозначно ли определяется мультизапись на стороне ПК под Линукс,т.е. ПК автоматом увеличивает адрес с каждым тактом, когда я пишу при мультизаписи?
XVR
Цитата(xxxmatrixxx @ Jul 12 2012, 17:28) *
программист под линукс может отслеживать, что приходит ему по PCI за такт???
Нет
Цитата
однозначно ли определяется мультизапись на стороне ПК под Линукс,т.е. ПК автоматом увеличивает адрес с каждым тактом, когда я пишу при мультизаписи?
Насколько я помню стандарт (давненько это было, увы) адрес в транзакции указывается 1 раз. Так что пока транзакция не кончится, она должна ложиться по последовательным адресам (если вы конечно не в IO пространство пишете)
xxxmatrixxx
Цитата(XVR @ Jul 12 2012, 21:16) *
Нет
Насколько я помню стандарт (давненько это было, увы) адрес в транзакции указывается 1 раз. Так что пока транзакция не кончится, она должна ложиться по последовательным адресам (если вы конечно не в IO пространство пишете)


Пробовал... ситуация такая - по signaltab видно, что в соответствии со стандартом пачка должна быть отправлена с моей стороны, но на стороне линукса считывается чушь, а вернее 1 слово почти всегда верно, а остальные выдаются 0... причем 0 - это данные, которыми я управляю вот так:
CODE
//выставление данных на шину АД PCI
assign l_adi = (rdWorkInf == 1)? WorkInf: (fl_adr == 1)? adress: (EnableWritePCIMaster == 1 && StatePCI == 0)? SumOfCountForPCI: (StatePCI == 4)? DataForPCI:(StatePCI == 6)? 32'hFACE_DEAD: ( StatePCI == 7 || StatePCI == 2 || StatePCI == 3 || StatePCI == 5)? WorkDataForPCI: 32'h0000_0000;


если я меняю 32'h0000_0000 на другое значение, то вместо 0 на стороне линукс появляется это значение....

под Линукс сделан лог того, что происходит... по приему прерывания от меня считывается 40 слов с того адреса, что мне выдавался на шину
лог такой:
CODE
57.282587] e_bus: got_irq irq=17 dev_id=f61d2800 minor=0
[ 57.282587] e_bus: e_bus_read f=ed7949c0, buf=775da008, size = 40000000h, loff=eb3edf98
[ 57.282589] e_bus: First word: 24h (36) from eb3f0000
[ 57.282626] e_bus: e_bus_buf[0] = 0h from eb3f0000
[ 57.282627] e_bus: e_bus_buf[1] = 0h from eb3f0004
[ 57.282629] e_bus: e_bus_buf[2] = 0h from eb3f0008
[ 57.282630] e_bus: e_bus_buf[3] = 0h from eb3f000c
[ 57.282631] e_bus: e_bus_buf[4] = 0h from eb3f0010
[ 57.282632] e_bus: e_bus_buf[5] = 0h from eb3f0014
[ 57.282634] e_bus: e_bus_buf[6] = 0h from eb3f0018
[ 57.282635] e_bus: e_bus_buf[7] = 0h from eb3f001c
[ 57.282636] e_bus: e_bus_buf[8] = 0h from eb3f0020
[ 57.282638] e_bus: e_bus_buf[9] = 0h from eb3f0024
[ 57.282639] e_bus: e_bus_buf[10] = 0h from eb3f0028
[ 57.282640] e_bus: e_bus_buf[11] = 0h from eb3f002c
[ 57.282641] e_bus: e_bus_buf[12] = 0h from eb3f0030
[ 57.282643] e_bus: e_bus_buf[13] = 0h from eb3f0034
[ 57.282644] e_bus: e_bus_buf[14] = 0h from eb3f0038
[ 57.282645] e_bus: e_bus_buf[15] = 0h from eb3f003c
[ 57.282646] e_bus: e_bus_buf[16] = 0h from eb3f0040
[ 57.282648] e_bus: e_bus_buf[17] = 0h from eb3f0044
[ 57.282649] e_bus: e_bus_buf[18] = 0h from eb3f0048
[ 57.282650] e_bus: e_bus_buf[19] = 0h from eb3f004c
[ 57.282652] e_bus: e_bus_buf[20] = 0h from eb3f0050
[ 57.282653] e_bus: e_bus_buf[21] = 0h from eb3f0054
[ 57.282654] e_bus: e_bus_buf[22] = 0h from eb3f0058
[ 57.282655] e_bus: e_bus_buf[23] = 0h from eb3f005c
[ 57.282657] e_bus: e_bus_buf[24] = 0h from eb3f0060
[ 57.282658] e_bus: e_bus_buf[25] = 0h from eb3f0064
[ 57.282659] e_bus: e_bus_buf[26] = 0h from eb3f0068
[ 57.282661] e_bus: e_bus_buf[27] = 0h from eb3f006c
[ 57.282662] e_bus: e_bus_buf[28] = 0h from eb3f0070
[ 57.282663] e_bus: e_bus_buf[29] = 0h from eb3f0074
[ 57.282665] e_bus: e_bus_buf[30] = 0h from eb3f0078
[ 57.282666] e_bus: e_bus_buf[31] = 0h from eb3f007c
[ 57.282667] e_bus: e_bus_buf[32] = 0h from eb3f0080
[ 57.282668] e_bus: e_bus_buf[33] = 0h from eb3f0084
[ 57.282670] e_bus: e_bus_buf[34] = 0h from eb3f0088
[ 57.282671] e_bus: e_bus_buf[35] = 0h from eb3f008c
[ 57.282672] e_bus: e_bus_buf[36] = 0h from eb3f0090
[ 57.282673] e_bus: e_bus_buf[37] = 0h from eb3f0094
[ 57.282675] e_bus: e_bus_buf[38] = 0h from eb3f0098
[ 57.282676] e_bus: e_bus_buf[39] = 0h from eb3f009c
[ 57.282677] e_bus: Last word: 0h


видно, что First word: 24h (36), что соответствует действительности... но остальное...
причем иногда, но совсем редко можно получить такой пакет, что примерно соответствует правде

CODE
[ 57.581310] e_bus: got_irq irq=17 dev_id=f602d000 minor=0
[ 57.581313] e_bus: e_bus_read f=eb360900, buf=77590008, size = 40000000h, loff=eb2a7f98
[ 57.581315] e_bus: First word: 6ch (108) from eb378000
[ 57.581330] e_bus: got_irq irq=17 dev_id=f602d000 minor=0
[ 57.581354] e_bus: e_bus_buf[0] = 24h from eb378000
[ 57.581356] e_bus: e_bus_buf[1] = 1h from eb378004
[ 57.581357] e_bus: e_bus_buf[2] = 5h from eb378008
[ 57.581358] e_bus: e_bus_buf[3] = 20h from eb37800c
[ 57.581360] e_bus: e_bus_buf[4] = FFFF0000h from eb378010
[ 57.581361] e_bus: e_bus_buf[5] = 20001h from eb378014
[ 57.581362] e_bus: e_bus_buf[6] = 40003h from eb378018
[ 57.581364] e_bus: e_bus_buf[7] = 60005h from eb37801c
[ 57.581365] e_bus: e_bus_buf[8] = 80007h from eb378020
[ 57.581366] e_bus: e_bus_buf[9] = A0009h from eb378024
[ 57.581368] e_bus: e_bus_buf[10] = 0h from eb378028
[ 57.581369] e_bus: e_bus_buf[11] = 0h from eb37802c
[ 57.581370] e_bus: e_bus_buf[12] = 0h from eb378030
[ 57.581372] e_bus: e_bus_buf[13] = 0h from eb378034
[ 57.581373] e_bus: e_bus_buf[14] = 0h from eb378038
[ 57.581374] e_bus: e_bus_buf[15] = 0h from eb37803c
[ 57.581375] e_bus: e_bus_buf[16] = 0h from eb378040
[ 57.581377] e_bus: e_bus_buf[17] = 0h from eb378044
[ 57.581378] e_bus: e_bus_buf[18] = 0h from eb378048
[ 57.581379] e_bus: e_bus_buf[19] = 0h from eb37804c
[ 57.581381] e_bus: e_bus_buf[20] = 0h from eb378050
[ 57.581382] e_bus: e_bus_buf[21] = 0h from eb378054
[ 57.581383] e_bus: e_bus_buf[22] = 0h from eb378058
[ 57.581384] e_bus: e_bus_buf[23] = 0h from eb37805c
[ 57.581386] e_bus: e_bus_buf[24] = 0h from eb378060
[ 57.581387] e_bus: e_bus_buf[25] = 0h from eb378064
[ 57.581388] e_bus: e_bus_buf[26] = 0h from eb378068
[ 57.581390] e_bus: e_bus_buf[27] = 0h from eb37806c
[ 57.581391] e_bus: e_bus_buf[28] = 0h from eb378070
[ 57.581392] e_bus: e_bus_buf[29] = 0h from eb378074
[ 57.581394] e_bus: e_bus_buf[30] = 0h from eb378078
[ 57.581395] e_bus: e_bus_buf[31] = 0h from eb37807c
[ 57.581396] e_bus: e_bus_buf[32] = 0h from eb378080
[ 57.581398] e_bus: e_bus_buf[33] = 0h from eb378084
[ 57.581399] e_bus: e_bus_buf[34] = 0h from eb378088
[ 57.581400] e_bus: e_bus_buf[35] = 0h from eb37808c
[ 57.581401] e_bus: e_bus_buf[36] = 0h from eb378090
[ 57.581403] e_bus: e_bus_buf[37] = 0h from eb378094
[ 57.581404] e_bus: e_bus_buf[38] = 0h from eb378098
[ 57.581405] e_bus: e_bus_buf[39] = 0h from eb37809c
[ 57.581406] e_bus: Last word: 0h
[ 57.581407] e_bus: wrong signature 0h (0), expected 0xFACEDEAD


т.е. данные примерно правильные до строки [ 57.581368] e_bus: e_bus_buf[10] = 0h from eb378028

Почему так происходит не понимаю.... причем от меня все уходит хорошо....

Кстати, у меня возник такой вопрос, для того чтобы сигнал готовности от меня(irdy) был неактивен там, где я хочу, надо сигнал lm_rdyn на локальной стороне выставлять за такт до тех данных, которые я не хочу чтобы попали но сторону PCI, хотя по диаграмме надо выставлять в том же такте, что и безразличные данные...

Сигнал lm_last так же высталяется в тот же момент, что и ты заканчиваешь передачу... а на диаграмме нарисовано что за такт до последних данных...

Я приложил диаграммы с signaltab, где на
1й картинке, как я работаю с локальной стороной и что в этот момент происходит на шине PCI
на 2й картинке, начало этой же транзакции, но увеличено для того, чтобы можно видеть было, что я передаю
на 3й картинке, конец этой же транзакции, но увеличено для того, чтобы можно видеть было, что я передаю

Сейчас управляющие сигналы и данные у меня выставляются так:
CODE
//выставление данных на шину АД PCI
assign l_adi = (rdWorkInf == 1)? WorkInf: (fl_adr == 1)? adress: (EnableWritePCIMaster == 1 && StatePCI == 0)? SumOfCountForPCI: (StatePCI == 4)? DataForPCI:(StatePCI == 6)? 32'hFACE_DEAD: ( StatePCI == 7 || StatePCI == 2 || StatePCI == 3 || StatePCI == 5)? WorkDataForPCI: 32'h0000_0000;

assign lm_rdyn = ((StatePCI == 0 || (StatePCI == 4 && CurrentIndexOfCounting >= localMaxCounting)) && lm_ackn == 0) ? 1'b1: (StatePCI_Wr == 4 && lm_ackn == 0)? 1'b0: 1'b1;

assign lm_lastn = (lm_ackn == 0 && /*(StatePCI == 1 && (localIndexSumOfCounting >= localMaxSumOfCount))*/StatePCI == 6)? 1'b0:1'b1;


пробовал синхронизировать данные сигналы для того, чтобы хоть что-то получить на стороне ПК из того, что я реально передаю, вот таким образом:
CODE
reg [31:0] ladi;
assign l_adi = ladi;
always @(*)
begin
if(Res == 0) ladi <= 32'h0000_0000;
else if (rdWorkInf == 1) ladi <= WorkInf;
else if (fl_adr == 1) ladi <= adress;
else case(StatePCI)
0: if(EnableWritePCIMaster == 0) ladi <= SumOfCountForPCI;
7: ladi <= WorkDataForPCI;
2: ladi <= WorkDataForPCI;
3: ladi <= WorkDataForPCI;
5: ladi <= WorkDataForPCI;
4: ladi <= DataForPCI;
6: ladi <= 32'hFACE_DEAD;
endcase
end*/

/*
reg lmrdyn;

// выставление сигнала готовности на стороне мастера
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) lmrdyn <= 1;
else if(StatePCI == 0) lmrdyn <= 1; // ставим задержку в передаче при передаче на сторону PCI
else if (StatePCI == 4 && CurrentIndexOfCounting >= localMaxCounting) lmrdyn <= 1;
else if(lm_ackn == 0 && StatePCI_Wr == 4 ) lmrdyn <= 0;
else lmrdyn <= 1;

end */

/*lmlastn;
always @(posedge ClkPCI or negedge Res)
begin
if(Res == 0) lmlastn <= 1;
else case(StatePCI)
1: if(lm_ackn == 0 && (localIndexSumOfCounting >= localMaxSumOfCount)) lmlastn <= 0; //последняя пачка
default: lmlastn <= 1;
endcase
end */


Но результаты те же....

Я пробовал менять настройки pcicore, но ничего не получилось...

Вопрос:
Куда мне двигаться дальше?)))) На что обратить внимание?
XVR
Цитата
[ 57.282589] e_bus: First word: 24h (36) from eb3f0000
[ 57.282626] e_bus: e_bus_buf[0] = 0h from eb3f0000
Странно у вас - адрес один и тот же, а данные разные

Цитата
причем иногда, но совсем редко можно получить такой пакет, что примерно соответствует правде
...

[ 57.581310] e_bus: got_irq irq=17 dev_id=f602d000 minor=0
[ 57.581313] e_bus: e_bus_read f=eb360900, buf=77590008, size = 40000000h, loff=eb2a7f98
[ 57.581315] e_bus: First word: 6ch (108) from eb378000
[ 57.581330] e_bus: got_irq irq=17 dev_id=f602d000 minor=0
В первом пакете у вас один irq - это действительно так?

Пока похоже на неправильную работу с памятью и прерываниями (в Linux). У вас как память в драйвере заказывается?
xxxmatrixxx
Цитата(XVR @ Jul 15 2012, 12:45) *
Странно у вас - адрес один и тот же, а данные разные

В первом пакете у вас один irq - это действительно так?

Пока похоже на неправильную работу с памятью и прерываниями (в Linux). У вас как память в драйвере заказывается?

CODE
dev->e_bus_buf = pci_alloc_consistent(e_dev->epdev, E_BUS_BUF_SIZE, &e_dev->dma_handle);

из e_bus_buf читаются данные, dma_handle передается в регистр платы.

Обработка прерывания:

CODE
/*
* Обработчик прерывания
*/
static irqreturn_t e_bus_irq_handler(int irq, void* dev_id) {
e_bus_dev* dev = (e_bus_dev*)dev_id;
unsigned int minor = dev->minor;
debug_print("got_irq irq=%d dev_id=%p minor=%d", irq, dev_id, minor);
/*
* Снимаем прерывание
*/
if (!(readl((void*)(dev->reg_vaddr+E_BUS_REG_STATUS)) & E_BUS_STATUS_IRQ)) {
debug_print("not our irq, skipped");
return IRQ_NONE;
}

writel(E_BUS_IRQ_OFF, (void*)(e_bus_dev_list[minor].mem_vaddr));
/*
* Оповещаем пользователя
*/
e_bus_notify_user(minor,E_BUS_SIG_RX);
return IRQ_HANDLED;
}
XVR
Все вроде правильно, НО -
обратите внимание - у вас когда чтение происходит правильно приходит 2 прерывания, а когда неправильно - одно.
Еще попробуй те прочесть что нибудь из вышего устройства (любой регистр) перед чтением буфера (PCI hub может переставить транзакции на шине)
Еще не понятно, почему тут -
Цитата
[ 57.581315] e_bus: First word: 6ch (108) from eb378000
[ 57.581354] e_bus: e_bus_buf[0] = 24h from eb378000
разные данные. Судя по печати это выдается из одного и того же места буфера
xxxmatrixxx
Цитата(XVR @ Jul 16 2012, 12:11) *
Все вроде правильно, НО -
обратите внимание - у вас когда чтение происходит правильно приходит 2 прерывания, а когда неправильно - одно.
Еще попробуй те прочесть что нибудь из вышего устройства (любой регистр) перед чтением буфера (PCI hub может переставить транзакции на шине)
Еще не понятно, почему тут -
разные данные. Судя по печати это выдается из одного и того же места буфера


Проблема оказалась в том, что программист под Linux читал данные, а потом затирал их при обращении к Bar0...

Прерывания приходили из-за того, что я синхронизировал процесс, отвечающий за разрешение генерирования прерывания,не от частоты,
на которой работает мой модуль, а от clkPCI....

Сейчас все заработало...кажется)))) может косяки еще обнаружатся потом, но сейчас пока все нормуль)))

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