首先前向会引入至少一个cyc的延迟,前向 m_valid和m_dout是寄存器输出
而后向是s_ready寄存器输出,如果m_ready没有反压,数据不会有delay。
根据实际情况选择使用,也可以两个级联使用。
1.前向插流水
assign s_ready = (~m_valid) | m_ready;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
m_valid <= 1'd0;
else if (start == 1'd1)
m_valid <= 1'd0;
else if (s_valid == 1'd1)
m_valid <= 1'd1;
else if (m_ready == 1'd1)
m_valid <= 1'd0;
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
m_dout <= {DW{1'd0}};
else if (s_valid == 1'd1 && s_ready == 1'd1)
m_dout <= s_din;
end
1.2 非完整写法
assign s_ready = m_ready;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
m_valid <= 1'd0;
else if (start == 1'd1)
m_valid <= 1'd0;
else if (s_valid == 1'd1 && s_ready == 1'd1)
m_valid <= 1'd1;
else if (m_ready == 1'd1)
m_valid <= 1'd0;
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
m_dout <= {DW{1'd0}};
else if (s_valid == 1'd1 && s_ready == 1'd1)
m_dout <= s_din;
end
这种不完整写法在s_ready和m_valid的产生都和标准写法不一致。这两种写法不能混写。非完整写法和标准写法的时序区别在于,如果最后一级有反压,不完整写法的各级流水都同时停掉了,此时没有充分利用各级流水上的寄存器缓存,各级寄存器可能是空的;而标准写法最后一级反压逐级上传,各级寄存器上都会有数据。
2.后向插流水
2.1 标准写法
assign m_valid = full | (s_valid & s_ready);
assign s_ready = ~full;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
full <= 1'd0;
else if (start == 1'd1)
full <= 1'd0;
else
full <= m_valid & (~m_ready);
end
assign m_dout = (full == 1'd1) ? s_din_ff : s_din;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
s_din_ff <= {DW{1'd0}};
else if (s_valid == 1'd1 && s_ready == 1'd1 && m_ready == 1'd0)
s_din_ff <= s_din;
end
2.2 非标准写法
assign m_dout = (s_valid == 1'd1 && s_ready == 1'd1) ? s_din : s_din_ff;
assign m_valid = (s_valid & s_ready) | m_valid_tmp;
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
m_valid_tmp <= 1'd0;
else if (start == 1'd1)
m_valid_tmp <= 1'd0;
else if (s_valid == 1'd1 && s_ready == 1'd1 && m_ready == 1'd0)
m_valid_tmp <= 1'd1;
else if (m_ready == 1'd1)
m_valid_tmp <= 1'd0;
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
s_din_ff <= {DW{1'd0}};
else if (s_valid == 1'd1 && s_ready == 1'd1 && m_ready == 1'd0)
s_din_ff <= s_din;
end
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'd0)
s_ready <= 1'd0;
else if (start == 1'd1)
s_ready <= 1'd0;
else
s_ready <= m_ready;
end
非标准写法的s_ready和m_valid都和和标准写法不一致。这两种写法不能混写。标准写法只在后级不能接收s_din时才将数据锁存到s_din_ff上面,这两种写法结果应该是一样的。
可以用在后级rdy信号做FIFO/mem的读信号,虽然fifo/mem的读数据比rden晚一拍,用上述后向插流水就没有问题