alt

本题要求实现将4个输入数据累加之后输出,模块与上下游采用valid-ready双向握手机制。

alt

时序图含有的信息较多,观察时序图需要注意:

  • data_out是在已接收到4个数据后产生输出;

  • 在data_out准备好,valid_b拉高时,如果下游的ready_b为低,表示下游此时不能接收本模块的数据,那么,将会拉低ready_a,以反压上游数据输入;

  • 当下游ready_b拉高,且valid_b为高,表示模块与下游握手成功,valid_b在下一个时钟周期拉低;

  • 当下游ready_b拉高,本来由于之前ready_b为低而反压上游的ready_a立即拉高,开始接收上游数据,注意,此细节,也是体现了题目要求的数据传输无气泡。如果ready_a不是立即拉高,而是在下一个时钟周期拉高,那么本模块将会在下游握手成功后空一个时钟周期,才能开始接收上游数据,这样是不满足题目要求的。

`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
);
reg 	[1:0]		data_cnt;

assign ready_a = !valid_b | ready_b;

always @(posedge clk or negedge rst_n ) begin
	if(!rst_n) 
		data_cnt <= 'd0;
	else if(valid_a && ready_a)
		data_cnt <= (data_cnt == 2'd3) ? 'd0 : (data_cnt + 1'd1);
end
always @(posedge clk or negedge rst_n ) begin
	if(!rst_n) 
		valid_b <= 'd0;
	else if(data_cnt == 2'd3 && valid_a && ready_a)
		valid_b <= 1'd1;
	else if(valid_b && ready_b)
		valid_b <= 1'd0;
end

always @(posedge clk or negedge rst_n ) begin
	if(!rst_n) 
		data_out <= 'd0;
	else if(ready_b && valid_a && ready_a && (data_cnt == 2'd0))
		data_out <= data_in;
	else if(valid_a && ready_a)
		data_out <= data_out + data_in;
	
end


endmodule