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

📄 read_ch_arbiter.v

📁 如何使用ISE和FPGA使用指南
💻 V
字号:

//_____________________________________________________________________________________
// read_ch_arbiter.v
//_____________________________________________________________________________________
// This arbiter, arbitrates the next channel to read from.  Each channel that has a pn_lock
// will increment by 1 for each read cycle which it is not the channel read from.  If it is
// the channel that is read it will be reset to 0.  Whichever channel has the highest count
// and maintains a pn_lock will be the next channel to be read.  In this way, at the most, 
// each channel will be read every 4th read cycle.  Channel A has the highest priority, then B, 
// then C, and finally channel D.  If a channel loses lock, its count will be reset to 0. 
//_____________________________________________________________________________________


module read_ch_arbiter(input clk, 
		       input reset, 
		       input waiting_cntr_en, 
		       input next_ch_en, 
		       input [3:0] pn_lock_rd_clk, 
		       input [3:0] almost_full, 
		       input [3:0] almost_empty, 
		       input [3:0] empty, 
		       input [3:0] full, 
		       output [3:0] next_ch);
    
    reg       next_cha, next_chb, next_chc, next_chd;
    reg [2:0] cha_waiting_cntr, chb_waiting_cntr, chc_waiting_cntr, chd_waiting_cntr; // counts the number of cycles between being read.
    reg [3:0] priority, priority_v; // assigns priority to those channels that are almost_full.  Otherwise, 
    // if there are no almost_full channels priority is given to the channels that are not almost_empty.
    wire [2:0] cha_weight, chb_weight, chc_weight, chd_weight; // priority * waiting time
    
    assign next_ch = {next_chd, next_chc, next_chb, next_cha};
    //_____________________________________________________________________________________
    // Counts the number of cycles that each channel has been locked and waiting to output data.
    //_____________________________________________________________________________________
    always @ (posedge clk)
    begin: locked_ch_wait_cntr
	if (reset)
	begin
	    cha_waiting_cntr <= 0;
	    chb_waiting_cntr <= 0;
	    chc_waiting_cntr <= 0;
	    chd_waiting_cntr <= 0;
	end // if (reset)
	else
	begin
	      if (~pn_lock_rd_clk[0] | next_cha)
		cha_waiting_cntr <= 0;
	      else if (waiting_cntr_en & pn_lock_rd_clk[0])// clock enable waiting_cntr_en => Only enabled every 8 clock cycles
		cha_waiting_cntr <= cha_waiting_cntr + 1;
	    
	      if (~pn_lock_rd_clk[1] | next_chb)
		chb_waiting_cntr <= 0;
	      else if (waiting_cntr_en & pn_lock_rd_clk[1])// clock enable waiting_cntr_en => Only enabled every 8 clock cycles
		chb_waiting_cntr <= chb_waiting_cntr + 1;
	    
	    if (~pn_lock_rd_clk[2] | next_chc)
		chc_waiting_cntr <= 0;
	      else if (waiting_cntr_en & pn_lock_rd_clk[2])// clock enable waiting_cntr_en => Only enabled every 8 clock cycles
		chc_waiting_cntr <= chc_waiting_cntr + 1;

	      if (~pn_lock_rd_clk[3] | next_chd)
		chd_waiting_cntr <= 0;
	      else if (waiting_cntr_en & pn_lock_rd_clk[3])// clock enable waiting_cntr_en => Only enabled every 8 clock cycles
		chd_waiting_cntr <= chd_waiting_cntr + 1;
	end // else: !if(reset)
    end // block: locked_ch_wait_cntr

    //_____________________________________________________________________________________
    // Assigns priority to those channels that are almost_full.  If no channel is almost_full,
    // priority is assigned to those channels that are NOT almost_empty.  Finally, if there
    // is no priority, then the read is based on the waiting counters.
    //_____________________________________________________________________________________
    always @ (posedge clk)
    begin
	if (reset)
	  priority <= 0;
	else
	  begin
	      // default
	      priority_v = 0;
	      
	      if (|full) // highest priority given to those channels that are full
		priority_v = full;
	      else if (|almost_full) // priority is given to those channels that are almost_full
		priority_v = almost_full;
	      else // if no channels are almost full, priority is given to the channels that are not almost_empty
		if (|almost_empty) // if locked channels are the same as the almost_empty channelss
		  priority_v = ~almost_empty; 

	      if (|priority_v == 0 | ((priority_v & pn_lock_rd_clk) == 4'b0000))  // if there isn't any priority, the priority 
	        // will go to the highest waiting period
		priority_v = pn_lock_rd_clk;
	      else
		priority_v = priority_v & pn_lock_rd_clk;

	      priority <= priority_v & ~empty;// give the highest priority to those channels that are NOT empty
	  end // else: !if(reset)
	
    end // always @ (posedge clk or posedge reset)
    

    assign cha_weight = (priority[0]) ? cha_waiting_cntr + 1 : 0;
    assign chb_weight = (priority[1]) ? chb_waiting_cntr + 1 : 0;
    assign chc_weight = (priority[2]) ? chc_waiting_cntr + 1 : 0;
    assign chd_weight = (priority[3]) ? chd_waiting_cntr + 1 : 0;
    
    //_____________________________________________________________________________________
    // Read channel Arbiter.  Which ever channel is locked and has the highest "weight"
    // will be the next channel that is read.  
    //_____________________________________________________________________________________
    always @ (posedge clk)
    begin: next_ch_read_arbiter
	if (reset)
	begin
	    next_cha <= 0;
	    next_chb <= 0;
	    next_chc <= 0;
	    next_chd <= 0;
	end // if (reset)
	else
	begin
	    if (next_ch_en)
	    begin
		// defaults
		next_cha <= 0;
		next_chb <= 0;
		next_chc <= 0;
		next_chd <= 0;
		
		case (priority)
		    4'b0000:
		    begin
			next_cha <= 0;
			next_chb <= 0;
			next_chc <= 0;
			next_chd <= 0;
		    end
		    default:
		      begin
			  next_cha <= ((cha_weight >= chb_weight) & 
				       (cha_weight >= chc_weight) & (cha_weight >= chd_weight));
			  next_chb <= ((chb_weight > cha_weight) & 
				       (chb_weight >= chc_weight) & (chb_weight >= chd_weight));
			  next_chc <= ((chc_weight > cha_weight) & 
				       (chc_weight > chb_weight) & (chc_weight >= chd_weight));
			  next_chd <= ((chd_weight > cha_weight) & 
				       (chd_weight > chb_weight) & (chd_weight > chc_weight));
		      end // case: default
		endcase // case(priority)
 	    end // if (next_ch_en)
	end // else: !if(reset)
    end // block: next_ch_read_arbiter


endmodule // read_ch_arbiter

⌨️ 快捷键说明

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