引言
我们知道时序路径的建立时间收敛依赖于触发器之间的组合逻辑延迟,以及时钟周期。对于一个确定的设计一般来说,时钟频率不会有太多的让步,因此修时序的时候主要发力点就是减小触发器之间组合逻辑延迟。一方面可以通过组合逻辑优化来降低组合逻辑延迟,另一方面也可以通过插入寄存器来优化时序。register slice 在数字设计中常用来打断前后级的逻辑(握手型总线协议),保证timing收敛,同时实现pipeline的高性能效果。AXI协议是目前广泛采用的总线协议(握手型总线协议)。为了使总线能够跑上更高的频率,获得更好的timing性能,register slice 被广泛采用,用于切断/分割AXI总线的critical timing path。
RS(register slice)前向打拍器则是针对握手型(valid-ready)接口的valid时序优化(建立时间)。握手型信号在打拍时是不能简单的对valid信号打拍的,还需要对数据信号同步打拍。否则valid和data就不能对齐,出现逻辑错误。
RS前向打拍器的逻辑其实比较容易理解,可以理解为深度为1的buffer,从侧ready拉高的逻辑为主侧ready拉高或者当前valid buffer的输出为低电平(表示valid 的buffer空)。从侧的valid和ready握手成功时,数据由从侧寄存一拍输出到主侧。
可以结合时序图理解一下:
CBB设计源码
// ==================-------------------------------------------------------=====================
// 在路上-正出发
// Common Building Block
// ==================-------------------------------------------------------=====================
// ________ ________ ________
// |\ ____\ |\ __ \ |\ __ \
// \ \ \___| \ \ \|\ /_ \ \ \|\ /_
// \ \ \ \ \ __ \ \ \ __ \
// \ \ \____ \ \ \|\ \ \ \ \|\ \
// \ \_______\ \ \_______\ \ \_______\
// \|_______| \|_______| \|_______|
// ==================-------------------------------------------------------=====================
// 在路上-正出发
// Common Building Block
// ==================-------------------------------------------------------=====================
// CBB Module Name :CBB_RS_FORWARD
// CBB Created Date :2024-08-04
// CBB Module Function:Register Slice mode:forward
// Usage Limitation :
// Author :在路上-正出发
// -----------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------
`timescale 1ns/1ps
module CBB_RS_FORWARD #(
// ---- parameter define
parameter P_DATA_WIDTH = 64
)(
// ---- port define
input i_clk,
input i_rstn,
input slv_i_valid,
input [P_DATA_WIDTH-1:0] slv_i_data,
output slv_o_ready,
output mst_o_valid,
output [P_DATA_WIDTH-1:0] mst_o_data,
input mst_i_ready
);
reg r_mst_o_valid;
reg [P_DATA_WIDTH-1:0] r_mst_o_data;
assign slv_o_ready = mst_i_ready || (~r_mst_o_valid);
always @(posedge i_clk or negedge i_rstn) begin : proc_valid
if(~i_rstn) begin
r_mst_o_valid <= 1'b0;
end else if (slv_o_ready)begin
r_mst_o_valid <= slv_i_valid;
end
end
always @(posedge i_clk)begin:proc_data
if(slv_i_valid & slv_o_ready) begin
r_mst_o_data <= slv_i_data;
end
end
assign mst_o_valid = r_mst_o_valid;
assign mst_o_data = r_mst_o_data;
endmodule
CBB验证
从侧 valid信号拉高的时间间隔随机,且拉高的时机与ready无关,主侧ready信号拉高的持续时间随机,相邻两个高电平之间的间隔随机。包括各种反压case。
验证源码
// ==================-------------------------------------------------------=====================
// 在路上-正出发
// Common Building Block
// ==================-------------------------------------------------------=====================
// ________ ________ ________
// |\ ____\ |\ __ \ |\ __ \
// \ \ \___| \ \ \|\ /_ \ \ \|\ /_
// \ \ \ \ \ __ \ \ \ __ \
// \ \ \____ \ \ \|\ \ \ \ \|\ \
// \ \_______\ \ \_______\ \ \_______\
// \|_______| \|_______| \|_______|
// ==================-------------------------------------------------------=====================
// 在路上-正出发
// Common Building Block
// ==================-------------------------------------------------------=====================
// CBB Module Name :TB_RS_FORWARD
// CBB Created Date :2024-08-04
// CBB Module Function:
// Usage Limitation :
// Author :在路上-正出发
// -----------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------
`timescale 1ns/1ps
module TB_RS_FORWARD();
// ---- parameter define
parameter P_DATA_WIDTH = 32;
// ---- port define
reg i_clk;
reg i_rstn;
reg slv_i_valid;
reg [P_DATA_WIDTH-1:0] slv_i_data;
wire slv_o_ready;
wire mst_o_valid;
wire [P_DATA_WIDTH-1:0] mst_o_data;
reg mst_i_ready;
initial i_clk = 1'b0;
always #5 i_clk = ~i_clk;
integer time_dly1,time_dly2;
initial
begin
i_rstn = 1'b0;
mst_i_ready = 1'b0;
#20;
i_rstn = 1'b1;
#20;
repeat(20)
begin
time_dly1 = $urandom_range(1,10);
repeat(time_dly1)
begin
@(posedge i_clk);
end
@(posedge i_clk)
mst_i_ready <= 1'b1;
time_dly1 = $urandom_range(1,10);
repeat(time_dly1)
begin
@(posedge i_clk);
end
@(posedge i_clk)
mst_i_ready <= 1'b0;
end
end
initial
begin
slv_i_valid = 1'b0;
slv_i_data = 0;
@(posedge i_rstn);
#20;
repeat(20)
begin
@(posedge i_clk)
slv_i_valid <= 1'b1;
slv_i_data <= $random();
while(~slv_o_ready) @(posedge i_clk);
@(posedge i_clk)
slv_i_valid <= 1'b0;
slv_i_data <= 0;
time_dly2 = $urandom_range(1,10);
repeat(time_dly2) @(posedge i_clk);
end
#100;
$finish;
end
CBB_RS_FORWARD #(
.P_DATA_WIDTH(P_DATA_WIDTH)
) U_CBB_RS_FORWARD (
.i_clk (i_clk),
.i_rstn (i_rstn),
.slv_i_valid (slv_i_valid),
.slv_i_data (slv_i_data),
.slv_o_ready (slv_o_ready),
.mst_o_valid (mst_o_valid),
.mst_o_data (mst_o_data),
.mst_i_ready (mst_i_ready)
);
endmodule
波形
CBB综合
综合结果,可以明确看出,前向RS打拍器对输入数据以及valid信号做了打拍处理,完全切断了从侧与主侧valid 以及data的timing path,有助于这两个信号的建立时间收敛。但是ready信号则是通过组合逻辑由主侧传递到从侧,并没有切断从侧与主侧的timing path,因此前向打拍器不能够优化ready信号的时序。