LATTICE FPGA USB3.0 UVC方案verilog源代码音频卡顿问题求助-Lattice-莱迪斯社区-FPGA CPLD-ChipDebug

LATTICE FPGA USB3.0 UVC方案verilog源代码音频卡顿问题求助

我们用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
请登录后发表评论

    没有回复内容