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

📄 tx_client_fifo_8.v

📁 Xilinx Virtex5 SGMII高速串行通信例程。
💻 V
📖 第 1 页 / 共 3 页
字号:
                 rd_nxt_state <= QUEUE2_s;
              end
           QUEUE2_s : begin
                 rd_nxt_state <= QUEUE3_s;
              end
           QUEUE3_s : begin
                 rd_nxt_state <= QUEUE_ACK_s;
              end
           QUEUE_ACK_s : begin
                 rd_nxt_state <= WAIT_ACK_s;
              end
           WAIT_ACK_s : begin
              // the output pipe line is fully loaded, so wait for ack from mac
              // before moving on
              if (tx_ack == 1'b1)
                 rd_nxt_state <= FRAME_s;
              else
                 rd_nxt_state <= WAIT_ACK_s;
              end
           FRAME_s : begin
              // when the end of frame has been reached wait another frame in
              // the fifo
              if (rd_eof == 1'b1)
                 rd_nxt_state <= IDLE_s;
              else
                 rd_nxt_state <= FRAME_s;
              end
           default : begin
                 rd_nxt_state <= IDLE_s;
              end
        endcase
  end
                                // full duplex state machine

end // gen_fd_sm
endgenerate

   
  //---------------------------------------------------------------------------
  // Full and Half Duplex State Machine
generate if (FULL_DUPLEX_ONLY != 1) begin : gen_hd_sm
  // decode the next state
  // should never receive a rd_drop_frame pulse outside of the Frame state
  always @(rd_state or frame_in_fifo or rd_eof_reg or tx_ack or rd_drop_frame or rd_retransmit)
  begin
  case (rd_state)
           IDLE_s : begin
              // if a retransmit request is detected go to retransmit state
              if (rd_retransmit == 1'b1)
                 rd_nxt_state <= RETRANSMIT_s;
              // if there is a frame in the fifo then queue the new frame to
              // the output
              else if (frame_in_fifo == 1'b1)
                 rd_nxt_state <= QUEUE1_s;
              else
                 rd_nxt_state <= IDLE_s;
              end
           QUEUE1_s : begin
              if (rd_retransmit == 1'b1)
                 rd_nxt_state <= RETRANSMIT_s;
              else
                rd_nxt_state <= QUEUE2_s;
              end
           QUEUE2_s : begin
              if (rd_retransmit == 1'b1)
                 rd_nxt_state <= RETRANSMIT_s;
              else
                 rd_nxt_state <= QUEUE3_s;
              end
           QUEUE3_s : begin
              if (rd_retransmit == 1'b1)
                 rd_nxt_state <= RETRANSMIT_s;
              else
                 rd_nxt_state <= QUEUE_ACK_s;
              end
           QUEUE_ACK_s : begin
              if (rd_retransmit == 1'b1)
                 rd_nxt_state <= RETRANSMIT_s;
              else
                 rd_nxt_state <= WAIT_ACK_s;
              end
           WAIT_ACK_s : begin
              // the output pipeline is now fully loaded so wait for ack from
              // mac before moving on.
              if (rd_retransmit == 1'b1)
                 rd_nxt_state <= RETRANSMIT_s;
              else if (tx_ack == 1'b1)
                 rd_nxt_state <= FRAME_s;
              else
                 rd_nxt_state <= WAIT_ACK_s;
              end
           FRAME_s : begin
              // if a collision only request, then must drop the rest of the
              // current frame, move to drop state
              if (rd_drop_frame == 1'b1)
                 rd_nxt_state <= DROP_s;
              else if (rd_retransmit == 1'b1)
                 rd_nxt_state <= RETRANSMIT_s;
              // continue transmitting frame until the end of the frame is
              // detected, then wait for a new frame to be sent.
              else if (rd_eof_reg == 1'b1)
                 rd_nxt_state <= IDLE_s;
              else
                 rd_nxt_state <= FRAME_s;
              end
           DROP_s : begin
              // wait until rest of frame has been cleared.
              if (rd_eof_reg == 1'b1)
                 rd_nxt_state <= IDLE_s;
              else
                 rd_nxt_state <= DROP_s;
              end
           RETRANSMIT_s : begin
              // reload the data pipe from the start of the frame
                 rd_nxt_state <= QUEUE1_s;
              end
           default : begin
                 rd_nxt_state <= IDLE_s;
              end
        endcase
  end

end // gen_hd_sm                               // half duplex state machine
endgenerate
   
  //---------------------------------------------------------------------------
  // decode output signals
  // decode output data
  always @(posedge rd_clk)
  begin
     if (rd_enable == 1'b1)
        begin
        if (rd_nxt_state == FRAME_s)
           tx_data <= rd_data_pipe;
        else
	   begin
           case (rd_state)
              QUEUE_ACK_s : 
                 tx_data <= rd_data_pipe;
              WAIT_ACK_s : 
		 tx_data <= tx_data;		 
              FRAME_s :
                 tx_data <= rd_data_pipe;
              default :
                 tx_data <= 8'b0;
           endcase
           end
        end  
  end

  // decode output data valid
  always @(posedge rd_clk)
  begin
     if (rd_enable == 1'b1)
        begin
        if (rd_nxt_state == FRAME_s)
           tx_data_valid <= ~(tx_collision && ~(tx_retransmit));
        else
 	   begin
           case (rd_state)
              QUEUE_ACK_s :
                 tx_data_valid <= 1'b1;
              WAIT_ACK_s :
                 tx_data_valid <= 1'b1;
              FRAME_s :
                 tx_data_valid <= ~(rd_nxt_state == DROP_s);
              default :
                 tx_data_valid <= 1'b0;
           endcase
           end
        end   
  end

  //---------------------------------------------------------------------------
  // decode full duplex only control signals
generate if (FULL_DUPLEX_ONLY == 1) begin : gen_fd_decode

  assign rd_en = (rd_state == IDLE_s) ? 1'b0 :
                 (rd_nxt_state == FRAME_s) ? 1'b1 :
                 (rd_state == WAIT_ACK_s) ? 1'b0 : 1'b1;
  
  assign rd_addr_inc = rd_en;
  
  assign rd_addr_reload = (rd_state == FRAME_s && rd_nxt_state == IDLE_s) ? 1'b1 : 1'b0;

  // Transmit frame pulse is only 1 clock enabled pulse long.
  // Transmit frame pulse must never be more frequent than 64 clocks to allow toggle to cross clock domain
  assign rd_transmit_frame = (rd_state == WAIT_ACK_s && rd_nxt_state == FRAME_s) ? 1'b1 : 1'b0;

  // unused for full duplex only
  assign rd_start_addr_reload = 1'b0;
  assign rd_start_addr_load   = 1'b0;
  assign rd_retransmit_frame  = 1'b0;

end // gen_fd_decode                              // full duplex control signals
endgenerate
   
  //---------------------------------------------------------------------------
  // decode half duplex control signals
generate if (FULL_DUPLEX_ONLY != 1) begin : gen_hd_decode

  assign rd_en = (rd_state == IDLE_s) ? 1'b0 :
                 (rd_nxt_state == DROP_s && rd_eof == 1'b1) ? 1'b0 :
                 (rd_nxt_state == FRAME_s) ? 1'b1 :
                 (rd_state == RETRANSMIT_s) ? 1'b0 :
                 (rd_state == WAIT_ACK_s) ? 1'b0 : 1'b1;
  
  assign rd_addr_inc = rd_en;
  
  assign rd_addr_reload = (rd_state == FRAME_s && rd_nxt_state == IDLE_s) ? 1'b1 :
                          (rd_state == DROP_s && rd_nxt_state == IDLE_s) ? 1'b1 : 1'b0;

  assign rd_start_addr_reload = (rd_state == RETRANSMIT_s) ? 1'b1 : 1'b0;
  
  assign rd_start_addr_load = (rd_state == WAIT_ACK_s && rd_nxt_state == FRAME_s) ? 1'b1 :
                              (rd_col_window_expire == 1'b1) ? 1'b1 : 1'b0;

  // Transmit frame pulse must never be more frequent than 64 clocks to allow toggle to cross clock domain
  assign rd_transmit_frame = (rd_state == WAIT_ACK_s && rd_nxt_state == FRAME_s) ? 1'b1 : 1'b0;

  // Retransmit frame pulse must never be more frequent than 16 clocks to allow toggle to cross clock domain
  assign rd_retransmit_frame = (rd_state == RETRANSMIT_s) ? 1'b1 : 1'b0;
  
end // gen_hd_decode                           // half duplex control signals
endgenerate
  
  //---------------------------------------------------------------------------
  // Frame Count
  // We need to maintain a count of frames in the fifo, so that we know when a
  // frame is available for transmission.  The counter must be held on the
  // write clock domain as this is the faster clock.
  //---------------------------------------------------------------------------

  // A frame has been written to the fifo
  assign wr_store_frame = (wr_state == EOF_s && wr_nxt_state != EOF_s) ? 1'b1 : 1'b0;
  
  // generate a toggle to indicate when a frame has been transmitted from the fifo
  always @(posedge rd_clk)
  begin  // process
     if (rd_sreset == 1'b1)
         rd_tran_frame_tog <= 1'b0;
     else if (rd_enable == 1'b1)
        if (rd_transmit_frame == 1'b1)     // assumes EOF_s is valid for one clock
                                        // cycle only ever!  check
              rd_tran_frame_tog <= !rd_tran_frame_tog;
  end

  // move the read transmit frame signal onto the write clock domain
  always @(posedge wr_clk)
  begin 
      if (wr_sreset == 1'b1)
	 begin
            wr_tran_frame_tog  <= 1'b0;
            wr_tran_frame_sync <= 1'b0;
            wr_tran_frame_delay <= 1'b0;
            wr_transmit_frame   <= 1'b0;
         end
      else
	begin
           wr_tran_frame_tog  <= rd_tran_frame_tog;
           wr_tran_frame_sync <= wr_tran_frame_tog;
           wr_tran_frame_delay <= wr_tran_frame_sync;
           // edge detector
           if ((wr_tran_frame_delay ^ wr_tran_frame_sync) == 1'b1)
             wr_transmit_frame    <= 1'b1;
           else
             wr_transmit_frame    <= 1'b0;
        end
  end

  //---------------------------------------------------------------------------  
generate if (FULL_DUPLEX_ONLY == 1) begin : gen_fd_count
     
  // count the number of frames in the fifo.  the counter is incremented when a
  // frame is stored and decremented when a frame is transmitted.  Need to keep
  // the counter on the write clock as this is the fastest clock.
  always @(posedge wr_clk)
  begin 
     if (wr_sreset == 1'b1)
        wr_frames <= 9'b0;
     else
        if ((wr_store_frame & !wr_transmit_frame) == 1'b1)
           wr_frames <= wr_frames + 1;
        else if ((!wr_store_frame & wr_transmit_frame) == 1'b1)
           wr_frames <= wr_frames - 1;
  end
  
end // gen_fd_count
endgenerate

  //---------------------------------------------------------------------------
generate if (FULL_DUPLEX_ONLY != 1) begin : gen_hd_count
     
  // generate a toggle to indicate when a frame has been transmitted from the fifo
  always @(posedge rd_clk)
  begin  // process
     if (rd_sreset == 1'b1)
        rd_retran_frame_tog <= 1'b0;
     else if (rd_enable == 1'b1)
        if (rd_retransmit_frame == 1'b1)     // assumes EOF_s is valid for one clock
                                   // cycle only ever!  check
           rd_retran_frame_tog <= !rd_retran_frame_tog;
  end

  // move the read transmit frame signal onto the write clock domain
  always @(posedge wr_clk)
  begin 
     if (wr_sreset == 1'b1)
        begin
           wr_retran_frame_tog  <= 1'b0;
           wr_retran_frame_sync <= 1'b0;
           wr_retran_frame_delay <= 1'b0;
           wr_retransmit_frame  <= 1'b0;
	end
     else
        begin
           wr_retran_frame_tog  <= rd_retran_frame_tog;
           wr_retran_frame_sync <= wr_retran_frame_tog;
           wr_retran_frame_delay <= wr_retran_frame_sync;
           // edge detector
           if ((wr_retran_frame_delay ^ wr_retran_frame_sync) == 1'b1)
              wr_retransmit_frame    <= 1'b1;
           else
              wr_retransmit_frame    <= 1'b0;
        end
  end

  // count the number of frames in the fifo.  the counter is incremented when a
  // frame is stored or retransmitted and decremented when a frame is transmitted.  Need to keep
  // the counter on the write clock as this is the fastest clock.
  // Assumes transmit and retransmit cannot happen at same time
  always @(posedge wr_clk)
  begin 
     if (wr_sreset == 1'b1)
        wr_frames <= 9'b0;
     else
        if ((wr_store_frame & wr_retransmit_frame) == 1'b1)
           wr_frames <= wr_frames + 2;
        else if (((wr_store_frame | wr_retransmit_frame) & !wr_transmit_frame) == 1'b1)
           wr_frames <= wr_frames + 1;
        else if (wr_transmit_frame == 1'b1 & !wr_store_frame)
           wr_frames <= wr_frames - 1;
  end
  
end // gen_hd_count
endgenerate


  //---------------------------------------------------------------------------
  // generate a frame in fifo signal for use in control logic
  always @(posedge wr_clk)
  begin 
      if (wr_sreset == 1'b1)
         wr_frame_in_fifo <= 1'b0;
      else
         if (wr_frames != 9'b0)
            wr_frame_in_fifo <= 1'b1;
         else
            wr_frame_in_fifo <= 1'b0;
  end

  // register back onto read domain for use in the read logic
  always @(posedge rd_clk)
  begin 
     if (rd_sreset == 1'b1) 
        begin
           frame_in_fifo_sync <= 1'b0;
           frame_in_fifo <= 1'b0;
        end
     else if (rd_enable == 1'b1)
        begin
           frame_in_fifo_sync <= wr_frame_in_fifo;
           frame_in_fifo <= frame_in_fifo_sync;
        end
  end

  //---------------------------------------------------------------------------
  // Address counters
  //---------------------------------------------------------------------------
  // Address counters
  // write address is incremented when write enable signal has been asserted
  always @(posedge wr_clk)
  begin
     if (wr_sreset == 1'b1)
        wr_addr <= 12'b0;
     else if (wr_addr_reload == 1'b1)
        wr_addr <= wr_start_addr;
     else if (wr_addr_inc == 1'b1)
        wr_addr <= wr_addr + 1;
  end

  // store the start address incase the address must be reset
  always @(posedge wr_clk)
  begin
     if (wr_sreset == 1'b1)
        wr_start_addr <= 12'b0;
     else if (wr_start_addr_load == 1'b1)
        wr_start_addr <= wr_addr + 1;
  end

  //---------------------------------------------------------------------------
generate if (FULL_DUPLEX_ONLY == 1) begin : gen_fd_addr
  // read address is incremented when read enable signal has been asserted
  always @(posedge rd_clk)
  begin
     if (rd_sreset == 1'b1)
        rd_addr <= 12'b0;
     else if (rd_enable == 1'b1)
        if (rd_addr_reload == 1'b1)
           rd_addr <= rd_dec_addr;
        else if (rd_addr_inc == 1'b1)
           rd_addr <= rd_addr + 1;
  end

  // do not need to keep a start address, but the address is needed to
  // calculate fifo occupancy.
  always @(posedge rd_clk)
  begin
     if (rd_sreset == 1'b1)
        rd_start_addr <= 12'b0;
     else if (rd_enable == 1'b1)
        rd_start_addr <= rd_addr;
  end


  

⌨️ 快捷键说明

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