verilog 流水线控制

文章目录

  • Verilog 流水线控制
    • 1、关键问题、实现方式及其对比
    • 2、实现方式
      • 2.1、控流水线输入:根据每一拍的 din_en_d* 打拍,没有最终的 else block
      • 2.2、控流水线输入:根据每一拍的 din_en_d* 打拍,有最终的 else block
      • 2.3、控流水线每一级:根据每一拍的 din_en_d* 和 o_dout_rdy 打拍,没有最终的 else block
      • 2.4、控流水线每一级:根据每一拍的 din_en_d* & o_dout_rdy 打拍,有最终的 else block

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

verilog 流水线控制_第1张图片
存在问题:
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

verilog 流水线控制_第2张图片
可以看到,数据可以不用复位,只复位din_en_d* 和 din_flag_d* 有正确的标志位即可,即

...
else begin
		din_en_d* <= 'd0;
		din_flag_d* <= 'd0;
end
...

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

verilog 流水线控制_第3张图片

可以看到,依然存在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

verilog 流水线控制_第4张图片
可以看到,功能和数据基本完全错误
原因:else 复位信号后,下一级无法再获取有效信号

你可能感兴趣的:(Verilog电路设计,fpga开发,芯片)