题目
实现串行输入数据累加输出,输入端输入8bit数据,每当模块接收到4个输入数据后,输出端输出4个接收到数据的累加结果。输入端和输出端与上下游的交互采用valid-ready双向握手机制。要求上下游均能满速传输时,数据传输无气泡,不能由于本模块的设计原因产生额外的性能损失。
电路的接口如下图所示。valid_a用来指示数据输入data_in的有效性,valid_b用来指示数据输出data_out的有效性;ready_a用来指示本模块是否准备好接收上游数据,ready_b表示下游是否准备好接收本模块的输出数据;clk是时钟信号;rst_n是异步复位信号。
模块的时序图如下:
信号 | 类型 | 输入/输出 | 位宽 | 描述 |
---|---|---|---|---|
clk | wire | Intput | 1 | 系统时钟信号 |
rst_n | wire | Intput | 1 | 异步复位信号,低电平有效 |
data_in | wire | Intput | 8 | 输入8bit数据 |
valid_a | wire | Intput | 1 | 输入数据有效 |
ready_b | wire | Intput | 1 | 下游是否准备好接收本模块的输出数据 |
data_out | wire | Output | 10 | 输出10比特累加结果 |
valid_b | reg | Output | 1 | 指示输出累加结果有效 |
ready_a | reg | Output | 1 | 指示本模块是否准备好接收上游数据 |
答案
`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
);
assign ready_a = (~valid_b) | ready_b;
//当ready_a为低电平时,表示告诉上游模块,停止数据数据输入,
//那么什么情况下需要告诉上游模块,停止数据输入到当前模块中?
//当当前模块的输出有效时,且下游的模块还未准备好接收本模块的数据时,即valid_b=1,ready_b=0时,
//需要告诉上游模块,停止数据输入,即将ready_a拉低,
//所以当valid_b=1,ready_b=0时,ready_a=0
//即~ready_a = valid_b & (!ready_b);
//简化后得到ready_a = ~(valid_b & (!ready_b))= !valid_b || ready_b;
//计数器
reg [1:0] cnt;
always @(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 2'd0;
else if(valid_a && ready_a)
if(cnt == 2'd3)
cnt <= 'd0;
else
cnt <= cnt + 1'd1;
else
cnt <= cnt;
//当前模块输出数据有效信号
always @(posedge clk or negedge rst_n)
if(!rst_n)
valid_b <= 1'b0;
else if(valid_a && ready_a && cnt==2'd3)
valid_b <= 1'b1;
else if(ready_b && valid_b)
valid_b <= 1'b0;
else
valid_b <= valid_b;
//输出数据
always @(posedge clk or negedge rst_n)
if(!rst_n)
data_out <= 'd0;
else if(valid_a && ready_a && ready_b && (cnt==2'd0))
data_out <= data_in;
else if(valid_a && ready_a)
data_out <= data_out + data_in;
else
data_out <= data_out;
endmodule