Доброго времени суток.
Уже несколько недель тщетно пытаюсь побороть 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. Вроде бы всё описал. Слёзно прошу помощи.