⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tx_client_fifo.v

📁 本系统由服务器软件控制平台和fpga硬件处理系统组成
💻 V
📖 第 1 页 / 共 4 页
字号:
      begin
      ll_frame_transmitted_toggle    <= 3'b000;
      ll_frame_transmitted           <= 1'b0;
      end 
    else
      begin
      ll_frame_transmitted_toggle[0] <= frame_transmitted_toggle;
      ll_frame_transmitted_toggle[1] <= ll_frame_transmitted_toggle[0];
      ll_frame_transmitted_toggle[2] <= ll_frame_transmitted_toggle[1];
      ll_frame_transmitted           <= ll_frame_transmitted_toggle[2] ^ ll_frame_transmitted_toggle[1];
      end
  end

  // Repeat for frame_retransmit pulse
  always @(posedge write_clock_in)
  begin
    if (ll_reset == 1'b1)
      begin
      ll_frame_retransmit_toggle     <= 3'b000;
      ll_frame_retransmit            <= 1'b0;
      end
    else
      begin
      ll_frame_retransmit_toggle[0]  <= frame_retransmit_toggle;
      ll_frame_retransmit_toggle[1]  <= ll_frame_retransmit_toggle[0]; 
      ll_frame_retransmit_toggle[2]  <= ll_frame_retransmit_toggle[1];
      ll_frame_retransmit            <= ll_frame_retransmit_toggle[2] ^ ll_frame_retransmit_toggle[1];
      end
  end
     
  // Generate frame count on write clock
  // **If the FIFO is expanded to use more BRAM, ensure frame count signals are
  // wide enough to count the maximum number of frames that can be stored in FIFO**
  always @(posedge write_clock_in)
  begin
    if (ll_reset == 1'b1)
      ll_frame_count <= 9'd0;
    else
      begin 
      if (ll_frame_transmitted == 1'b1 && frame_received == 1'b0)
        ll_frame_count <= ll_frame_count - 1;
      else if ((ll_frame_transmitted == 1'b0 && frame_received == 1'b1 && ll_frame_retransmit == 1'b0) ||
                                                     (ll_frame_retransmit == 1'b1 && frame_received == 1'b0))
        ll_frame_count <= ll_frame_count + 1;
      else if (ll_frame_retransmit == 1'b1 && frame_received == 1'b1)
        ll_frame_count <= ll_frame_count + 2;
      end
  end

  //---------------------------------------------------------------------------
  // As the frame_count information will be used by the transmitter logic, we
  // need to convert the frame count( signal back to the transmit clock domain.
  // This is done using gray code.
  //---------------------------------------------------------------------------
  // Convert the ll_frame_count signal to gray code
  always @(posedge write_clock_in)
  begin
    if (ll_reset == 1'b1)
      ll_frame_count_gray <= 9'd0;  
    else
      begin
      ll_frame_count_gray[8] <= ll_frame_count[8]; 
      ll_frame_count_gray[7] <= ll_frame_count[8] ^ ll_frame_count[7];
      ll_frame_count_gray[6] <= ll_frame_count[7] ^ ll_frame_count[6];
      ll_frame_count_gray[5] <= ll_frame_count[6] ^ ll_frame_count[5];
      ll_frame_count_gray[4] <= ll_frame_count[5] ^ ll_frame_count[4];
      ll_frame_count_gray[3] <= ll_frame_count[4] ^ ll_frame_count[3];
      ll_frame_count_gray[2] <= ll_frame_count[3] ^ ll_frame_count[2];
      ll_frame_count_gray[1] <= ll_frame_count[2] ^ ll_frame_count[1];
      ll_frame_count_gray[0] <= ll_frame_count[1] ^ ll_frame_count[0];
      end
  end

  // Clock this onto the tx_clk.
  always @(posedge tx_clk)
  begin
    if (tx_reset == 1'b1)
      frame_count_gray <= 9'd0;
    else if (tx_enable == 1'b1)
      frame_count_gray <= ll_frame_count_gray;
  end

  // Convert this back to binary.
  always @(posedge tx_clk)
  begin
    if (tx_reset == 1'b1)
      frame_count <= 9'd0;
    else if (tx_enable == 1'b1)
      begin
      frame_count[8] <=  frame_count_gray[8]; 
      frame_count[7] <=  frame_count_gray[8] ^ frame_count_gray[7];
      frame_count[6] <=  frame_count_gray[8] ^ frame_count_gray[7]
                       ^ frame_count_gray[6];
      frame_count[5] <=  frame_count_gray[8] ^ frame_count_gray[7]
                       ^ frame_count_gray[6] ^ frame_count_gray[5];
      frame_count[4] <=  frame_count_gray[8] ^ frame_count_gray[7]
                       ^ frame_count_gray[6] ^ frame_count_gray[5]
                       ^ frame_count_gray[4];
      frame_count[3] <=  frame_count_gray[8] ^ frame_count_gray[7]
                       ^ frame_count_gray[6] ^ frame_count_gray[5]
                       ^ frame_count_gray[4] ^ frame_count_gray[3];
      frame_count[2] <=  frame_count_gray[8] ^ frame_count_gray[7]
                       ^ frame_count_gray[6] ^ frame_count_gray[5]
                       ^ frame_count_gray[4] ^ frame_count_gray[3]
                       ^ frame_count_gray[2];
      frame_count[1] <=  frame_count_gray[8] ^ frame_count_gray[7]
                       ^ frame_count_gray[6] ^ frame_count_gray[5] 
                       ^ frame_count_gray[4] ^ frame_count_gray[3]
                       ^ frame_count_gray[2] ^ frame_count_gray[1];       
      frame_count[0] <=  frame_count_gray[8] ^ frame_count_gray[7]
                       ^ frame_count_gray[6] ^ frame_count_gray[5]
                       ^ frame_count_gray[4] ^ frame_count_gray[3]
                       ^ frame_count_gray[2] ^ frame_count_gray[1]
                       ^ frame_count_gray[0];
      end
  end

  // Indicator signal for one or more frames in the fifo
  assign frame_in_fifo = (frame_count == 9'd0) ? 1'b0 : 1'b1;		

  //--------------------------------------------------------------------
  // We want to count up through the frame data after we have received  
  // an ack back from the MAC. When data_valid goes low then we stop.
  // If frame_in_fifo_held is low then the signal is de-asserted to 
  // prevent an underrun.
  //--------------------------------------------------------------------
  always @(posedge tx_clk)
  begin
    if (tx_reset == 1'b1)
      frame_in_progress <= 1'b0;
    else if (tx_enable == 1'b1)
      begin  
      if (tx_data_valid_pipe == 1'b0 || frame_in_fifo_held == 1'b0)
        frame_in_progress <= 1'b0;
      else if (tx_ack == 1'b1)
        frame_in_progress <= 1'b1;
      end
  end
     
  assign not_frame_in_progress = !(frame_in_progress);
 
  //---------------------------------------------------------------------------
  // Hold the frame_in_fifo signal until the frame has been completely 
  // transmitted. This will be used to gate the data_valid output.
  //---------------------------------------------------------------------------
  always @(posedge tx_clk)
  begin
    if (tx_reset == 1'b1)
      frame_in_fifo_held <= 1'b0;
    else if (tx_enable == 1'b1)
      begin
      if ((frame_in_progress == 1'b1 && tx_data_valid_pipe == 1'b0) || frame_in_fifo == 1'b1)
        frame_in_fifo_held <= frame_in_fifo;
      end
  end

  //--------------------------------------------------------------------
  // At the start of each frame we need to clock the first byte of  
  // data from the memory as we have to change this as soon as ack is 
  // received. 
  //--------------------------------------------------------------------
  always @(posedge tx_clk)
  begin
    if (tx_reset == 1'b1)
      queue <= 1'b0;
    else if (tx_enable == 1'b1)
      queue <= (frame_in_fifo & !(frame_in_fifo_held) & !(queue_for_retransmit_held));
  end

  //--------------------------------------------------------------------
  // We have to calculate the occupancy of the fifo as we need to drop  
  // frames when it is about to overflow. This will be calculated on  
  // the write clock and so we need to get the tx_addr into the write clock  
  // domain. To do this we first convert the tx_addr to gray codes as 
  // this helps to counter problems with the 2 addresses being on 
  // different clock domains. This gray code representation of the  
  // tx_addr is then clocked onto the write clock and converted back to 
  // binary.  The binary version can then be compared to to the 
  // write_addr on the write clock.
  // **If the FIFO is expanded to use more BRAM, increase tx_addr_gray,
  // ll_tx_addr_gray and ll_tx_addr_bin size as required ** 
  //--------------------------------------------------------------------
  // Convert tx address to gray codes.
  always @(posedge tx_clk)
  begin
    if (tx_reset == 1'b1)
      tx_addr_gray <= 12'h001;  
    else if (tx_enable == 1'b1)
      begin     
      tx_addr_gray[11] <= tx_addr_reg[11] ;
      tx_addr_gray[10] <= tx_addr_reg[11] ^ tx_addr_reg[10];
      tx_addr_gray[9]  <= tx_addr_reg[10] ^ tx_addr_reg[9];
      tx_addr_gray[8]  <= tx_addr_reg[9]  ^ tx_addr_reg[8];
      tx_addr_gray[7]  <= tx_addr_reg[8]  ^ tx_addr_reg[7];
      tx_addr_gray[6]  <= tx_addr_reg[7]  ^ tx_addr_reg[6];
      tx_addr_gray[5]  <= tx_addr_reg[6]  ^ tx_addr_reg[5];
      tx_addr_gray[4]  <= tx_addr_reg[5]  ^ tx_addr_reg[4];
      tx_addr_gray[3]  <= tx_addr_reg[4]  ^ tx_addr_reg[3];
      tx_addr_gray[2]  <= tx_addr_reg[3]  ^ tx_addr_reg[2];
      tx_addr_gray[1]  <= tx_addr_reg[2]  ^ tx_addr_reg[1];
      tx_addr_gray[0]  <= tx_addr_reg[1]  ^ tx_addr_reg[0];
      end
  end

  // Clock this onto the write clock.
  always @(posedge write_clock_in)
  begin
    if (ll_reset == 1'b1)
      ll_tx_addr_gray <= 12'h001;
    else
      ll_tx_addr_gray <= tx_addr_gray;
  end

  // Convert this back to binary.
  always @(posedge write_clock_in)
  begin
    if (ll_reset == 1'b1)
      ll_tx_addr_bin <= 12'h001;
    else
      begin
      ll_tx_addr_bin[11] <=  ll_tx_addr_gray[11];
      ll_tx_addr_bin[10] <=  ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10];
      ll_tx_addr_bin[9]  <=  ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
                           ^ ll_tx_addr_gray[9];
      ll_tx_addr_bin[8]  <=  ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
                           ^ ll_tx_addr_gray[9]  ^ ll_tx_addr_gray[8];
      ll_tx_addr_bin[7]  <=  ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
                           ^ ll_tx_addr_gray[9]  ^ ll_tx_addr_gray[8]
                           ^ ll_tx_addr_gray[7];
      ll_tx_addr_bin[6]  <=  ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
                           ^ ll_tx_addr_gray[9]  ^ ll_tx_addr_gray[8]
                           ^ ll_tx_addr_gray[7]  ^ ll_tx_addr_gray[6];
      ll_tx_addr_bin[5]  <=  ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
                           ^ ll_tx_addr_gray[9]  ^ ll_tx_addr_gray[8]
                           ^ ll_tx_addr_gray[7]  ^ ll_tx_addr_gray[6]
                           ^ ll_tx_addr_gray[5];
      ll_tx_addr_bin[4]  <=  ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
                           ^ ll_tx_addr_gray[9]  ^ ll_tx_addr_gray[8]
                           ^ ll_tx_addr_gray[7]  ^ ll_tx_addr_gray[6]
                           ^ ll_tx_addr_gray[5]  ^ ll_tx_addr_gray[4];       
      ll_tx_addr_bin[3]  <=  ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
                           ^ ll_tx_addr_gray[9]  ^ ll_tx_addr_gray[8]
                           ^ ll_tx_addr_gray[7]  ^ ll_tx_addr_gray[6]
                           ^ ll_tx_addr_gray[5]  ^ ll_tx_addr_gray[4]
                           ^ ll_tx_addr_gray[3];
      ll_tx_addr_bin[2]  <=  ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
                           ^ ll_tx_addr_gray[9]  ^ ll_tx_addr_gray[8]
                           ^ ll_tx_addr_gray[7]  ^ ll_tx_addr_gray[6]
                           ^ ll_tx_addr_gray[5]  ^ ll_tx_addr_gray[4]
                           ^ ll_tx_addr_gray[3]  ^ ll_tx_addr_gray[2];
     ll_tx_addr_bin[1]  <=   ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
                           ^ ll_tx_addr_gray[9]  ^ ll_tx_addr_gray[8]
                           ^ ll_tx_addr_gray[7]  ^ ll_tx_addr_gray[6]
                           ^ ll_tx_addr_gray[5]  ^ ll_tx_addr_gray[4]
                           ^ ll_tx_addr_gray[3]  ^ ll_tx_addr_gray[2]
                           ^ ll_tx_addr_gray[1];
     ll_tx_addr_bin[0]  <=   ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
                           ^ ll_tx_addr_gray[9]  ^ ll_tx_addr_gray[8]
                           ^ ll_tx_addr_gray[7]  ^ ll_tx_addr_gray[6]
                           ^ ll_tx_addr_gray[5]  ^ ll_tx_addr_gray[4]
                           ^ ll_tx_addr_gray[3]  ^ ll_tx_addr_gray[2]  
                           ^ ll_tx_addr_gray[1]  ^ ll_tx_addr_gray[0];
     end
  end

  // Subtract the tx address from the write address
  always @(posedge write_clock_in)
  begin
    if (ll_reset == 1'b1)
      ll_add_sub <= 12'h001;
    else
      ll_add_sub <= ll_tx_addr_bin - write_addr_reg;
  end

  // Set the full flag to go up when the rx address is 16 bytes 
  // away from the tx address.
  assign full_pulse = ((ll_add_sub  < 12'd22) 
                            && (ll_add_sub > 12'd1)) ? 1'b1 : 1'b0;

  // Calculate the fifo status from the difference in addresses
  assign fifo_status_full = write_addr_reg - ll_tx_addr_bin + 1;

  // Truncate to give the 4 bit output signal
  assign fifo_status_out = fifo_status_full[11:8];

  //---------------------------------------------------------------------------
  // Set overflow to 1 when the full pulse goes high and there are no frames
  // in fifo to be transmitted.  For this to happen an oversize frame must have
  // been written into the fifo.
  //---------------------------------------------------------------------------
  always @(posedge write_clock_in)
  begin
    if (ll_reset == 1'b1)
      overflow_int <= 1'b0;
    else if (frame_in_fifo_held == 1'b0)
      overflow_int <= full_pulse;
  end

  ////-------------------------------------------------------------------------
  // Hold this signal until the eof signals the 
  // end of the overflow frame has arrived.
  //---------------------------------------------------------------------------
  always @(posedge write_clock_in)
  begin
    if (ll_reset == 1'b1)
      overflow_int_held <= 1'b0;
    else if (overflow_int == 1'b1)
      overflow_int_held <= 1'b1;
    else if (overflow_eof_in_n_reg_reg == 1'b0 && overflow_eof_in_n_reg_reg_reg == 1'b1)
      overflow_int_held <= 1'b0;
  end

  // Assign overflow output indicator to signal that current frame is being dropped
  assign overflow = overflow_int_held;  

  //---------------------------------------------------------------------------
  // Set the memory full pulse to go high when the write address is 16 bytes
  // away from the tx start address.  This protects a frame from being overwritten
  // until there is no possibility of a further request for retransmission.
  // Convert tx_start_address onto local link clock via gray code
  // **If the FIFO is expanded to use more BRAM, increase tx_start_addr_gray
  // ll_tx_start_addr_gray and ll_tx_start_addr size as required ** 
  //---------------------------------------------------------------------------
  // Convert tx address to gray codes.
  always @(posedge tx_clk)
  begin
    if (tx_reset == 1'b1)
      tx_start_addr_gray <= 12'h001;  
    else if (tx_enable == 1'b1)
      begin
      tx_start_addr_gray[11] <= tx_start_addr[11];
      tx_start_addr_gray[10] <= tx_start_addr[11] ^ tx_start_addr[10];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -