题解 | #数据累加输出#

数据累加输出

http://www.nowcoder.com/practice/956fa4fa03e4441d85262dc1ec46a3bd

题意整理

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


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

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

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

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

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

题解主体

要实现4个输入数据的累加,要用1个寄存器将先到达的数据累加之后进行缓存。当上游握手成功,将输入数据累加进寄存器;当累加完4个输入数据,且下游握手成功,将新的输入数据缓存进寄存器。注意,之所以这样设计,是为了不造成性能损失,而之前的累加结果,已经传给了下游。

需要计数器来计数接收到的数据数量,计数器在0-3之间循环。计数器初始值是0,每接收一个数据,计数器加1,当计数器再次循环到0时,表示已经接收到4个数据,可以输出累加结果。


对于ready_a输出信号的产生,如果下游ready_b拉高,表示下游可以接收模块输出数据,那么此时ready_a应拉高,即本模块可以接收上游数据;如果没有接收够4个数据,即valid_b未拉高,那么表示本模块仍可以接收上游数据此时ready_a应拉高。所以综上所述,ready_a信号的产生采用组合逻辑产生。

Verilog代码如下:


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

参考答案

`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


全部评论
您好,data_in是8位,dataout是10位,累加的话应该补符号位或者加signed吧?
1 回复 分享
发布于 2022-05-02 10:06
else if(ready_b && valid_a && ready_a && (data_cnt == 2'd0))这里应该不需要ready_b吧
3 回复 分享
发布于 2023-08-11 15:36 湖北
这个代码有问题啊。 如果valid_a在初始发送三个数值后被拉低,按你的代码这个时候data_cnt == 2'd3,valid_b被拉高了,但这个时候只输入了三个数据不应该有数据输出。
1 回复 分享
发布于 2022-03-06 20:50
ready_a肯定只是和ready_b有关,参考hready_o的设计,还有data_out需要第一次为data_in要补齐位宽,反压一定是ready_b反压ready_a, 从而结合valid_a控制寄存器,和valid_b没有任何关系,valid_b只和计数器和ready_b有关
点赞 回复 分享
发布于 2023-03-22 14:27 陕西
这个代码波形不满足题目要求,仿真一下就看出来了。
点赞 回复 分享
发布于 2023-01-24 01:02 河北
else if (valid_a &&ready_a) data_out <= data_out + data_in; 这句好像不太对啊,这表示在时钟来的时候valid_a和ready_a都要是高电平才能进行计算,但是时序图里,时钟来的时候,ready_a已经变为低电平了,怎么会进行计算呢?求教
点赞 回复 分享
发布于 2022-11-27 23:16 北京
求教,答案中 else if(ready_b && valid_a && ready_a && (data_cnt == 2'd0)) data_out <= data_in; 这里为什么需要ready_b信号为高电平?
点赞 回复 分享
发布于 2022-09-20 19:19 上海
这道题有问题吧,题目要求每当接受四个数据才输出四个之和,但是代码写的必须得是data_out <= data_out + data_in才可以通过,这分明矛盾
点赞 回复 分享
发布于 2022-04-14 16:20
if(ready_b && valid_a && ready_a && (data_cnt == 2'd0)) data_out <= data_in; 这个代码什么意思啊。怎么输入直接链接输出了呀,按照这条件在ready-b完成握手的同时(如题目完成第一个data-out输出),完全满足if的条件,但是题目给的图中data-out还是10呀,10也没有变成此时的data-in呀
点赞 回复 分享
发布于 2022-03-07 21:41

相关推荐

评论
45
4
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务