数据累加输出 alt

  1. 输出信号: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

alt

但是过不了; alt

说是我的的data_out 有问题; 好吗 这才看到第四个数没加进去; valid_b改为全敏感之后就有一个问题,就是等ready_b 拉高之后等一个周期才能拉低,这个周期被挤掉了; alt

好吧,我还是用计数器吧, alt

看起来貌似没问题了,但是还是没通过,并且我觉得这里有问题;就是当我把第三段改为:

    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

感谢这位朋友;