题解 | #数据累加输出#

数据累加输出

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

全部评论

相关推荐

点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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