前言
【芯片前端】保持代码手感——一对多的握手拆分模块_尼德兰的喵的博客-CSDN博客_前端拆分模块
有一对多的握手场景,就必然有多对一的握手场景,这篇文章就是探究下握手融合场景应该如何组织rtl。
接口
握手融合嘛,那必然是上游有多组握手接口,下游有一组握手接口:
对应的接口即为:
module hand_merge #( parameter CHANNEL = 2 )( input [CHANNEL -1:0]in_valid, output [CHANNEL -1:0]in_ready, output out_valid, input out_ready ); endmodule
实现
明确下功能,对于多打一的握手merge场景,显然需要上游所有的in_valid均为有效后,才能向下游起out_valid有效,因此对下游的out_valid逻辑很简单:
assign out_valid = &in_valid;
而对上游的in_ready逻辑呢稍微复杂一下,我之前尝试写了两种代码,一种是当所有的in_valid有效且out_ready有效时,对上游起in_ready:
assign in_ready[CHANNEL -1:0]in_ready = {CHANNEL{out_ready && (&in_valid)}};
然后是第二种写法,基于ready和valid解耦的思想,对于某一路的ready实际上不需要看自己这一路的valid,只要其他路的valid都来了,out-ready也有了那么这一路的in_ready就可以有效,此时只要这一路的in_valid一来,就满足了所有in_valid全部到达的条件,如果以这个思路那么组织代码为:
genvar i; generate for(i=0; i<CHANNEL; i=i+1)begin wire [CHANNEL -1:0] mask = {{(CHANNEL-1){1'b0}},1'b1} << i; wire [CHANNEL -1:0] in_valid_mask = in_valid | mask; assign in_ready[i] = out_ready && (&in_valid_mask); end endgenerate
最后我思来想去更加满意的还是第二种思路,因此最终的完成版代码就是这样:
module hand_merge #( parameter CHANNEL = 2 )( input [CHANNEL -1:0]in_valid, output [CHANNEL -1:0]in_ready, output out_valid, input out_ready ); genvar i; generate for(i=0; i<CHANNEL; i=i+1)begin wire [CHANNEL -1:0] mask = {{(CHANNEL-1){1'b0}},1'b1} << i; wire [CHANNEL -1:0] in_valid_mask = in_valid | mask; assign in_ready[i] = out_ready && (&in_valid_mask); end endgenerate assign out_valid = &in_valid; endmodule