我最后提交的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里比了一下,两个结果是完全对的上的啊
收藏
赞
评论加载中...