我们用latticeu uvc方案现在发现音频接有的高清播放器他会卡顿。我们抓取usb的isoc数据,发现我们的数据是1692和1880交替,实际按uvc应该是 稳定传输1920数据。
下面的数据是我们的,另外一端是抓取和我们一个方式的其他家卡他稳定1920.
gpif_sf_cntl.v中 373行不是很明白,麻烦大伙帮我们分析一下这个问题。
audio_cnt <= 7'd46;
if (afifo_status > 700) begin
audio_cnt <= 7'd47;
end else if (afifo_status < 100) begin
audio_cnt <= 7'd45;
end
我们的数据:
Bus Hound 6.01 capture on Windows Vista Service Pack 1 (x64). Complements of www.perisoft.net
Device - Device ID (followed by the endpoint for USB devices)
(29) USB Composite Device
(32) ZhongAn USB 3.0 UAC Audio
(35) USB Composite Device
(37) LXHF-710 Audio
Length - Total transfer length
Phase - Phase Type
ISOC Isochronous transfer
Data - Hex dump of the data transferred
Descr - Description of the phase
Cmd... - Position in the captured data
Date - Date the phase occurred in year/month/day form
Time - Time the phase occurred in hour:minute:second.millisec form
Device Length Phase Data Description Cmd.Phase.Ofs(rep) Date Time
------ -------- ----- ------------------------------------------------------------------------------------------------------ -------------------------------- ------------------ ---------- ------------
32.1 1692 ISOC 4d 03 65 03 c3 03 48 03 37 04 c9 03 4b 04 3c 04 M.e...H.7...K.<. 1.1.0 2019/05/12 23:34:58.441
32.1 1880 ISOC 66 01 b0 01 1c 01 6b 01 b6 00 21 01 39 00 b0 00 f.....k...!.9... 2.1.0 2019/05/12 23:34:58.451
32.1 1692 ISOC 23 03 04 03 2f 03 22 03 32 03 36 03 4e 03 32 03 #.../.".2.6.N.2. 3.1.0 2019/05/12 23:34:58.461
32.1 1692 ISOC da 01 0a 02 e2 01 d5 01 08 02 e1 01 19 02 0a 02 ................ 4.1.0 2019/05/12 23:34:58.471
32.1 1880 ISOC 1a 02 10 02 19 02 1b 02 0e 02 19 02 0b 02 0d 02 ................ 5.1.0 2019/05/12 23:34:58.481
32.1 1692 ISOC 59 fc 5b fc 55 fc 59 fc 41 fc 55 fc 2d fc 43 fc Y.[.U.Y.A.U.-.C. 6.1.0 2019/05/12 23:34:58.491
32.1 1880 ISOC 67 f9 6b f9 65 f9 67 f9 6f f9 65 f9 7f f9 71 f9 g.k.e.g.o.e...q. 7.1.0 2019/05/12 23:34:58.501
另外一家正常的抓取的数据:他稳定传输1920,音频是正常的。
Device Length Phase Data Description Cmd.Phase.Ofs(rep) Date Time
------ -------- ----- ------------------------------------------------------------------------------------------------------ -------------------------------- ------------------ ---------- ------------
37.1 1920 ISOC fc ff fa ff fb ff fa ff fb ff fa ff fc ff fa ff ................ 1.1.0 2019/05/12 23:39:44.225
37.1 1920 ISOC f3 ff ef ff f3 ff ef ff f3 ff ef ff f3 ff f0 ff ................ 2.1.0 2019/05/12 23:39:44.235
37.1 1920 ISOC f5 ff fa ff f5 ff fa ff f5 ff fa ff f6 ff fa ff ................ 3.1.0 2019/05/12 23:39:44.245
37.1 1920 ISOC f6 ff f7 ff f6 ff f7 ff f6 ff f6 ff f6 ff f7 ff ................ 4.1.0 2019/05/12 23:39:44.255
37.1 1920 ISOC fd ff f8 ff fd ff f8 ff fd ff f8 ff 00 00 f9 ff ................ 5.1.0 2019/05/12 23:39:44.265
37.1 1920 ISOC f8 ff f9 ff f7 ff f9 ff f7 ff f9 ff f6 ff f9 ff ................ 6.1.0
gpif_sf_cntl.v完整源码如下:
// --------------------------------------------------------------------
// Copyright (c) 2014 by Lattice Semiconductor Corporation
// --------------------------------------------------------------------
//
// Permission:
//
// Lattice Semiconductor grants permission to use this code for use
// in synthesis for any Lattice programmable logic product. Other
// use of this code, including the selling or duplication of any
// portion is strictly prohibited.
//
// Disclaimer:
//
// This VHDL or Verilog source code is intended as a design reference
// which illustrates how these types of functions can be implemented.
// It is the user's responsibility to verify their design for
// consistency and functionality through the use of formal
// verification methods. Lattice Semiconductor provides no warranty
// regarding the use or functionality of this code.
//
// --------------------------------------------------------------------
//
// Lattice Semiconductor Corporation
// 5555 NE Moore Court
// Hillsboro, OR 97214
// U.S.A
//
// TEL: 1-800-Lattice (USA and Canada)
// 503-268-8001 (other locations)
//
// web: http://www.latticesemi.com/
// email: techsupport@latticesemi.com
//
// --------------------------------------------------------------------
//
// Project: PC Camera (HDMI-to-USB3.0) Bridge design
// File: gpif_sf_cntl.v
// Title: gpif_sf_cntl
// Description: This module generates the proper timing and sequence
// of the GPIF II Slave FIFO interface.
//
// --------------------------------------------------------------------
// Author : D. Wang
// $Revision: 1.0 $
// Author : B. Snajder (Mikroprojekt, Croatia)
// $Revision: 2.0 $
// Author : B. Snajder (Mikroprojekt, Croatia)
// $Revision: 2.1 $
// --------------------------------------------------------------------
// This moddule implements the control signals and timing of the FX3 GPIF II Synchronous Slave FIFO interface.
// EZ-USB FX3 provides four physical hardware threads (sockets). This design writes audio or video data
// into one of the two threads over the GPIF II interface and automatically switches between them.
// A dedicated thread flag (full/notfull) is assocated with each thread to indicate the availability of the FIFO.
//
// *** This version will only switch thread when the current thread is filled up ***
//
// For this application, it only requires write operation from the FPGA to the FX3 USB through GPIF II.
// In the future, we may support Read operaton from FX3 USB to FPGA for configuration/reset purpose.
// *** Design Note - Threads and Flags
// The following discussion is based on Cypress's technote AN65974.pdf.
// 1. The EZ-USB FX3 provides as many as four physical threads for data transfer over the GPIF II.
// In this design, we map Video_FIFO_A, Vidoe_FIFO_B and Audio_FIFO to 3 out of four threads,
// such that the data transfter from different FIFOs won't conflict wtih each other.
// 2. Flags are associated with specific threads. FX3 can be configured to support 2 types of thread flags.
// - Dedicated Thread Flag indicates the status of a particular thread
// - Current Thread Flag indicates the status of the currently addressed thread
// Because there are only two flags (FLAGA and FLAGB), and we have 3 threads, Current Thread flag
// is the only choise, unless the FX3 can support 3 dedicated thread flags.
// 3. Flags indicate empty or full based on the direction of the thread operation.
// [Comment by Andrew Tamoney (Cypress)]:
// The flag signifies "DMA ready" which means you have space to write into the buffer or that you have data
// to read from the buffer. However, if you do wish to use a flag a Empty/not Empty you could use the
// DMA Watermark flag instead of DMA ready. You could then configure the watermark value with CyU3PGpifSocketConfigure.
// 4. For synchronous slave FIFO, two-cycle latency is incurred when the Current-Thread flag is used.
// Becuase the GPIF II first must sample the address and then update the flag.
// 5 Each slave FIFO thread is defined as 16K-deep buffer which size exceeds the maximum number of video
// horizontal pixels and maximum number of audio packets per frame. A short packet can be committed to the USB host
// by asserting sf_pktend_n signal along with the last word of data and sf_wr_n pulse corresponding to the last word.
// *** 3/12/2014 -- Updated by David Wang
// change the Dedicated Thread Flag to Current Thread Flag. It incurs two-cycle latency starting when a
// a valid address is presented on the interface. On the third clock edge after this, the valid state of
// the FLAG of the newly addressed thread can be sampled.
// *** 6/4/2014 -- Updated by Boris Snajder
// GPIF II interface now reads data from Video and Audio FIFO. Video FIFO is associated with addresses 0 and 1,
// while Audio FIFO is associated with address 2 and 3.
// *** 13/05/2015 -- Updated by Boris Snajder
// Improved audio clock sync
// Video is not interrupted in order to transfer audio
// Video is flushed with pktend when unexpected vsync is detected
module gpif_sf_cntl (
//clocks, resets, control pins
input wire clk,
input wire rstn,
input wire srst,
input wire video_en,
// Video Audio Multiplexor interface
output wire vfifo_rden,
input wire[33:0] vfifo_data,
input wire vfifo_aempty,
input wire vfifo_afull,
output wire afifo_rden,
input wire[31:0] afifo_data,
input wire afifo_aempty,
input wire afifo_afull,
input wire [10:0] afifo_status,
//GPIF II slave fifo interface , 32bit data, 2bit address
output wire sf_clk,
output wire sf_rst_n,
output wire [31:0] sf_data,
output wire [1:0] sf_addr,
output wire sf_cs_n,
output wire sf_we_n,
output wire sf_rd_n,
output wire sf_oe_n,
output wire sf_epswitch_n,
output wire sf_pktend_n,
input wire sf_flaga,
input wire sf_flagb,
//GPIF II status
input wire overflow_err,
output wire overflow_done,
input wire audio_disable,
// for debug
output wire [31:0] tx_error_count
);
//clocks and reset
wire clk_100m = clk;
wire rst_n = rstn;
localparam STATE_IDLE = 0;
localparam STATE_VFLAGCHK = 1;
localparam STATE_AFLAGCHK = 2;
localparam STATE_VTX = 3;
localparam STATE_ATX = 4;
localparam STATE_TURN = 5;
localparam STATE_ERROR = 6;
localparam STATE_RELEASEHOLD = 7;
reg sf_cs_n_int;
reg sf_we_n_int;
wire [1:0] sf_addr_int;
reg [31:0] sf_data_int;
//reg sf_epswitch_n_int;
reg sf_pktend_n_int;
reg[3:0] sf_wr_stat;
wire sf_wr_full;
reg sf_rstn_int;
reg vfifo_rden_int;
reg vfifo_rden_int_d;
reg vfifo_rden_int_2d;
reg afifo_rden_int;
reg afifo_rden_int_d;
reg[2:0] flagchk_cnt;
reg video_addr;
reg audio_addr;
wire pktend_int;
wire pktend_short_int;
reg pktend_int_d;
reg apktend_int_d;
reg apktend_int_2d;
reg apktend_int_3d;
reg pktend_short_int_d;
reg pktend_short_int_2d;
reg pktend_short_int_3d;
reg pktend_int_2d;
reg pktend_int_3d;
reg av_sel;
reg a_lo_addr;
reg v_lo_addr;
reg lo_addr;
reg overflow_err_d;
reg error_d;
reg [6:0] audio_cnt;
reg audio_cnt_d;
reg overflow_req;
reg overflow_req_d;
reg overflow_req_2d;
reg video_pkt_active;
reg pkt_terminate;
reg vdata_hold;
reg [31:0] vfifo_data_d;
reg hold_release;
reg hold_release_d;
reg hold_release_2d;
reg end_transfer;
reg overflow_err_int;
reg overflow_done_i;
reg audio_start;
reg [11:0] timeout_cnt;
reg [31:0] tx_error_count_r;
assign tx_error_count = tx_error_count_r;
//tristate enable logic for the data bus
//wire[31:0] sf_data = sf_data_out_en ? sf_data_int : 32'hzzzzzzzz;
// *** Byte swapping due to Cypress software requirement ***
assign sf_data = {sf_data_int[7:0], sf_data_int[15:8], sf_data_int[23:16], sf_data_int[31:24]};
assign sf_addr = sf_addr_int[1:0];
assign sf_cs_n = sf_cs_n_int;
assign sf_we_n = sf_we_n_int;
assign sf_rd_n = sf_flaga; // 1'b1; //sf_rd_n_int;
assign sf_oe_n = 1'b1; //sf_oe_n_int;
assign sf_epswitch_n = 1'b1; //sf_epswitch_n_int;
assign sf_pktend_n = sf_pktend_n_int;
assign sf_rst_n = sf_rstn_int; //rst_n;
assign sf_clk = clk_100m;
reg [1:0] error_state_d;
always @(negedge rstn or posedge clk) begin
if (~rstn)
error_state_d <= 2'b0;
else
if (sf_wr_stat == STATE_ERROR)
error_state_d <= {error_state_d[0], 1'b1};
else
error_state_d <= {error_state_d[0], 1'b0};
end
always @(negedge rstn or posedge clk) begin
if (~rstn)
tx_error_count_r <= 16'h0000;
else
if (error_state_d == 2'b01)
tx_error_count_r <= tx_error_count_r + 1;
end
// Synchronize reset
always @(negedge rstn or posedge clk) begin
if (~rstn)
sf_rstn_int <= 1'b0;
else if (srst)
sf_rstn_int <= 1'b0;
else
sf_rstn_int <= 1'b1;
end
always @(negedge rstn or posedge clk) begin
if (~rstn)
overflow_err_int <= 1'b0;
else if (srst)
overflow_err_int <= 1'b0;
else
if (overflow_err_int == 1'b1 && sf_wr_stat == STATE_ERROR) begin
overflow_err_int <= 1'b0;
end else if (overflow_err_int == 1'b0 && overflow_err == 1'b1) begin
overflow_err_int <= 1'b1;
end
end
// Selected thread availability (1= Not_full; 0= Full)
//assign sf_wr_full = (sf_addr_int[0])? sf_flagb : sf_flaga; // 2-thread, Current Thread Flag
assign sf_wr_full = sf_flaga; // <-- Current Thread Flag
always @ (posedge clk_100m or negedge rst_n)
begin
if (~rst_n) begin
sf_cs_n_int <= 1'b1;
sf_pktend_n_int <= 1'b1;
flagchk_cnt <= 0;
vfifo_rden_int <= 1'b0;
afifo_rden_int <= 1'b0;
av_sel <= 1'b0;
v_lo_addr <= 1'b0;
a_lo_addr <= 1'b0;
lo_addr <= 1'b0;
overflow_req <= 1'b0;
end
else if (srst) begin
sf_cs_n_int <= 1'b1;
sf_pktend_n_int <= 1'b1;
vfifo_rden_int <= 1'b0;
av_sel <= 1'b0;
flagchk_cnt <= 0;
vfifo_rden_int <= 1'b0;
afifo_rden_int <= 1'b0;
v_lo_addr <= 1'b0;
a_lo_addr <= 1'b0;
lo_addr <= 1'b0;
overflow_req <= 1'b0;
end
else begin
sf_pktend_n_int <= 1'b1;
if (~av_sel) begin
sf_pktend_n_int <=~((pktend_short_int_d) && (~pktend_short_int_2d));// && (~pktend_short_int_d)); //&& (~apktend_int_d);
end else begin
sf_pktend_n_int <= ~(apktend_int_2d && (~apktend_int_3d));
end
// State transitions
case(sf_wr_stat)
STATE_IDLE : begin
sf_cs_n_int <= 1'b0;
vfifo_rden_int <= 1'b0;
afifo_rden_int <= 1'b0;
lo_addr <= v_lo_addr;
if ((afifo_afull == 1'b1) && (av_sel==1'b0)) begin
flagchk_cnt <= 3'b011; //we need to wait for 3 clocks for flag assertion
av_sel <= 1'b1; //audio
lo_addr <= a_lo_addr;
sf_cs_n_int <= 1'b0;
end else if (vfifo_afull == 1'b1 || overflow_err_int) begin
flagchk_cnt <= 3'b011;//we need to wait for 3 clocks for flag assertion
av_sel <= 1'b0; //video
//lo_addr <= v_lo_addr;
sf_cs_n_int <= 1'b0;
end else begin
//av_sel <= 1'b1; //audio
if (vfifo_aempty == 1'b1) begin
av_sel <= 1'b0; //audio
end
end
if (overflow_req == 1'b1) begin
overflow_req <= 1'b0;
end
if (error_d == 1'b1 && sf_pktend_n_int == 1'b0 && sf_we_n_int == 1'b0) begin
v_lo_addr <= !v_lo_addr;
end
if ( ~video_en) begin
v_lo_addr <= 1'b0;
end
end
STATE_VFLAGCHK : begin //wait for flag
flagchk_cnt <= flagchk_cnt - 1'b1;
vfifo_rden_int <= 1'b0;
afifo_rden_int <= 1'b0;
av_sel <= 1'b0;
sf_cs_n_int <= 1'b0;
end
STATE_AFLAGCHK : begin//wait for flag
flagchk_cnt <= flagchk_cnt - 1'b1;
afifo_rden_int <= 1'b0;
av_sel <= 1'b1;
sf_cs_n_int <= 1'b0;
audio_cnt <= 7'd46;
if (afifo_status > 700) begin
audio_cnt <= 7'd47;
end else if (afifo_status < 100) begin
audio_cnt <= 7'd45;
end
//audio_cnt <= 7'd47;
end
STATE_VTX: begin
if (overflow_err_int) begin //if video fifo overflows we need to terminate packet
vfifo_rden_int <= 1'b0;
end else begin
if (((pktend_int) || (pktend_short_int)) && (vfifo_rden_int_d) ) begin //if we detect pktend bit asserted in fifo we will terminate packet
vfifo_rden_int <= 1'b0;
end else begin
vfifo_rden_int <= 1'b1;
end
end
flagchk_cnt <= 3'b001;
av_sel <= 1'b0;
sf_cs_n_int <= 1'b0;
end
STATE_ATX: begin
afifo_rden_int <= 1'b1;
flagchk_cnt <= 3'b001;
av_sel <= 1'b1;
sf_cs_n_int <= 1'b0;
audio_cnt <= audio_cnt - 1;
end
STATE_TURN: begin //before we change address and thread we need to be sure that all data has propagated to the FX3
vfifo_rden_int <= 1'b0;
afifo_rden_int <= 1'b0;
flagchk_cnt <= flagchk_cnt - 1;
sf_cs_n_int <= (!vfifo_rden_int_2d) && (!afifo_rden_int_d);
end
STATE_ERROR: begin //terminate packet in case of video fifo overflow
overflow_req <= 1'b1;
av_sel <= 1'b0; //video
lo_addr <= v_lo_addr;
vfifo_rden_int <= 1'b0;
//if ((pkt_terminate == 1'b1) && (overflow_req_2d == 1'b0) && (overflow_req_d == 1'b1)) begin
//if ((overflow_req_2d == 1'b0) && (overflow_req_d == 1'b1)) begin
if (sf_wr_full && (overflow_req_2d == 1'b1) && (overflow_req_d == 1'b1) && video_pkt_active == 1'b1) begin
sf_cs_n_int <= 1'b0;
sf_pktend_n_int <= 1'b0;
end else begin
sf_cs_n_int <= 1'b1;
sf_pktend_n_int <= 1'b1;
end
end
STATE_RELEASEHOLD: begin
vfifo_rden_int <= 1'b0;
afifo_rden_int <= 1'b0;
av_sel <= 1'b0;
sf_cs_n_int <= 1'b0;
end
endcase
//when pktend is asserted we need to change address
if ((~av_sel)) begin
//if ((((pktend_int_2d) || (pktend_short_int_2d)) && sf_cs_n_int == 1'b0 && sf_we_n_int == 1'b0) || (sf_wr_full && (overflow_req_2d == 1'b1) && (overflow_req_d == 1'b1))) begin
if ((((pktend_int_2d) || (pktend_short_int_2d)) && sf_cs_n_int == 1'b0 && sf_we_n_int == 1'b0) ) begin
v_lo_addr <= !v_lo_addr;
end
if (sf_wr_stat == STATE_ERROR && sf_pktend_n_int == 1'b0 && sf_we_n_int == 1'b0) begin
v_lo_addr <= !v_lo_addr;
end
end else begin
//if (sf_pktend_n_int == 1'b0) begin
if (apktend_int_2d && sf_cs_n_int == 1'b0) begin
a_lo_addr <= !a_lo_addr;
end
end
//if we were muted make sure that we will start from address 2
if (audio_disable == 1'b1) begin
a_lo_addr <= 1'b0;
end
end
end
//if bit1 of sd_addr_int==0 then we are sending video, if 1 we are sending audio
assign sf_addr_int = {av_sel,lo_addr};
always @ (posedge clk_100m or negedge rst_n)
begin
if (~rst_n) begin
sf_wr_stat <= STATE_IDLE;
end
else if (srst) begin
sf_wr_stat <= STATE_IDLE;
end
else begin
// State transitions
case(sf_wr_stat)
STATE_IDLE : begin
//in idle state we check if there is anything in fifos.
//if (overflow_err && video_pkt_active) begin
//if (overflow_err) begin
// sf_wr_stat <= STATE_ERROR;
//end else
if ((afifo_afull == 1'b1) && (av_sel==1'b0) && (audio_disable == 1'b0)) begin //if audio is muted do not send any audio; av_sel==0 => we prioritaize audio but if audio fifo is always full and we
//are unable to send anything make sure that we will handle video as well
sf_wr_stat <= STATE_AFLAGCHK;
end else if (vfifo_afull == 1'b1 || overflow_err_int) begin
sf_wr_stat <= STATE_VFLAGCHK;
end else begin
sf_wr_stat <= STATE_IDLE;
end
end
//if there is data in video FIFO we assert address for video fifo and wait for flag
STATE_VFLAGCHK : begin
if (flagchk_cnt[2] == 1'b1) begin
if ((sf_wr_full) && overflow_err_int) begin
sf_wr_stat <= STATE_ERROR;
end else if ((sf_wr_full) && (~overflow_err_int)) begin
if (vdata_hold) begin
sf_wr_stat <= STATE_RELEASEHOLD;
end else begin
sf_wr_stat <= STATE_VTX;
end
end else begin
sf_wr_stat <= STATE_IDLE;
end
end else begin
sf_wr_stat <= STATE_VFLAGCHK;
end
end
//if there is data in audio FIFO we assert address for audio fifo and wait for flag
STATE_AFLAGCHK : begin
if (flagchk_cnt[2] == 1'b1) begin
if (sf_wr_full && audio_start) begin
sf_wr_stat <= STATE_ATX;
end else begin
sf_wr_stat <= STATE_IDLE;
end
end else begin
sf_wr_stat <= STATE_AFLAGCHK;
end
end
STATE_RELEASEHOLD : begin
sf_wr_stat <= STATE_VTX;
end
//in this state we are sending video data
STATE_VTX : begin
//we will stop if we detected pktend or fifo is Empty
if ((vfifo_aempty || timeout_cnt[11]) || (((pktend_int) || (pktend_short_int)) && (vfifo_rden_int_d)) ) begin
sf_wr_stat <= STATE_TURN;
end else if (overflow_err_int) begin
//sf_wr_stat <= STATE_ERROR;
sf_wr_stat <= STATE_IDLE;
end else begin
sf_wr_stat <= STATE_VTX;
end
end
//in this state we are sending audio data
STATE_ATX : begin
//we will stop if fifo is empty of we have send 48 words of audio
if ((afifo_aempty) || (audio_cnt[6] == 1'b1)) begin
sf_wr_stat <= STATE_TURN;
end else begin
sf_wr_stat <= STATE_ATX;
end
end
//in this state we wait for all data to propagate to FX3 before we change address
STATE_TURN : begin
if (flagchk_cnt[2] == 1'b1) begin
if (overflow_err_int) begin
//sf_wr_stat <= STATE_ERROR;
sf_wr_stat <= STATE_IDLE;
end else begin
sf_wr_stat <= STATE_IDLE;
end
end else begin
sf_wr_stat <= STATE_TURN;
end
end
//we need to go into this state in case we need to terminate packet because of overflow
STATE_ERROR : begin
/*if (overflow_err == 1'b1 || (overflow_req_2d == 1'b0)) begin
sf_wr_stat <= STATE_ERROR;
end else begin
sf_wr_stat <= STATE_IDLE;
end */
//if (video_pkt_active == 1'b0 && (overflow_req_2d == 1'b1) && (overflow_req_d == 1'b1)) begin
// sf_wr_stat <= STATE_IDLE;
//end else
if (sf_wr_full && (overflow_req_2d == 1'b1) && (overflow_req_d == 1'b1)) begin
sf_wr_stat <= STATE_IDLE;
end else begin
sf_wr_stat <= STATE_ERROR;
end
end
endcase
end
end
always @(posedge clk_100m or negedge rst_n)
begin
if (~rst_n) begin
timeout_cnt <= 12'd0;
end else if (srst) begin
timeout_cnt <= 12'd0;
end else begin
if (sf_wr_stat == STATE_VFLAGCHK) begin
timeout_cnt <= 12'd900;
end if (sf_wr_stat == STATE_VTX) begin
if (timeout_cnt[11] == 1'b0) begin
timeout_cnt <= timeout_cnt - 1;
end
end
end
end
always @ (posedge clk_100m or negedge rst_n)
begin
if (~rst_n) begin
hold_release <= 1'b0;
hold_release_d <= 1'b0;
hold_release_2d <= 1'b0;
end else if (srst || ~video_en) begin
hold_release <= 1'b0;
hold_release_d <= 1'b0;
hold_release_2d <= 1'b0;
end else begin
if (sf_wr_stat == STATE_RELEASEHOLD) begin
hold_release <= 1'b1;
end else begin
hold_release <= 1'b0;
end
hold_release_d <= hold_release;
hold_release_2d <= hold_release_d;
end
end
always @ (posedge clk_100m or negedge rst_n)
begin
if (~rst_n) begin
video_pkt_active <= 1'b0;
end else if (srst || ~video_en) begin
video_pkt_active <= 1'b0;
end else begin
if (~av_sel) begin
//video packet is active from the moment we start sending it until it is terminated with pktend
/*if ((~sf_pktend_n_int) || (pktend_short_int_2d)) begin
video_pkt_active <= 1'b0;
end else if ((vfifo_rden_int == 1'b1) && (overflow_err == 1'b0)) begin
video_pkt_active <= 1'b1;
end */
if (sf_we_n_int == 1'b0) begin
video_pkt_active <= 1'b1;
if (pktend_int_2d || pktend_short_int_2d || sf_pktend_n_int == 1'b0) begin
video_pkt_active <= 1'b0;
end
end
end
end
end
always @ (posedge clk_100m or negedge rst_n)
begin
if (~rst_n) begin
pkt_terminate <= 1'b0;
end else if (srst) begin
pkt_terminate <= 1'b0;
end else begin
//detect cases when we will need to terminate packet in case of overflow
if ((overflow_err_int == 1'b1) &&(overflow_err_d == 1'b0)) begin
if (video_pkt_active == 1'b1) begin//we are in the middle of packet and we need to terminate it
pkt_terminate <= 1'b1;
end
if (sf_wr_stat == STATE_VTX) begin //if overflow happend when we are finishing packet, we do not need to terminate it
if ((pktend_short_int == 1'b1) || (pktend_int == 1'b1)) begin
pkt_terminate <= 1'b0;
end
end
if (sf_wr_stat == STATE_TURN) begin //if overflow happened when we are finishing packet, we do not need to terminate it
if ((pktend_short_int_d == 1'b1) || (pktend_int_d == 1'b1) || (pktend_short_int_2d == 1'b1) || (pktend_int_2d == 1'b1)) begin
pkt_terminate <= 1'b0;
end
end
end
if (sf_wr_stat == STATE_ERROR) begin
if (overflow_req_d == 1'b1) begin
pkt_terminate <= 1'b0;
end
end
end
end
assign vfifo_rden = vfifo_rden_int;
assign afifo_rden = afifo_rden_int;
always @ (posedge clk_100m or negedge rst_n)
begin
if (~rst_n) begin
sf_we_n_int <= 1'b1;
sf_data_int <= 32'b0;
vfifo_data_d <= 32'b0;
end else if (srst) begin
sf_we_n_int <= 1'b1;
sf_data_int <= 32'b0;
vfifo_data_d <= 32'b0;
end else begin
if (sf_wr_stat == STATE_ERROR) begin
//if ((overflow_req_2d == 1'b0) && (overflow_req_d == 1'b1)) begin
if (sf_wr_full && (overflow_req_2d == 1'b1) && (overflow_req_d == 1'b1)) begin
sf_we_n_int <= 1'b0;
end else begin
sf_we_n_int <= 1'b1;
end
end else begin
if (afifo_rden_int_d) begin
sf_we_n_int <= 1'b0;
end else begin
//if (((vfifo_rden_int_2d) && (!pktend_int_2d && !pktend_short_int_2d)) || (hold_release_2d)) begin
if (((vfifo_rden_int_2d) && (!end_transfer)) || (hold_release_2d)) begin
sf_we_n_int <= 1'b0;
end else begin
sf_we_n_int <= 1'b1;
end
end
//sf_we_n_int <= (!vfifo_rden_int_2d) && (!afifo_rden_int_d);
end
if (vfifo_rden_int_d) begin
vfifo_data_d <= vfifo_data[31:0];
end
if (vfifo_rden_int_2d || hold_release_2d) begin
sf_data_int <= vfifo_data_d;//vfifo_data[31:0];
end else begin
sf_data_int <= {afifo_data[7:0], afifo_data[15:8], afifo_data[23:16], afifo_data[31:24]};
end
end
end
always @ (posedge clk_100m or negedge rst_n)
begin
if (~rst_n) begin
vfifo_rden_int_d <= 1'b0;
vfifo_rden_int_2d <= 1'b0;
afifo_rden_int_d <= 1'b0;
vdata_hold <= 1'b0;
error_d <= 1'b0;
end else begin
vfifo_rden_int_d <= vfifo_rden_int;
vfifo_rden_int_2d <= vfifo_rden_int_d;
afifo_rden_int_d <= afifo_rden_int;
if ((vfifo_rden_int_d) && (pktend_int || pktend_short_int)) begin
//vdata_hold <= 1'b1;
vdata_hold <= vfifo_rden_int;
end
if (hold_release_2d || sf_wr_stat == STATE_ERROR) begin
vdata_hold <= 1'b0;
end
if (sf_wr_stat == STATE_ERROR ) begin
error_d <= 1'b1;
end else begin
error_d <= 1'b0;
end
end
end
always @ (posedge clk_100m or negedge rst_n)
begin
if (~rst_n) begin
end_transfer <= 1'b0;
end else if (srst) begin
end_transfer <= 1'b0;
end else begin
if (sf_wr_stat == STATE_TURN) begin
if (pktend_short_int_d || pktend_int_d) begin
end_transfer <= 1'b1;
end else begin
end_transfer <= 1'b0;
end
end
if (sf_wr_stat == STATE_VFLAGCHK) begin
end_transfer <= 1'b0;
end
end
end
always @ (posedge clk_100m or negedge rst_n)
begin
if (~rst_n) begin
audio_start <= 1'b0;
end else if (srst) begin
audio_start <= 1'b0;
end else begin
if (afifo_status > 400 && audio_start == 1'b0) begin
audio_start <= 1'b1;
end
end
end
assign pktend_int = vfifo_data[33];
assign pktend_short_int = vfifo_data[32];
always @ (posedge clk_100m or negedge rst_n)
begin
if (~rst_n) begin
video_addr <= 1'b0;
pktend_int_d <= 1'b0;
apktend_int_d <= 1'b0;
apktend_int_2d <= 1'b0;
apktend_int_3d <= 1'b0;
pktend_int_2d <= 1'b0;
pktend_int_3d <= 1'b0;
pktend_short_int_d <= 1'b0;
pktend_short_int_2d <= 1'b0;
overflow_err_d <= 1'b0;
audio_cnt_d <= 1'b0;
overflow_req_d <= 1'b0;
overflow_req_2d <= 1'b0;
overflow_done_i <= 1'b0;
end else if (srst) begin
video_addr <= 1'b0;
pktend_int_d <= 1'b0;
apktend_int_d <= 1'b0;
apktend_int_2d <= 1'b0;
apktend_int_3d <= 1'b0;
pktend_int_2d <= 1'b0;
pktend_int_3d <= 1'b0;
pktend_short_int_d <= 1'b0;
pktend_short_int_2d <= 1'b0;
overflow_err_d <= 1'b0;
audio_cnt_d <= 1'b0;
overflow_req_d <= 1'b0;
overflow_req_2d <= 1'b0;
overflow_done_i <= 1'b0;
end else begin
audio_cnt_d <= audio_cnt[6];
pktend_int_2d <= pktend_int_d;
pktend_int_3d <= pktend_int_2d;
pktend_short_int_d <= pktend_short_int;
pktend_short_int_2d <= pktend_short_int_d;
overflow_req_d <= overflow_req;
overflow_req_2d <= overflow_req_d;
if (sf_wr_stat == STATE_ERROR) begin
overflow_done_i <= 1'b1;
end else begin
overflow_done_i <= 1'b0;
end
if ((sf_wr_stat == STATE_IDLE) && overflow_req == 1'b1) begin
overflow_req_d <= 1'b0;
overflow_req_2d <= 1'b0;
end
overflow_err_d <= overflow_err_int;
//when we need to assert pktend for audio
if ( ((audio_cnt_d==1'b0) && (audio_cnt[6] == 1'b1)) || ((sf_wr_stat == STATE_ATX) && ((audio_cnt[6] == 1'b1) || ((afifo_rden_int_d) && (afifo_aempty))))) begin
apktend_int_d <= 1'b1;
end else begin
apktend_int_d <= 1'b0;
end
pktend_int_d <= pktend_int;
apktend_int_2d <= apktend_int_d;
apktend_int_3d <= apktend_int_2d;
end
end
assign overflow_done = overflow_done_i;
endmodule
没有回复内容