我最后提交的RTL呢,data_out是reg输出的,valid_b不是reg输出,后面也提交了一版valid_b reg输出的代码。

既然在累加四次的下一拍valid_b就必须要输出有效,那么可见这个题的核心就在于记录累加次数的计数器,所以我们就先做这个计数器好了:

wire hand_a = (valid_a && ready_a);
wire hand_b = (valid_b && ready_b);

//add num cnt
wire         cnt_en;
wire [3 -1:0]cnt_d;
wire [3 -1:0]cnt_q;
assign cnt_en = hand_a || hand_b;
assign cnt_d  = (hand_a && hand_b) ? 3'd1 :
                hand_b ? 3'd0 :
                cnt_q + 3'd1;
dffre #(.WIDTH(3)) u_cnt_dffre(
    .clk(clk),
    .rst_n(rst_n),
    .d(cnt_d),
    .en(cnt_en),
    .q(cnt_q)
);

这个cnt的寄存器位3bit,更新的条件必定是输入握手成功或输出握手成功,逻辑也很清晰:1.当只有输入握手时,cnt + 1;2.当只有输出握手时,cnt归零;3.当同一拍输入握手&&输出握手时,cnt置1,显然,在这种条件下是没有性能瓶颈的。

ok,cnt的条件已经做完,其他的就变得简单了。

累加寄存器的逻辑很类似,就不赘述了:

wire         value_en;
wire [10 -1:0]value_d;
wire [10 -1:0]value_q;
assign value_en = cnt_en;
assign value_d  = (hand_a && hand_b) ? {2'b0, data_in} :
                  hand_b ? 10'd0 :
                  value_q + {2'b0, data_in};
dffre #(.WIDTH(10)) u_value_dffre(
    .clk(clk),
    .rst_n(rst_n),
    .d(value_d),
    .en(value_en),
    .q(value_q)
);

assign valid_b  = (cnt_q == 3'd4);

wire valid_b_en = cnt_en;
wire valid_b_d  = (cnt_d == 3'd4);
dffre #(.WIDTH(10)) u_valid_b_dffre(
    .clk(clk),
    .rst_n(rst_n),
    .d(valid_b_d),
    .en(valid_b_en),
    .q(valid_b)
);

assign ready_a  = (cnt_q != 3'd4);

因为不能有空泡,所以输入的ready要看输出的握手,这样虽然性能更好,但是时序更差:

assign ready_a  = (cnt_q != 3'd4) || hand_b;

 完整代码

`timescale 1ns/1ns

module dffre#(
    parameter WIDTH = 1
)(
    input                 clk,
    input                 rst_n,
    input  [WIDTH -1:0]    d,
    input                en,
    output [WIDTH -1:0]    q
);
reg [WIDTH -1:0]q;
always @(posedge clk or negedge rst_n)begin
    if(~rst_n)  q <= {WIDTH{1'b0}};
    else if(en) q <= d;
end
endmodule

module valid_ready(
    input                 clk         ,   
    input                 rst_n        ,
    input        [7:0]    data_in        ,
    input                valid_a        ,
    input                 ready_b        ,
 
     output                 ready_a        ,
     output                valid_b        ,
    output      [9:0]     data_out
);

parameter MAX = 4;

wire hand_a = (valid_a && ready_a);
wire hand_b = (valid_b && ready_b);

//add num cnt
wire         cnt_en;
wire [3 -1:0]cnt_d;
wire [3 -1:0]cnt_q;
assign cnt_en = hand_a || hand_b;
assign cnt_d  = (hand_a && hand_b) ? 3'd1 :
                hand_b ? 3'd0 :
                cnt_q + 3'd1;
dffre #(.WIDTH(3)) u_cnt_dffre(
    .clk(clk),
    .rst_n(rst_n),
    .d(cnt_d),
    .en(cnt_en),
    .q(cnt_q)
);

//add num value
wire         value_en;
wire [10 -1:0]value_d;
wire [10 -1:0]value_q;
assign value_en = cnt_en;
assign value_d  = (hand_a && hand_b) ? {2'b0, data_in} :
                  hand_b ? 10'd0 :
                  value_q + {2'b0, data_in};
dffre #(.WIDTH(10)) u_value_dffre(
    .clk(clk),
    .rst_n(rst_n),
    .d(value_d),
    .en(value_en),
    .q(value_q)
);

//gen hand
wire valid_b_en = cnt_en;
wire valid_b_d  = (cnt_d == 3'd4);
dffre #(.WIDTH(10)) u_valid_b_dffre(
    .clk(clk),
    .rst_n(rst_n),
    .d(valid_b_d),
    .en(valid_b_en),
    .q(valid_b)
);
    
//assign valid_b  = (cnt_q == 3'd4);
assign ready_a  = (cnt_q != 3'd4) || hand_b;
assign data_out = value_q;

endmodule
没有mismatch但是就是报比对不过,改用
assign valid_b  = (cnt_q == 3'd4);
就过了,而我在verdi里比了一下,两个结果是完全对的上的啊


收藏