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

📄 tx_client_fifo.v

📁 本系统由服务器软件控制平台和fpga硬件处理系统组成
💻 V
📖 第 1 页 / 共 4 页
字号:
      tx_start_addr_gray[9]  <= tx_start_addr[10] ^ tx_start_addr[9];
      tx_start_addr_gray[8]  <= tx_start_addr[9]  ^ tx_start_addr[8];
      tx_start_addr_gray[7]  <= tx_start_addr[8]  ^ tx_start_addr[7];
      tx_start_addr_gray[6]  <= tx_start_addr[7]  ^ tx_start_addr[6];
      tx_start_addr_gray[5]  <= tx_start_addr[6]  ^ tx_start_addr[5];
      tx_start_addr_gray[4]  <= tx_start_addr[5]  ^ tx_start_addr[4];
      tx_start_addr_gray[3]  <= tx_start_addr[4]  ^ tx_start_addr[3];
      tx_start_addr_gray[2]  <= tx_start_addr[3]  ^ tx_start_addr[2];
      tx_start_addr_gray[1]  <= tx_start_addr[2]  ^ tx_start_addr[1];
      tx_start_addr_gray[0]  <= tx_start_addr[1]  ^ tx_start_addr[0];
      end
  end

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

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

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

  assign memory_full_pulse = ((ll_start_add_sub < 12'd16) && 
                                     (ll_start_add_sub > 12'd1)) ? 1'b1 : 1'b0;

  always @(posedge write_clock_in)
  begin
    if (ll_reset == 1'b1)
      memory_full <= 1'b0;
    else 
      memory_full <= memory_full_pulse;
  end
  
  //---------------------------------------------------------------------------
  // Register the write and tx addresses on their respective clocks.
  // **If the FIFO is expanded to use more BRAM, increase write_addr_reg and
  // tx_addr_reg size as required ** 
  //---------------------------------------------------------------------------  
  always @(posedge write_clock_in)
  begin
    if (ll_reset == 1'b1)
      write_addr_reg <= 12'h000;
    else
      write_addr_reg <= write_addr;
  end

  always @(posedge tx_clk)
  begin
    if (tx_reset == 1'b1)
      tx_addr_reg <= 12'h001;
    else if (tx_enable == 1'b1)
      tx_addr_reg <= tx_addr;
  end


  //---------------------------------------------------------------------------
  // Half Duplex Operation
  //---------------------------------------------------------------------------
  
  //---------------------------------------------------------------------------
  // If the FIFO is to be used only in Full duplex operation, the current frame
  // will never need to be retransmitted.  This allows data to be written over
  // any data that has been transmitted.  This allows memory space to be freed
  // up as quickly as possible.
  //---------------------------------------------------------------------------
`ifdef FULL_DUPLEX_ONLY

     // Start address is used to generate memory full signal.  As frame can
     // never be retransmitted, do not need to protect transmitted data.
     // **If the FIFO is expanded to use more BRAM, increase tx_start_addr size as
     // required ** 
     always @(posedge tx_clk)
     begin
       if (tx_reset == 1'b1)
         tx_start_addr        <= 12'h001;
       else if (tx_enable == 1'b1)
         tx_start_addr        <= tx_addr - 3;
     end

     // Tie collision signals to ground
     assign tx_idle_count             = 10'b0000000000;
     assign tx_length_count           = 10'b0000000000;
     assign col_no_retransmit         = 1'b0;
     assign tx_retransmit_reg         = 1'b0;
     assign tx_retransmit_reg_reg     = 1'b0;
     assign tx_retransmit_reg_reg_reg = 1'b0;
     assign retransmit_fip            = 1'b0;
     assign tx_collision_reg          = 1'b0;
     assign queue_for_retransmit      = 1'b0;
     assign queue_for_retransmit_held = 1'b0;
  
`else

  //---------------------------------------------------------------------------
  // If the FIFO is to be used in half duplex operation then the current frame
  // must be stored until it can no longer be retransmitted.
  //---------------------------------------------------------------------------

     //------------------------------------------------------------------------
     // Store the tx_address at the start of a frame transmission or when the
     // window for possible retransmission has expired.
     // The window for retransmission expires when the frame has completely
     // been transmitted by the MAC onto the network or the next frame is
     // accepted by the MAC.
     // The window for retranmission is calculated to expire after sufficient
     // delay from the end of the frame being written from the FIFO has ensured
     // that the frame will have been completely transmitted by the MAC.
     // If a minimum length frame is passed to the MAC, then it will be padded
     // in the MAC so the delay time is extended for a short frame to allow
     // for any padding of the frame.
     // **If the FIFO is expanded to use more BRAM, increase tx_start_addr size as
     // required ** 
     //------------------------------------------------------------------------
     always @(posedge tx_clk)
     begin
       if (tx_reset == 1'b1)
         tx_start_addr        <= 12'h001;
       else if (tx_enable == 1'b1)
         begin
         if (tx_ack == 1'b1)
           tx_start_addr        <= tx_addr - 3;
         else if ((tx_idle_count > 10'd20) && (tx_length_count_plus_tx_idle_count > 10'd528))
           tx_start_addr        <= tx_addr - 3;
         end
     end

     // An adder to count tx_length_count plus tx_idle_count
     always @(posedge tx_clk)
     begin
       if (tx_reset == 1'b1)
         tx_length_count_plus_tx_idle_count <= 11'd0;
       else if (tx_enable == 1'b1)
         tx_length_count_plus_tx_idle_count <= tx_length_count + tx_idle_count;
     end

     // A counter that records the length of the last frame sent, upto a length
     // of 528 decimal.  This is the minimum length frame allowed at 1Gig Half
     // Duplex of 512 plus 8 bytes of preamble added by the MAC and a small margin
     always @(posedge tx_clk)
     begin
       if (tx_reset == 1'b1)
         tx_length_count <= 10'd0;
       else if (tx_enable == 1'b1)
         begin
         if (tx_ack == 1'b1)
           tx_length_count <= 10'd0;
         else if (frame_in_progress == 1'b1 && (tx_length_count < 10'd528))
           tx_length_count <= tx_length_count + 1;
         end
     end

     // A counter that records the no of clock cycles from the last byte of the
     // last frame sent upto a value of 528 decimal.
     always @(posedge tx_clk)
     begin
       if (tx_reset == 1'b1)
         tx_idle_count <= 10'd0;
       else if (tx_enable == 1'b1)
         begin
         if (tx_ack == 1'b1)
           tx_idle_count <= 10'd0;
         else if (frame_in_progress == 1'b0 && (tx_idle_count < 10'd528))
	   tx_idle_count <= tx_idle_count + 1;
         end
     end
  
     //---------------------------------------------------------------------------
     // TX Half Duplex Collision handling circuit. On retransmit the circuit 
     // should go back to the start of the current frame and count up the 
     // frame counter. If a collision signal is seen without a retransmit 
     // then the circuit should drop the current frame.
     //---------------------------------------------------------------------------
     // If the collision is asserted without retransmit then we kill the rest
     // of the frame
     always @(posedge tx_clk)
     begin
       if (tx_reset == 1'b1)
         col_no_retransmit <= 1'b0;
       else if (tx_enable == 1'b1)
         begin
         if (tx_collision_reg == 1'b1 && tx_retransmit_reg == 1'b0 && 
                        frame_in_progress == 1'b1 && tx_data_valid_pipe == 1'b1)
           col_no_retransmit <= 1'b1;
         else if (tx_data_valid_pipe == 1'b0 || frame_in_fifo_held == 1'b0)
           col_no_retransmit <= 1'b0;
         end
     end

     // If a retransmit comes in we have to queue up the data for retransmission.
     // The queue for retransmit signal is asserted for one clock cycle after
     // receiving tx_retransmit, to load data into the data pipe.  The signal is
     // held for two clock cycles if the fifo is not currently transmitting a frame
     // or if the data pipe is empty.
     always @(posedge tx_clk)
     begin
       if (tx_reset == 1'b1)
         queue_for_retransmit   <= 1'b0;
       else if (tx_enable == 1'b1)
         begin
         if (tx_retransmit_reg_reg == 1'b1)
           queue_for_retransmit <= 1'b1;
         else if (tx_retransmit_reg_reg_reg == 1'b1 && 
                   ((frame_in_progress == 1'b0 && retransmit_fip == 1'b0) || tx_data_valid_pipe == 1'b0))
           queue_for_retransmit <= 1'b1;
         else
           queue_for_retransmit <= 1'b0;
         end
     end

     // queue_for_retransmit_held is used to turn off the signal queue from
     // assersion of queue_for_retransmit until next tx_ack is recieved.
     // It is also used to force the tx_mem_enable signal high until the 
     // frame is requeued
     always @(posedge tx_clk)
     begin
       if (tx_reset == 1'b1)
         queue_for_retransmit_held <= 1'b0;
       else if (tx_enable == 1'b1)
         begin
         if (queue_for_retransmit == 1'b1)
           queue_for_retransmit_held <= 1'b1;
         else if (tx_ack == 1'b1)
           queue_for_retransmit_held <= 1'b0;
         end
     end

     always @(posedge tx_clk)
     begin
       if (tx_reset == 1'b1)
         retransmit_fip <= 1'b0;
       else if (tx_enable == 1'b1)
         retransmit_fip <= frame_in_progress;
     end

     //---------------------------------------------------------------------------
     // Generate the tx_retransmit_reg signal that is used to count back to 
     // the start of the frame.
     //---------------------------------------------------------------------------
     always @(posedge tx_clk)
     begin
       if (tx_reset == 1'b1)
	 begin
         tx_retransmit_reg         <= 1'b0;
         tx_retransmit_reg_reg     <= 1'b0;
         tx_retransmit_reg_reg_reg <= 1'b0;
	 end
       else if (tx_enable == 1'b1)
	 begin	       
         tx_retransmit_reg         <= tx_retransmit;
         tx_retransmit_reg_reg     <= tx_retransmit_reg;
         tx_retransmit_reg_reg_reg <= tx_retransmit_reg_reg;
         end
     end

     always @(posedge tx_clk)
     begin
       if (tx_reset == 1'b1)
         tx_collision_reg <= 1'b0;
       else if (tx_enable == 1'b1)
         tx_collision_reg <= tx_collision;
     end
  
`endif

`ifdef FULL_DUPLEX_ONLY
`undef FULL_DUPLEX_ONLY
`endif

endmodule

⌨️ 快捷键说明

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