牛客刷题<31>数据累加输出

题目:数据累加输出_牛客题霸_牛客网

思路:需要注意的是 只有当valid_a 与 ready_a同时为1才能累加数据,ready_b为高时清空计数器,在下一个时钟上升沿valid_b拉低。ready_a与ready_b之间是组合逻辑的关系,累加4个之后,valid_b拉高 然后若是ready_b为低则立刻将ready_a拉低,表示没准备好接收上游数据,数据被锁存住。核心:只有valid_a ready_a同时为高才能累加数据,只有valid_b ready_b同时为高 才能将累加结果输出,并在下一时钟上升沿重新开始累加。

题意梳理

两组握手信号,分别是与上游的valid_a和ready_a、与下游的valid_b和ready_b; 需要说明的是每组的valid和ready之间没有先后关系,谁先谁后都行;

输出信号有三个:

①ready_a:为高表示我现在没啥事,告诉上游我准备好了,你可以发数据了;

②valid_b:为高表示给下游说我发数据了;

③data_out:给下游发的数据,配合valid_b,只有valid_b为高时,发送的才是有效数据。

那么分别来处理:

①ready_a: 如果下游ready_b拉高,表示下游可以接收模块输出数据,那么此时ready_a应拉高;同时,如果valid_b为低,表示4个数据还没收完,所以也拉高继续接收。

assign ready_a = ready_b | ~valid_b;

②valid_b: 当和上游正常通讯时(即valid_a和ready_a均为高),数据正常接收,但注意计数了4个就得加起来输出一次,所以data_cnt == 2'd3时拉高valid_b;而等待下游接收,即当ready_a也拉高表示接收完成,则拉低valid_b,保证只有在四个数之和的时候才拉高。

    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            valid_b <= 1'b0;
        else if(valid_a && ready_a && data_cnt == 2'd3)
            valid_b <= 1'd1;
        else if(valid_b && ready_b)
            valid_b <= 1'd0;
    end

③data_out: 同理,当和上游正常通讯时(即valid_a和ready_a均为高),数据正常接收,数据累加,当计数器data_cnt == 2'd0表示需要从头再加,清零,但注意需要等到ready_b拉高,表示下游接收完成才能清空重新累加

    always@(posedge clk or negedge rst_n) begin
        if(!rst_n)
            data_out <= 10'b0;
        else if(valid_a && ready_a && data_cnt == 2'd0 && ready_b)
            data_out <= data_in;
        else if(valid_a && ready_a)
            data_out <= data_out + data_in;
    end 

代码

`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] data_cnt;
    assign ready_a = !valid_b | ready_b;
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            data_cnt <= 2'd0;
        else if(valid_a && ready_a)
            data_cnt <= (data_cnt == 2'd3) ? 2'd0 : (data_cnt + 1'd1);
    end
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            valid_b <= 1'd0;
        else if(data_cnt == 2'd3 && valid_a && ready_a)
            valid_b <= 1'd1;
        else  if(valid_b && ready_b)
            valid_b <= 1'd0;
    end
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)
            data_out <= 1'd0;
        else if(ready_b && valid_a && ready_a && (data_cnt == 2'd0))
            data_out <= data_in;
        else if(valid_a && ready_a)
            data_out <= data_out + data_in;
    end
endmodule

 解法二:分段写

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;
always @ (posedge clk or negedge rst_n) 
begin
    if( ~rst_n ) begin
        count <= 2'b0;
    end 
    else begin
        if(valid_a & ready_a) begin
            if( count == 2'd3)
                count <= 2'd0;
            else 
                count <= count + 2'd1;
        end 
    end 
end 

always @ (posedge clk or negedge rst_n) 
begin
    if( ~rst_n ) begin
        data_out <= 10'b0;
    end 
    else begin
        if(valid_a && ready_a) begin
            if(count == 2'd0) begin
                data_out <= data_in;
            end
            else begin
                data_out <= data_out + data_in;
            end 
        end 
    end 
end 

always @ (posedge clk or negedge rst_n) 
begin
    if( ~rst_n ) begin
        valid_b <= 1'b0;
    end 
    else begin
        if(count == 2'd3 && valid_a && ready_a) begin
            valid_b <= 1'b1;
        end 
        else if(valid_b && ready_b)begin
            valid_b <= 1'b0;
        end 
        else begin
            valid_b <= valid_b;
        end 
    end 
end 

assign ready_a = ~valid_b | ready_b;
    
endmodule

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值