📄 read_ch_arbiter.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 + -