题解 | #数据累加输出#
数据累加输出
https://www.nowcoder.com/practice/956fa4fa03e4441d85262dc1ec46a3bd
`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 , output reg [1:0] cnt ); //===================================================== /*这道题有两个注意点: 1)对于握手信号这一类的题目,在编写内部握手信号产生逻辑、数据产生逻辑时,一定要注意使用一对握手信号的作为核心判断依据。 比如该题中,使用 (valid_a & ready_a) 以及 (valid_b & ready_b) 作为两个核心判断条件,来产生其他的信号。 2)在该题中,判断数据的更新时候,要注意:将判断数据是否开始接收下一轮输入的条件放在第一个if分支中,然后再判断数据的累加情况。 这是因为,在输出开始接收新的输入时,可能会满足 (valid_a & ready_a)和(valid_b & ready_b)同时拉高; 但是数据累加情况是只有(valid_a & ready_a)拉高时才能进行的。若把累加情况的分支放在第一个,在本该接收新输入时,就会出现,Verilog找到第一个符合的条件,就跳出分支, 结果执行的是累加而不是接收输入。 */ //===================================================== wire rec_st; wire tra_st; assign rec_st = (valid_a & ready_a); assign tra_st = (valid_b & ready_b); // 四个数据,0-3,计数到3之后,会覆盖原数据从0重新开始计数, // 所以这里不用写其归零逻辑 // reg [1:0] cnt; always @(posedge clk or negedge rst_n) begin if(~rst_n) begin cnt <= 2'b00; end else begin // if(rec_st) // cnt <= (cnt==2'b11)? 2'b00 : cnt+1'b1; // else // cnt <= cnt; cnt <= rec_st? cnt+1'b1 : cnt; end end // assign ready_a = (~valid_b | tra_st); // valid_b always @(posedge clk or negedge rst_n) begin if(~rst_n) begin valid_b <= 1'b0; end else begin if(cnt==2'b11 && rec_st) valid_b <= 1'b1; else if(tra_st) valid_b <= 1'b0; else valid_b <= valid_b; end end // data_out always @(posedge clk or negedge rst_n) begin if(~rst_n) begin data_out <= 10'd0; end else begin // if(rec_st) // data_out <= data_out+data_in; // else if(tra_st && cnt==2'b00) // // 这里判断条件加上 cnt=2'b00,是考虑到ready_b比valid_b提前拉高的情况 // data_out <= data_in; // else // data_out <= data_out; if(tra_st && cnt==2'b00) data_out <= data_in; else if(rec_st) data_out <= data_out+data_in; else data_out <= data_out; end end endmodule
testbench:
`timescale 1ns/1ns
module tb;
reg 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;
wire [1:0] cnt;
always#5 clk = ~clk;
initial begin
clk = 1'b1;
rst_n = 1'b0;
data_in = 'b0;
valid_a = 1'b0;
ready_b = 1'b0;
#10
rst_n = 1'b1;
#30;
valid_a = 1'b1;
data_in = 'd1;
#10;
data_in = 'd2;
#10;
data_in = 'd3;
#10;
data_in = 'd4;
#10;
data_in = 'd5;
#20;
ready_b = 1'b1;
#10;
data_in = 'd2;
#10;
data_in = 'd7;
#10;
data_in = 'd8;
#10;
valid_a = 1'b0;
#20;
$finish();
end
valid_ready u_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 ),
.cnt (cnt)
);
endmodule

查看4道真题和解析