题解 | #数据累加输出#
数据累加输出
https://www.nowcoder.com/practice/956fa4fa03e4441d85262dc1ec46a3bd
`timescale 1ns/1ns module valid_ready( input clk , input rst_n , input [7:0] data_in , input valid_a , input ready_b , output ready_a , output reg valid_b , output reg [9:0] data_out ); //计数器控制块。计四拍。00 01 10 11 -> 00 01 10 11 -> ...... reg [1:0] cnt; always@(posedge clk or negedge rst_n) begin if(!rst_n) cnt <= 2'b00; else if (valid_a && ready_a) cnt <= cnt + 1'b1; //接受数据 else cnt <= cnt; //不接受数据 end /* 【总时序】 本模块在valid_a和ready_a握手(都拉高)后,开始接收上游下行的数据;(ready_a是输出,受制于其他变量) 本模块接受数据时,valid_b始终保持低。(并且ready_a也拉低,不允许输入) 接收完四个数据并累加后,valid_b拉高(表示data_out有效),等待ready_b握手。 ready_b握手(拉高)后,data_out被赋予值。此时ready_a应立刻拉高,进行下一轮读取和累加。 */ /* 【两次握手】 1.输入握手:valid_a和ready_a。(ready_a等待valid_a) 2.输出握手:valid_b和ready_b。(valid_b等待ready_b) 【握手间的相互制约】 输出握手后,ready_a立刻拉高。 */ /* ready_a 和 valid_b: 1. 他们是 OUTPUT,需要我们手动去拉高拉低。 2. 他们控制时序,互为判断依据。 */ //ready_a拉高的情况:1.ready_b拉高时,本模块数据下行,此时立刻允许新的data输入,立刻拉高ready_a。(保证无气泡传输) // 2.valid_b拉低时,本模块还在接受数据,ready_a持续高。 assign ready_a = (ready_b || !valid_b) ? 1 : 0; //valid_b拉高拉低的情况: 1.本模块接收完数据时:valid_b拉高。(此时即在等待ready_b握手,进行下行输出) // 2.valid_b和ready_b握手后,打一拍,valid_b再次拉低,准备接受新的数据。 //【valid_b:指示data_out数据是否有效,即指示“输入是否完成”和“输出是否完成”】 always@(posedge clk or negedge rst_n) begin if(!rst_n) valid_b <= 1'b0; else if(valid_a && ready_a && (cnt == 2'b11)) //1.输入结束,等待握手 valid_b <= 1'b1; else if(valid_b && ready_b) //2.输出握手后 valid_b <= 1'b0; end //数据写入和写出 always@(posedge clk or negedge rst_n) begin if(!rst_n) data_out <= 0; else if((cnt == 2'b00) && valid_a && ready_a && ready_b) //接收完毕,等待ready_b拉高。ready_b一旦拉高,数据写出到data_out。 //同时开始下一周期的写入。 data_out <= data_in; else if(valid_a && ready_a) //输入握手:正在接收上游数据,累加 data_out <= data_out + data_in; //注意:这两个else if不能调换位置!!!【md看了半天】 end endmodule