简析

输入:data_in[7:0] , valid_a, ready_b
输出:data_out[9:0], ready_a, valid_b

  • 数据端口:输入数据data_in,输出数据data_out
  • 上游握手信号:上游输入的数据是否有效valid_a,向上游发送本模块是否准备好接受ready_a
  • 下游握手信号:本模块输出的数据是否有效valid_b,下游是否准备好接受ready_b

首先设置一个计数器cnt用来指示有效数据的数量。cnt应只在输入有效且模块当前可以接收数据的状态工作。

reg [1:0] cnt;
always@(posedge clk or negedge rst_n) begin
    if(~rst_n)
    	cnt <= 0;
    else
        cnt <= valid_a&&ready_a? cnt+1: cnt;
end

当输入的有效数据达到4个时,输出数据有效,valid_b==1,模块暂停数据输入和更新;当下游将数据取走后,也就是ready_b==1时,valid==0,模块继续工作。

always@(posedge clk or negedge rst_n) begin
    if(~rst_n)
     	 valid_b <= 0;
    else if(~valid_b)
    	 valid_b <= cnt==3;
    else
     	 valid_b <= ready_b==0;
end

当输出数据有效并且尚未被下游读取时,模块尚未准备好接受新数据,此时ready_a==0。同时,通过多次仿真发现ready_a可以在非时钟边沿变化,所以是组合逻辑。

assign ready_a = ~(valid_b&&~ready_b);

最后,输出的数据data_out,当输入数据无效或者模块还未准备好接收数据时,data_out保持;当计数器清零时,输入新的数据;当正常工作时,data_out与输入数据累加。

always@(posedge clk or negedge rst_n) begin
    if(~rst_n)
      	data_out <= 0;
    else if(~valid_a||~ready_a)
      	data_out <= data_out;
    else if(cnt==0)
      	data_out <= data_in;
    else
      	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] cnt;
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            cnt <= 0;
        else
            cnt <= valid_a&&ready_a? cnt+1: cnt;
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            data_out <= 0;
        else if(~valid_a||~ready_a)
            data_out <= data_out;
        else if(cnt==0)
            data_out <= data_in;
        else
            data_out <= data_out+data_in;
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(~rst_n)
            valid_b <= 0;
        else if(~valid_b)
            valid_b <= cnt==3;
        else 
            valid_b <= ready_b==0;
    end
    
    assign ready_a = ~(valid_b&&~ready_b);
endmodule