Программируемая логика - это не так уж и сложно. Разберемся вместе.
Ответить

ULPI

Ср ноя 16, 2022 15:25:38

Доброго времени суток.

Уже несколько недель тщетно пытаюсь побороть ULPI. Вроде бы с самим протоколом разобрался и, если я правильно понимаю, моя проблема кроется либо в описании временных ограничений(в этом я не очень силен), либо в колхозности платы(сделано все на макетке, фото приложу ниже). Проблема имеется только с отправкой данных, поэтому далее речь пойдет только о трансмиттере.

Кратко опишу, как это работает. В модуле трансмиттера имеется 2 FIFO буфера. Один нужун для непосредственно данных(TXCMD в том числе), второй для количества передаваемых байт. Соответственно
1. Сначала детектируется то, что второй буфер не пуст
2. Считывается количество байт
3. Считывается первый байт
4. По сигналу NXT считываются следующие байты
5. По окончанию считывания генерируется STP
6. Из-за разности размера входной и выходной шины FIFO ненужные данные читаются в пустую

FPGA использую EP4CE6E22C8(Intel), трансивер FUSB2805, пишу на SystemVerilog.

Код модуля трансмиттера:
Спойлер
Код:
module ULPI_TX(
input CLK,
input DIR,
input NXT,
output bit STP,
output bit [7:0] DATA,

input OUT_FIFO_wrclk,
input OUT_FIFO_wren,
input [31:0] OUT_FIFO_data,
output bit OUT_FIFO_wrempty,
output bit [6:0] OUT_FIFO_wrusedw,

input BYTES_wrclk,
input BYTES_wren,
input [31:0] BYTES_data
);

logic [7:0] DATA_d;

logic rden_trig = 0;
logic rden_trig_d;
logic rden_trig_edge;
always_ff @(posedge CLK)
   rden_trig_d<=rden_trig;
assign rden_trig_edge=rden_trig^rden_trig_d;
   
logic rden;

always_ff @(posedge CLK)
if (rden)
   DATA<=DATA_d;

assign rden = (NXT|rden_trig_edge);

logic rdempty;

ULPI_MEM_OUT mem_out (
   .data(OUT_FIFO_data),
   .rdclk(CLK),
   .rdreq(rden),
   .wrclk(OUT_FIFO_wrclk),
   .wrreq(OUT_FIFO_wren),
   .q(DATA_d),
   .rdempty(rdempty),
   .wrempty(OUT_FIFO_wrempty),
   .wrusedw(OUT_FIFO_wrusedw)
);
logic [31:0] BYTES_q;
logic BYTES_rden;
logic BUFE;                                    //Buffer empty

ULPI_MEM_OUT_bytes mem_out_b (
   .data(BYTES_data),
   .rdclk(CLK),
   .rdreq(BYTES_rden),
   .wrclk(BYTES_wrclk),
   .wrreq(BYTES_wren),
   .q(BYTES_q),
   .rdempty(BUFE)
);

logic [31:0] bytes_cnt;

enum bit [2:0] {BUFE_detecting, BUFFER_broadcast, NOT_VALID_BYTES_flush} STAGE = BUFE_detecting;

logic [1:0] minor_substages = 0;

always_ff @(posedge CLK)
begin
   if (STAGE==BUFE_detecting)
   begin
      case (minor_substages)
         0:   if (!BUFE)
            begin
               minor_substages<=minor_substages+1'b1;
               BYTES_rden<=1;
            end
            
         1:   begin
               BYTES_rden<=0;
               minor_substages<=minor_substages+1'b1;
            end
         2:   begin
               if (!DIR)
               begin
                  minor_substages<=minor_substages+1'b1;
                  rden_trig<=!rden_trig;
               end
            end
         3:   begin
               bytes_cnt<=BYTES_q-1;
               minor_substages<=0;
               STAGE<=BUFFER_broadcast;
               rden_trig<=!rden_trig;
            end
      endcase
   end
   
   if (STAGE==BUFFER_broadcast)
   begin
      if (NXT)
         bytes_cnt<=bytes_cnt-1;
      if ((bytes_cnt==0)&(NXT))
      begin
         STP<=1;
         STAGE<=NOT_VALID_BYTES_flush;
      end
   end
   
   if (STAGE==NOT_VALID_BYTES_flush)
   begin
      STP<=0;
      if (!rdempty)
         rden_trig<=!rden_trig;
      else
         STAGE<=BUFE_detecting;
   end
end
endmodule


Код временных ограничений:

Спойлер
Код:
derive_clock_uncertainty

create_clock -name clk60 -period 60MHz [get_ports {ULPI_CLK}]
create_clock -period 60MHz -name {virt_clk_60}

set_output_delay -clock [ get_clocks {virt_clk_60} ] -max 7 [get_ports {ULPI_DATA[0] ULPI_DATA[1] ULPI_DATA[2] ULPI_DATA[3] ULPI_DATA[4] ULPI_DATA[5] ULPI_DATA[6] ULPI_DATA[7] ULPI_STP}]

set_output_delay -clock [ get_clocks {virt_clk_60} ] -min -1 [get_ports {ULPI_DATA[0] ULPI_DATA[1] ULPI_DATA[2] ULPI_DATA[3] ULPI_DATA[4] ULPI_DATA[5] ULPI_DATA[6] ULPI_DATA[7] ULPI_STP}]


Фото платы трансивера:

СпойлерИзображение Изображение


P.S. Вроде бы всё описал. Слёзно прошу помощи.

Re: ULPI

Ср ноя 16, 2022 18:30:10

Изображение

Сурово :)
Проблема имеется только с отправкой данных

Т.е. данные принимаются нормально?

60 МГц для FIFO 4-го циклона вообще не частота.
Что есть из доступных средств отладки?

Re: ULPI

Ср ноя 16, 2022 19:43:15



Согласен, не самое лучшее исполнение. Но пока что какое есть. Заказал себе платку на usb3300, но приедет она недели через 2 в лучшем случае.

Gudd-Head писал(а):
Проблема имеется только с отправкой данных

Т.е. данные принимаются нормально?


Да, с приемом проблем никаких нет

Gudd-Head писал(а):Что есть из доступных средств отладки?


Есть такая плата с китайским usb blaster
http://piswords.com/alteraep4ce6e.html

Помимо этого есть осциллограф https://www.conrad.com/p/voltcraft-dso- ... cs-1589987
и логический анализатор https://www.perytech.com/Logic-Analyzer.htm

Re: ULPI

Ср ноя 16, 2022 19:49:52

Ну то есть есть, чем посмотреть времянку.
Временные соотношения сигналов соответствуют задуманным?

Re: ULPI

Ср ноя 16, 2022 20:27:43

Временные соотношения сигналов соответствуют задуманным?


Впринципе очень даже. Вот такое показывает осциллограф. Это сигнал STP, который по timing analyzer самый глючный (на нем слак хоть и положительный, но самый низкий)
Изображение

В signal tap был такой симптом еще, когда я еще не прописал констрэйны: данные, которые выходили из памяти и данные на выходных триггерах были разными, как будто на каких-то линиях сигнал слишком задержанный и не успел защелкнуться
Ответить