credit_based 流控管理-2
上篇文章是简要介绍一下基于credit的流控原理,和实现方法;
本篇序列是应对: when the design can send and return more than one credits at a time.
针对考虑解决:
- send and return credits > 1 at a time. notes: have the send_units and taken_units port.
- offer overflow and underflow protection.
code blocks are as belows:
以下代码未经过编译和功能验证,仅供逻辑参考;
verilog
//--Auther :colonel
//--Date :2024-05-23
//--Function:credit_based for flow control
// consider for the send and return credits at a time.
//--History :Description
//--05/22 :Firstly create the file
//
module crdt_tracker_multi#(
parameter WIDTH = 4
)(
input clk,
input rst_n,
input [WIDTH -1:0] crdt_limit,
input send,
input [WIDTH -1:0] send_units,
input taken,
input [WIDTH -1:0] taken_units,
output reg has_crdt,
output reg[WIDTH -1:0] crdt_left
);
reg [WIDTH -1:0] crdt_cnt;
wire[WIDTH :0] nxt_crdt_cnt;//Note: Width changed
wire[WIDTH :0] delta; //minus units:send minus taken
wire overflow;
wire underflow;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
crdt_cnt <= 0;
end else begin
if(overflow || underflow) begin
crdt_cnt <= (overflow) ? crdt_limit:0;
end else begin
crdt_cnt <= nxt_crdt_cnt;
end
end
end
always@(*) begin
delta = 0;
nxt_crdt_cnt = {1'b0,crdt_cnt};
if(send && !taken) begin
delta = {1'b0,send_units};
nxt_crdt_cnt = {1'b0,crdt_cnt} + delta;
end else if(!send && taken) begin
delta = {1'b0,taken_units}
nxt_crdt_cnt = {1'b0,crdt_cnt} - delta;
end else if(send && taken) begin
delta = {1'b0,send_units} - {1'b0,taken_units};
nxt_crdt_cnt = {1'b0,crdt_cnt} + delta;
end else begin
delta = delta;
nxt_crdt_cnt = nxt_crdt_cnt;
end
end
//--underflow and overflow logic
assign underflow = send && (~delta[WIDTH-1] && nxt_crdt_cnt[WIDTH] || (send_units>taken_units))
assign overflow = taken && (delta[WIDTH-1] && nxt_crdt_cnt[WIDTH] || (taken_units>send_units))
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
has_crdt <= 1'b0;
crdt_left<= crdt_limit;
end else begin
if(nxt_crdt_cnt < crdt_limit) begin
has_crdt <= 1'b1;
crdt_left<= crdt_limit - nxt_crdt_cnt;
end else begin
has_crdt <= 1'b0;
crdt_left<= 0;
end
end
end
endmodule
Reference: