打印
[FPGA]

cypress 68013 数据传输错误

[复制链接]
615|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kangqiao004|  楼主 | 2020-7-20 17:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 kangqiao004 于 2020-7-20 17:42 编辑

68013  在传输过程中偶尔会出现不确定bit位数据错误,出错几率比较大,10次会有3/4次出错。
例如:发送1b1a787878780078, FPGA的ila抓到1b1a587978780078

如下代码,fpga_gclk来自68013的IFCLK。代码中 if(i==3) begin红色高亮的地方,如果i=1,就不会出错。
如果i=3,就会大概率出错。   i=1 改到i=3,仅仅是为了连续从68013多读取两个16bit数据。

这份代码是参考开发板改的。
还请大神帮忙分析!或者有遇到过类似问题的赐教,感谢!!


//////////////////////////////////////////////////////////////////////////////////
// Module Name:    usb_test
// Description: If the FIFO of EP2 is not empty and
//              the EP6 is not full, Read the 16bit data from EP2 FIFO
//              and send to EP6 FIFO.  
//////////////////////////////////////////////////////////////////////////////////
module usb_test(
  input                                     fpga_gclk,        // FPGA Clock Input 48Mhz
  input                                     reset_n,          // FPGA Reset input
  output reg         [1:0]             usb_fifoaddr,     // CY68013 FIFO Address
(*mark_debug = "true"*)  output reg                             usb_slcs,         // CY68013 Chipset select
(*mark_debug = "true"*)  output reg                             usb_sloe,         // CY68013 Data output enable
(*mark_debug = "true"*) output reg                              usb_slrd,         // CY68013 READ indication
(*mark_debug = "true"*)  output reg                             usb_slwr,         // CY68013 Write indication
(*mark_debug = "true"*)  output wire                        usb_pktend,       // package end         
  inout                   [15:0]             usb_fd,           // CY68013 Data
(*mark_debug = "true"*)  input                                       usb_flaga,        // CY68013 EP2 FIFO empty indication; 1:not empty; 0: empty
(*mark_debug = "true"*)  input                                       usb_flagb,        // CY68013 EP4 FIFO empty indication; 1:not empty; 0: empty
  input                                       usb_flagc,        // CY68013 EP6 FIFO full indication; 1:not full; 0: full

(*mark_debug = "true"*)          output reg        [63:0]             user_data,
(*mark_debug = "true"*)          output reg              user_data_valid,
        input                                     data_to_usb_valid,// INA226 read done
        input                   [15:0]             data_to_usb,      // INA226 data
        input                   pkt_end_flag      // pkt_end_flag
    );


reg               bus_busy;        //usb busy                          
reg               rd_ep2_req;      //read EP2 request
reg               wr_ep6_req;      //write EP6 request                     
reg               usb_fd_en;       //usb data bus  direction control

(*mark_debug = "true"*)  reg [4:0]         usb_state;       //usb FSM state
(*mark_debug = "true"*)  reg [4:0]         i;

wire [15:0]       fifo_dout;       //fifo data out
wire              full;            //fifo full
wire              empty;           //fifo empty
reg [63:0]        fifo_din;        //fifo data in
(*mark_debug = "true"*)wire [15:0]       i_usb_fd;        
(*mark_debug = "true"*)wire [15:0]       o_usb_fd;
wire [12:0]       rd_data_count;   //fifo rd_data_count
wire [63:0]       data2fifo2;      //data to fifo, buffer for data2fifo1
reg               fifo_wr_en;      //fifo write enable


//*** modified by KQ ************************
reg               k_data_to_usb_valid;
reg               k_data_to_usb_valid_r;
reg               k_usb_pktend;
wire              usb_pktend_r;

//**************wire for audio***************
wire   [63:0]         data2fifo1;
wire            o_ak_bick;
wire            transmit_stop;
wire            wr_fifo_en;
//*****************************************

parameter IDLE         = 5'd0;
parameter EP2_RD_CMD   = 5'd1;
parameter EP2_RD_DATA  = 5'd2;
parameter EP2_RD_OVER  = 5'd3;
parameter EP6_WR_CMD   = 5'd4;
parameter EP6_WR_OVER  = 5'd5;     


assign usb_pktend_r    =  k_usb_pktend ;
assign usb_pktend      = usb_pktend_r;      
assign data2fifo2      = {data2fifo1[47:40],data2fifo1[39:32],data2fifo1[63:56],data2fifo1[55:48],data2fifo1[15:8],data2fifo1[7:0],data2fifo1[31:24],data2fifo1[23:16]};
/* Generate USB read/write access request*/

