题目描述
实现串行输入数据累加输出,输入端输入8bit数据,每当模块接收到4个输入数据后,输出端输出4个接收到数据的累加结果。输入端和输出端与上下游的交互采用valid-ready双向握手机制。要求上下游均能满速传输时,数据传输无气泡,不能由于本模块的设计原因产生额外的性能损失。
valid_a用来指示数据输入data_in的有效性,valid_b用来指示数据输出data_out的有效性;ready_a用来指示本模块是否准备好接收上游数据,ready_b表示下游是否准备好接收本模块的输出数据;clk是时钟信号;rst_n是异步复位信号。
看题意似懂非懂,波形图也没有画完整,就我的理解来看
//ready_a用来指示输入准备好的状态,从波形图上看,只有在输出数据时跳变为低电平且维持两个周期
//valid_b在信号有效时置为高电平,且持续三个周期
//valid_a有效时开始计数
//ready_b 没有准备好接收数据 ?
看的答案进一步理解的题意:
1、data_out是在已接收到4个数据后产生输出;
2、在data_out准备好且valid_b拉高时,如果下游的ready_b为低,表示下游此时不能接收本模块的数据,那么,将会拉低ready_a;
3、当下游ready_b拉高,且valid_b为高,表示模块与下游握手成功,输出数据,valid_b在下一个时钟周期拉低;
4、当下游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
);
//ready_a一直保持高电平,只要在需要输出时且下游没有准备后才下拉,在ready_b上升时上升
//所以,只有在valid_b为1且ready_b为0时,ready_a才为0,用来保证不再继续读数
assign ready_a = ! (valid_b&&(!ready_b));
//设一个计数器num;设置一个寄存器保持加数之和
reg [1:0]num;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
num <= 0;
else if( valid_a && ready_a )
num <=(num==3)? 0:num+1;
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
valid_b <= 0;
else if(num == 3 && valid_a && ready_a)
valid_b <=1 ; //何时置1由上游a判断
else if(ready_b && valid_b)
//当valid_b有效准备输出时,只有ready_a为1才说明下游有效可以输出,完成输出后valid_a置0
//何时置0由b下游判断
valid_b <=0 ;
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
data_out <= 0;
else if(num == 0 && ready_b && valid_a && ready_a ) //输出数据归零与valid_b无关,a准备好且有效,b准备好,即可
data_out <=data_in;
else if( valid_a && ready_a )
data_out <= data_out + data_in;
end
endmodule
深入理解valid—ready双向握手机制
需要深入了解波形图及各个参数的意义,ready_a和ready_b表示上下游准备好了数据的传输,valid_a表示输入有效,valid_b表示已经完成四个数据的累加可以输出。
这四个参量如何决定输出?
1、在4个周期计数的判断中,当valid_a==1&&ready_a==1时num+1,即输入有效时记一个数,保证完成4个数据的累加;
2、而valid_b的判断就需要:置1:num==3(4个周期),且ready_a和valid_a都为1,即计数周期达到且上游输入有效;置0:下游valid_b 和ready_b都为1,即完成一个结果的输出后置0,与上游无关;若ready_b=0还会使ready_a置0,使得停止输入,等待完成输出。
3、data_out的判断和num类似。
DONE!!