协议实现
相信网上已经有很多文章对valid/ready的原理与应用等进行了很详细的描述,这里就不再赘述,直接上代码:
module frs #(parameter DW='d256)(
input [DW-1:0] m_data ,
input m_valid ,
output m_ready ,
output reg [DW-1:0] s_data ,
output reg s_valid ,
input s_ready ,
input clk ,
input rst_n
);
//============== Forward Registered ========
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
s_valid <= 1'd0;
else if (m_valid == 1'd1)
s_valid <= 1'd1;
else if (s_ready == 1'd1)
s_valid <= 1'd0;
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
s_data <= 'd0;
else if (m_valid == 1'd1 && m_ready == 1'd1)
s_data <= m_data;
end
assign m_ready = (~s_valid) | s_ready;
endmodule
ready信号打拍
当设计中数据流处理的流水线级数比较多时,ready的时序将会变得很差,这可以通过对ready信号寄存一拍来改善其时序。
module brs #(parameter DW='d256)(
input [DW-1:0] m_data ,
input m_valid ,
output m_ready ,
output [DW-1:0] s_data ,
output s_valid ,
input s_ready ,
input clk,
input rst_n
);
reg valid_tmp0;
reg [DW-1:0] payload_tmp0;
reg ready_d1;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
valid_tmp0 <= 1'd0;
else if (m_valid == 1'd1 && s_ready == 1'd0 && valid_tmp0 == 1'd0)
valid_tmp0 <= 1'd1;
else if (s_ready == 1'd1)
valid_tmp0 <= 1'd0;
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
payload_tmp0 <= 'd0;
else if (m_valid == 1'd1 && s_ready == 1'd0 && valid_tmp0 == 1'd0)
payload_tmp0 <= m_data;
end
assign s_data = (valid_tmp0 == 1'd1) ? payload_tmp0 : m_data;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
ready_d1 <= 1'd0;
else
ready_d1 <= s_ready;
end
assign m_ready = ~valid_tmp0 | ready_d1;
assign s_valid = valid_tmp0 | m_valid;
endmodule
仿真
仿真图如下,可以看到仿真结果正确。