//*** modified by KQ ************************
// use k_data_to_usb_valid posedge to generate wr_ep6_req ,for triggering usb writing state
always @(posedge fpga_gclk)
begin
    if(~reset_n)
     k_data_to_usb_valid <= 1'b0;
    else
         k_data_to_usb_valid <= data_to_usb_valid;
end

always @(posedge fpga_gclk)
begin
    if(~reset_n)
      k_data_to_usb_valid_r <= 1'b0;
    else
          k_data_to_usb_valid_r <= k_data_to_usb_valid;
end

//*****************************************

//***sync ak5397(ADC) data and fifo_wr_en to o_ak_bick*********
always @(posedge o_ak_bick or negedge reset_n)
begin
    if(~reset_n)
          begin
        fifo_din <= 0;
                fifo_wr_en <= 0;
          end
    else
          begin
            fifo_din <= data2fifo2;
                fifo_wr_en <= ((wr_fifo_en)&&(!full));
          end
end

//***collect data from usb_fd for user_data *********
//command from PC
always@(posedge fpga_gclk or negedge reset_n)
begin
        if (~reset_n )
      begin
        user_data <= 64'd0;
      end
        else
      if(usb_slrd==1'b0)
        begin
          user_data <= {user_data[47:0],i_usb_fd};
        end
      else
        begin
          user_data <= user_data;
        end
end

//***generate read EP2 request*******************
always @(negedge fpga_gclk or negedge reset_n)
begin
   if (~reset_n ) begin
      rd_ep2_req <= 1'b0;
   end
   else begin
      if (usb_flaga & (bus_busy==1'b0))     //EP2 is not empty ,and usb state is not busy
          rd_ep2_req <= 1'b1;               //generate read EP2 request
      else
          rd_ep2_req <= 1'b0;
   end
end

//***generate write EP6 request*******************
always @(negedge fpga_gclk or negedge reset_n)
begin
   if (~reset_n ) begin
      wr_ep6_req <= 1'b0;
   end
   else begin
      if (usb_flagb & (!empty) & (bus_busy==1'b0) || (k_data_to_usb_valid && (~k_data_to_usb_valid_r)))     //EP6 is not full,  fifo is not empty and usb state is not busy or other data-to-usb request
          wr_ep6_req <= 1'b1;                             //generate write EP6 request
      else
          wr_ep6_req <= 1'b0;
   end
end


//***usb FSM****************************************
always @(posedge fpga_gclk or negedge reset_n)
  begin
   if (~reset_n)
     begin
       usb_fifoaddr <= 2'b00;
       usb_slcs <= 1'b0;               
       usb_sloe <= 1'b1;               
       usb_slrd <= 1'b1;        
       usb_slwr <= 1'b1;
       usb_fd_en <= 1'b0;        
       usb_state <= IDLE;
       k_usb_pktend <= 1;
     end               
   else begin
           case(usb_state)
        IDLE:
                  begin      //Idle
            k_usb_pktend <= 1;
            i<=0;
            usb_fd_en <= 1'b0;        
            if (rd_ep2_req==1'b1) begin                                   
              usb_state <= EP2_RD_CMD;    //jump to EP2_RD_CMD
              bus_busy <= 1'b1;           //set bus_busy
              usb_fifoaddr <= 2'b00;      //select EP2 address
                          user_data_valid <= 1'b0;
            end        
            else if ((wr_ep6_req==1'b1)) begin                                   
              usb_state <= EP6_WR_CMD;     //jump to EP6_WR_CMD
              bus_busy <= 1'b1;            //set bus_busy
              usb_fifoaddr <= 2'b10;       //select EP6 address                                    
            end                                   
            else begin
              bus_busy <= 1'b0;                  
              usb_state <= IDLE;  
              usb_fifoaddr <= usb_fifoaddr;//select EP2 address
                          user_data_valid <= 1'b0;
            end         
          end
                  
        EP2_RD_CMD:
                begin                 //EP2 FIFO Read Command
          k_usb_pktend <= 1;
          if(i==2) begin
            usb_slrd <= 1'b1;
            usb_sloe <= 1'b0;                 //set sloe to low                                 
            i <= i+1'b1;
          end
          else if(i==8) begin
            usb_slrd <= 1'b0;        //set slrd to low                        
            usb_sloe <= 1'b0;                                                
            i<=0;        
            usb_state <= EP2_RD_DATA;
          end
          else begin
            i <= i+1'b1;
          end
        end        
               
                EP2_RD_DATA:
                begin      //EP2 FIFO Read Data
          k_usb_pktend <= 1;
          if(i==3) begin
            usb_slrd <= 1'b1;   //        
            usb_sloe <= 1'b0;                                                
            i <= 0;        
            usb_state <= EP2_RD_OVER;
          end
          else begin
            usb_slrd <= 1'b0;                                      
            usb_sloe <= 1'b0;                                          
            i <= i + 1'b1;
          end
                end
                 
                 EP2_RD_OVER:
                 begin      //read over
           k_usb_pktend <= 1;
           if(i==4) begin
             usb_slrd <= 1'b1;            
             usb_sloe <= 1'b1;                                                
             i <= 0;        
             usb_fifoaddr <= 2'b00;       //EP6 address
             usb_state <= IDLE;
                         user_data_valid <= 1'b1;
             bus_busy <= 1'b0;
           end
           else begin
             usb_slrd <= 1'b1;                                      
             usb_sloe <= 1'b0;                                          
             i <= i + 1'b1;
           end
                 end
                 
                 EP6_WR_CMD:
                 begin                   //write EP6 FIFO
           k_usb_pktend <= 1;                 
           if(i==1) begin
             usb_slwr <= 1'b1;                     //
             i <= 0;                                                        
             usb_state <= EP6_WR_OVER;
           end
           else begin
             usb_slwr <= 1'b0;                             //slwr = 0 >50ns        
             usb_fd_en <= 1'b1;                     //
             i <= i + 1'b1;
           end
                 end
                 
                 EP6_WR_OVER:
                 begin           //EP6 write over         
           if(i==4)
                     begin
               k_usb_pktend <= 0;
               if(empty|(!usb_flagb))
                             begin
                   usb_fd_en <= 1'b0;
                   bus_busy <= 1'b0;
                   i <= 0;                                                        
                   usb_state <= IDLE;
                 end
               else
                         begin
                   usb_fd_en <= 1'b1;
                   bus_busy <= 1'b1;
                   i <= 0;                                                        
                   usb_state <= EP6_WR_CMD;
                 end
             end
           else
                     begin                  
               i <= i + 1'b1;
             end
                 end
                 
       default:  usb_state <= IDLE;
       endcase
         end
  end  

//assign o_usb_fd = (pkt_end_flag || user_data[63:48] == 16'haaaa) ? data_to_usb : fifo_dout ;    //switch data source
assign o_usb_fd = data_to_usb ;
genvar j;
generate
for(j=0;j<16;j=j+1)
begin :UINT

IOBUF #(
      .DRIVE(12), // Specify the output drive strength
      .IBUF_LOW_PWR("TRUE"),  // Low Power - "TRUE", High Performance = "FALSE"
      .IOSTANDARD("DEFAULT"), // Specify the I/O standard
      .SLEW("SLOW") // Specify the output slew rate
   ) IOBUF_inst (
      .O(i_usb_fd[j]),     // Buffer output
      .IO(usb_fd[j]),   // Buffer inout port (connect directly to top-level port)
      .I(o_usb_fd[j]),     // Buffer input
      .T(~usb_fd_en)      // 3-state enable input, high=input, low=output
   );
end
endgenerate

fifo_generator_0 uut (
  .wr_clk(~o_ak_bick),                // input wire wr_clk
  .rd_clk(fpga_gclk),                // input wire rd_clk
  .din(fifo_din),                      // input wire [31 : 0] din
  .wr_en(fifo_wr_en),                  // input wire wr_en
  .rd_en(~usb_slwr),                  // input wire rd_en
  .dout(fifo_dout),                    // output wire [15 : 0] dout
  .full(full),                    // output wire full
  .empty(empty),                  // output wire empty
  .rd_data_count(rd_data_count)  // output wire [9 : 0] rd_data_count
  //.rst(rst)                      // input wire rst
);

endmodule

使用特权

评论回复

相关帖子

沙发
kangqiao004|  楼主 | 2020-7-21 08:29 | 只看该作者
自己的坑,自己解

工程中用了o_clk98M_clk作为debug的采样时钟。但是没有写约束。加上下面的约束就好了。
set_clock_groups -asynchronous -group fpga_gclk -group o_clk98M_clk_wiz_0

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

61

帖子

3

粉丝