• verilog 流水线控制


    Verilog 流水线控制

    1、关键问题、实现方式及其对比

    1、控流水输入:o_dout_rdy 为低时,没有新数据进入,流水线中剩余的数据继续运算完成
    2、控流水线每一级:用 o_dout_rdy 控制每一级,o_dout_rdy 为低时,每一级的end、data、flag 保持,直到 o_dout_rdy 为高时,再继续流水

    2、实现方式

    2.1、控流水线输入:根据每一拍的 din_en_d* 打拍,没有最终的 else block

    din_en = i_din_vld & o_dout_rdy;
    
    reg 				din_en_d0, din_en_d1, din_en_d2, din_en_d3;
    reg [4-1:0] 	din_d0, din_d1, din_d2, din_d3;
    reg 				din_flag_d0, din_flag_d1, din_flag_d2, din_flag_d3;
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d0 <= 'd0;
    		din_d0 <= 'd0;
    		din_flag_d0 <= 'd0;
    	end
    	else if(din_en) begin
    	    din_en_d0 <= din_en;
    		din_d0 <= din;
    		din_flag_d0 <= din_flag;
    	end
    end
    
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d1 <= 'd0;
    		din_d1 <= 'd0;
    		din_flag_d1 <= 'd0;
    	end
    	else if(din_en_d0) begin
    		din_en_d1 <= din_en_d0;
    		din_d1 <= din_d0;
    		din_flag_d1 <= din_flag_d0;
    	end	
    end
    
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d2<= 'd0;
    		din_d2 <= 'd0;
    		din_flag_d2 <= 'd0;
    	end
    	else if(din_en_d1) begin
    		din_en_d2<= din_en_d1;
    		din_d2 <= din_d1;
    		din_flag_d2 <= din_flag_d1;
    	end	
    end
    
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d3 <= 'd0;
    		din_d3 <= 'd0;
    		din_flag_d3<= 'd0;
    	end
    	else if(din_en_d2) begin
    		din_en_d3 <= din_en_d2;
    		din_d3 <= din_d2;
    		din_flag_d3 <= din_flag_d2;
    	end	
    end
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    控流水线输入+dout_en_d*+no_else
    存在问题:
    1、若下一级没有握手信号,与 din_en_d3 握手得到有效 enable 信号,即输出 din_en_d3 为高时,数据就有效,就会导致输出数据重复且被标记为有效数据的情况
    2、对于标志位 din_flag_d* ,由于没有复位,则可能出现最后输出的 din_flag_d3 一直为高的问题,同上面的错误数据一起输出多个错误的标志位

    2.2、控流水线输入:根据每一拍的 din_en_d* 打拍,有最终的 else block

    din_en = i_din_vld & o_dout_rdy;
    
    reg 				din_en_d0, din_en_d1, din_en_d2, din_en_d3;
    reg [4-1:0] 	din_d0, din_d1, din_d2, din_d3;
    reg 				din_flag_d0, din_flag_d1, din_flag_d2, din_flag_d3;
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d0 <= 'd0;
    		din_d0 <= 'd0;
    		din_flag_d0 <= 'd0;
    	end
    	else if(din_en) begin
    	    din_en_d0 <= din_en;
    		din_d0 <= din;
    		din_flag_d0 <= din_flag;
    	end
    	else begin
    		din_en_d0 <= 'd0;
    		din_d0 <= 'd0;
    		din_flag_d0 <= 'd0;
    	end
    end
    
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d1 <= 'd0;
    		din_d1 <= 'd0;
    		din_flag_d1 <= 'd0;
    	end
    	else if(din_en_d0) begin
    		din_en_d1 <= din_en_d0;
    		din_d1 <= din_d0;
    		din_flag_d1 <= din_flag_d0;
    	end
    	else begin
    		din_en_d1 <= 'd0;
    		din_d1 <= 'd0;
    		din_flag_d1 <= 'd0;
    	end	
    end
    
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d2<= 'd0;
    		din_d2 <= 'd0;
    		din_flag_d2 <= 'd0;
    	end
    	else if(din_en_d1) begin
    		din_en_d2<= din_en_d1;
    		din_d2 <= din_d1;
    		din_flag_d2 <= din_flag_d1;
    	end	
    	else begin
    		din_en_d2<= 'd0;
    		din_d2 <= 'd0;
    		din_flag_d2 <= 'd0;
    	end
    end
    
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d3 <= 'd0;
    		din_d3 <= 'd0;
    		din_flag_d3<= 'd0;
    	end
    	else if(din_en_d2) begin
    		din_en_d3 <= din_en_d2;
    		din_d3 <= din_d2;
    		din_flag_d3 <= din_flag_d2;
    	end
    	else begin
    		din_en_d3 <= 'd0;
    		din_d3 <= 'd0;
    		din_flag_d3<= 'd0;
    	end	
    end
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    控流水线输入+dout_en_d*+else
    可以看到,数据可以不用复位,只复位din_en_d* 和 din_flag_d* 有正确的标志位即可,即

    ...
    else begin
    		din_en_d* <= 'd0;
    		din_flag_d* <= 'd0;
    end
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.3、控流水线每一级:根据每一拍的 din_en_d* 和 o_dout_rdy 打拍,没有最终的 else block

    din_en = i_din_vld & o_dout_rdy;
    
    reg 				din_en_d0, din_en_d1, din_en_d2, din_en_d3;
    reg [4-1:0] 	din_d0, din_d1, din_d2, din_d3;
    reg 				din_flag_d0, din_flag_d1, din_flag_d2, din_flag_d3;
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d0 <= 'd0;
    		din_d0 <= 'd0;
    		din_flag_d0 <= 'd0;
    	end
    	else if(din_en) begin
    	    din_en_d0 <= din_en;
    		din_d0 <= din;
    		din_flag_d0 <= din_flag;
    	end
    end
    
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d1 <= 'd0;
    		din_d1 <= 'd0;
    		din_flag_d1 <= 'd0;
    	end
    	else if(din_en_d0 & o_dout_rdy) begin
    		din_en_d1 <= din_en_d0;
    		din_d1 <= din_d0;
    		din_flag_d1 <= din_flag_d0;
    	end	
    end
    
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d2<= 'd0;
    		din_d2 <= 'd0;
    		din_flag_d2 <= 'd0;
    	end
    	else if(din_en_d1 & o_dout_rdy) begin
    		din_en_d2<= din_en_d1;
    		din_d2 <= din_d1;
    		din_flag_d2 <= din_flag_d1;
    	end	
    end
    
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d3 <= 'd0;
    		din_d3 <= 'd0;
    		din_flag_d3<= 'd0;
    	end
    	else if(din_en_d2 & o_dout_rdy) begin
    		din_en_d3 <= din_en_d2;
    		din_d3 <= din_d2;
    		din_flag_d3 <= din_flag_d2;
    	end	
    end
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    控流水线输入+dout_en_d* & rdy+no_else

    可以看到,依然存在2.1 的两个问题:
    1、若下一级没有握手信号,与 din_en_d3 握手得到有效 enable 信号,即输出 din_en_d3 为高时,数据就有效,就会导致输出数据重复且被标记为有效数据的情况
    2、对于标志位 din_flag_d* ,由于没有复位,则可能出现最后输出的 din_flag_d3 一直为高的问题,同上面的错误数据一起输出多个错误的标志位

    优点:
    1、实现了目标功能:用 o_dout_rdy 控制流水线的每一级
    2、在有效数据的数量(5个)范围内,din_flag_d3 & o_dout_rdy 就是输出数据有效的enable 信号

    2.4、控流水线每一级:根据每一拍的 din_en_d* & o_dout_rdy 打拍,有最终的 else block

    din_en = i_din_vld & o_dout_rdy;
    
    reg 				din_en_d0, din_en_d1, din_en_d2, din_en_d3;
    reg [4-1:0] 	din_d0, din_d1, din_d2, din_d3;
    reg 				din_flag_d0, din_flag_d1, din_flag_d2, din_flag_d3;
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d0 <= 'd0;
    		din_d0 <= 'd0;
    		din_flag_d0 <= 'd0;
    	end
    	else if(din_en) begin
    	    din_en_d0 <= din_en;
    		din_d0 <= din;
    		din_flag_d0 <= din_flag;
    	end
    	else begin
    		din_en_d0 <= 'd0;
    		din_d0 <= 'd0;
    		din_flag_d0 <= 'd0;
    	end
    end
    
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d1 <= 'd0;
    		din_d1 <= 'd0;
    		din_flag_d1 <= 'd0;
    	end
    	else if(din_en_d0) begin
    		din_en_d1 <= din_en_d0;
    		din_d1 <= din_d0;
    		din_flag_d1 <= din_flag_d0;
    	end
    	else begin
    		din_en_d1 <= 'd0;
    		din_d1 <= 'd0;
    		din_flag_d1 <= 'd0;
    	end	
    end
    
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d2<= 'd0;
    		din_d2 <= 'd0;
    		din_flag_d2 <= 'd0;
    	end
    	else if(din_en_d1) begin
    		din_en_d2<= din_en_d1;
    		din_d2 <= din_d1;
    		din_flag_d2 <= din_flag_d1;
    	end	
    	else begin
    		din_en_d2<= 'd0;
    		din_d2 <= 'd0;
    		din_flag_d2 <= 'd0;
    	end
    end
    
    always@(posedge i_clk or negedge i_rstn) begin
    	if(!i_rstn) begin
    		din_en_d3 <= 'd0;
    		din_d3 <= 'd0;
    		din_flag_d3<= 'd0;
    	end
    	else if(din_en_d2) begin
    		din_en_d3 <= din_en_d2;
    		din_d3 <= din_d2;
    		din_flag_d3 <= din_flag_d2;
    	end
    	else begin
    		din_en_d3 <= 'd0;
    		din_d3 <= 'd0;
    		din_flag_d3<= 'd0;
    	end	
    end
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    控流水线输入+dout_en_d* & rdy+else
    可以看到,功能和数据基本完全错误
    原因:else 复位信号后,下一级无法再获取有效信号

  • 相关阅读:
    python创建虚拟环境(非anaconda)并打包环境在另一台机器离线移植安装
    高等教育心理学:问题解决与创造性
    一个文件的开源项目,开启你的开源之旅
    c#仿热血江湖
    mySQL 安装
    苹果发布会:iPhone 15全系列手机正式发布
    C++类对象到底占多大存储空间呢
    Golang必知必会Go Mod命令
    SSM之spring注解式缓存redis
    【java毕业设计】基于java+tomcat+jsp的威客网站设计与实现(毕业论文+程序源码)——威客网站
  • 原文地址:https://blog.csdn.net/weixin_44544687/article/details/127917679