数据累加输出
- 输出信号:ready_a:当累加到四个数立刻拉低,等待ready_b拉高的瞬间也拉高;
2.valid_b:当累加到第四个数即刻拉高,等到ready_b为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
);
reg[4:0] cnt;
reg [9:0] data_outr;
always @ (posedge clk or negedge rst_n)
if (!rst_n)
begin
cnt <= 0;
data_outr <= 0;
end
else if (valid_a)
if (cnt < 5'd3)
begin
cnt <= cnt +1;
data_outr <= data_outr + data_in;
end
else
begin
cnt <= 0;
data_outr <= 0;
end
else
begin
cnt <= 0;
data_outr <= 0;
end
always @ (posedge clk or negedge rst_n)
if (!rst_n)
data_out <= 0;
else if (valid_a&&(cnt == 5'd3))
data_out <=data_outr;
else
data_out<=data_out;
always @(posedge clk or negedge rst_n)
if (!rst_n)
begin
valid_b <= 0;
end
else if (cnt == 5'd3 )
valid_b <= 1;
else if (ready_b)
valid_b <= 0;
else
valid_b <= valid_b;
assign ready_a = !(valid_b && !ready_b);
endmodule
测试tb
`timescale 1ns / 1ps
module tb();
reg clk = 0;
always #5 clk = !clk;
reg rst_n ;
reg [7:0] data_in ;
reg valid_a ;
reg ready_b ;
wire ready_a ;
wire valid_b ;
wire [9:0] data_out ;
valid_ready valid_ready (
.clk (clk),
.rst_n (rst_n),
. data_in (data_in),
.valid_a (valid_a),
.ready_b (ready_b),
.ready_a (ready_a),
.valid_b (valid_b),
. data_out (data_out)
);
initial
begin
rst_n <= 0; valid_a <= 0; ready_b <= 0; data_in <= 0;
#10 rst_n <= 1; valid_a <= 0; ready_b <= 0; data_in <= 0;
#10 valid_a <= 1; ready_b <= 0; data_in <= 8'd1;
#10 valid_a <= 1; ready_b <= 0; data_in <= 8'd2;
#10 valid_a <= 1; ready_b <= 0; data_in <= 8'd3;
#10 valid_a <= 1; ready_b <= 0; data_in <= 8'd4;
#10 valid_a <= 1; ready_b <= 0; data_in <= 8'd5;
#10 valid_a <= 1; ready_b <= 0; data_in <= 8'd5;
#10 valid_a <= 1; ready_b <= 1; data_in <= 8'd5;
end
endmodule
但是过不了;
说是我的的data_out 有问题; 好吗 这才看到第四个数没加进去; valid_b改为全敏感之后就有一个问题,就是等ready_b 拉高之后等一个周期才能拉低,这个周期被挤掉了;
好吧,我还是用计数器吧,
看起来貌似没问题了,但是还是没通过,并且我觉得这里有问题;就是当我把第三段改为:
always @(posedge clk or negedge rst_n)
if (!rst_n)
begin
valid_b <= 0;
end
else if (cnt == 5'd4 )
valid_b <= 1;
else if (ready_b)
valid_b <= 0;
else
valid_b <= valid_b;
计数器记到4就拉高,当检测到ready_b为1之后,就在下个时钟将valid置零;我觉得极端情况可能会漏掉一个周期;
算了 学学人家的代码吧;
`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] count;
wire add_cnt;
wire end_cnt;
assign add_cnt = valid_a && ready_a;
//valid_a用来指示数据输入data_in的有效性,ready_a用来指示本模块是否准备好接收上游数据,二者同时为一,则让计数器加一
assign end_cnt = valid_a && ready_a && (count == 'd3);
////valid_a用来指示数据输入data_in的有效性,ready_a用来指示本模块是否准备好接收上游数据,且计数器为3时,将cnt置零;
//count
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
count <= 0;
end
else if(end_cnt) begin
count <= 0;
end
else if(add_cnt) begin
count <= count + 1;
end
end
// 计数器从0加到3,
//data_out
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_out <= 0;
end
else if (add_cnt && count == 0) begin
data_out <= data_in;
end
else if (add_cnt) begin
data_out <= data_out + data_in;
end
end
//当add_cnt为一并且计数器为0时,输出数据为此时的输入数据,这也是我的问题所在,时序图最后一点没看仔细。
//否则当计数器不为0时,输出数据累加,我写的时候一直局限于将valid_b 和 data_out同时输出,说到底还是时序图看不仔细;
//ready_a
assign ready_a = !valid_b | ready_b;
//很奇怪为什么大家第一时间都是用assign ,就我没想到,以后遇到棘手的信号应该多这样想想。
//valid_b
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
valid_b <= 0;
end
else if(end_cnt) begin
valid_b <= 1;
end
else if(ready_b) begin
valid_b <= 0;
end
end
//计数为3则将valid_b拉高为1,当ready_b拉高再拉低;
endmodule
感谢这位朋友;