前导零计数电路的设计

LZC(leading zeros count)在浮点加法器设计中应用广泛。本文借助优先级编码器的原理设计了一个48bits的LZC电路。

优先级编码器的原理参考了:优先编码器 Priority Encoder-CSDN博客

直接上代码:

module LZC_cascade #(
	parameter N = 8
) (
	input  [N-1: 0]Q1  ,
	input  [N-1: 0]Q0  ,
	input          vld1,
	input          vld0,
	output [N  : 0]Q   ,
	output         vld  
	);

assign Q[N]     = vld1 ;
assign Q[N-1:0] = vld1 ? Q1[N-1:0]: Q0[N-1:0];
assign vld      = vld1 | vld0 ;
endmodule

module LZC_48bits (
	input  [ 47: 0]D            ,
	output         vld          ,
	output [  5: 0]leading_zeros   
	);

wire     [4*6 -1:0]PEnc8_x6 ;
wire     [5*3 -1:0]PEnc16_x3;
wire     [6*2 -1:0]PEnc32_0,PEnc32_1 ;
wire     [6     :0]PEnc48_0          ;
genvar   i ;

function [3:0]PEnc_8bits; //Priority Encoder: {vld,Q[2:0]}
input    [7:0]D;
reg           vld1;
begin
	vld1          = |D[7:4];
	PEnc_8bits[0] = vld1 ? D[7] | (~D[6] & D[5]) : D[3] | (~D[2] & D[1]) ; 
	PEnc_8bits[1] = vld1 ? D[7] | D[6]           : D[3] | D[2]           ;
	PEnc_8bits[2] = vld1                         ;
	PEnc_8bits[3] = vld1 | |D[3:0]               ;
end
endfunction

generate
for(i=0;i<6;i=i+1) begin: GEN0
	assign PEnc8_x6[i*4+3:i*4] = PEnc_8bits(D[i*8+7:i*8]);
end
endgenerate

generate
for(i=0;i<3;i=i+1) begin: GEN1
LZC_cascade #(
	.N(3)
)u_lzc16 (
	.Q1  ( PEnc8_x6[i*8+6:i*8+4] ),
	.Q0  ( PEnc8_x6[i*8+2:i*8+0] ),
	.vld1( PEnc8_x6[i*8+7]       ),
	.vld0( PEnc8_x6[i*8+3]       ),
	.Q   ( PEnc16_x3[ i*5+3:i*5+0] ),
	.vld ( PEnc16_x3[ i*5+4]       ) 
	);
end
endgenerate

LZC_cascade #(
	.N(4)
)u_lzc32 (
	.Q1  ( PEnc16_x3[8:    5] ),
	.Q0  ( PEnc16_x3[3:    0] ),
	.vld1( PEnc16_x3[9]       ),
	.vld0( PEnc16_x3[4]       ),
	.Q   ( PEnc32_0[ 4:    0] ),
	.vld ( PEnc32_0[ 5      ] ) 
	);

assign  PEnc32_1 = {PEnc16_x3[14],1'b0,PEnc16_x3[13:10]};

LZC_cascade #(
	.N(5)
)u_lzc48 (
	.Q1  ( PEnc32_1[4:    0] ),
	.Q0  ( PEnc32_0[4:    0] ),
	.vld1( PEnc32_1[5]       ),
	.vld0( PEnc32_0[5]       ),
	.Q   ( PEnc48_0[5:    0] ),
	.vld ( PEnc48_0[6      ] ) 
	);

assign  vld           =   PEnc48_0[6]  ;
assign  leading_zeros = {~PEnc32_1[5]&~PEnc32_0[4],PEnc48_0[4],~PEnc48_0[3:0]};

endmodule



Testbench文件如下:

module TB_LDC;

reg clk,rst_n;
reg [15:0]cnt;
reg [47:0]D  ;
wire      en  ;
reg       en_g;
integer   fl  ;

wire         vld          ;
wire [  5: 0]leading_zeros;  

always #12.5 clk = ~clk;


initial begin
	clk = 0;
	rst_n = 0;
	#80 rst_n = 1;
	fl = $fopen("bf16_result.txt","w");
	$fdisplay(fl,"      D         vld leading_zeros");
	wait(cnt == 100);
	$fclose(fl);
	#5 $stop;
	end

always @(negedge rst_n or posedge clk)
if(!rst_n) begin
	cnt  <= 'd0;
	en_g <= 'd0;
end else begin
	cnt  <= cnt + 1'b1;
	en_g <= en  ;
end


assign     en = (cnt > 'd35) && (cnt < 'd48);

always @(posedge clk or negedge rst_n)
if(!rst_n)
	D        <=  48'd0  ;
else if(en) begin
	D        <=  48'h93ab_5af1_10a5 >> ($random%48) ;
end

always @(posedge clk)
if(en_g) begin
	$fdisplay(fl,"%012h   %d    %d", D, vld, leading_zeros);
end


LZC_48bits
DUT(
	.D            (  D                ),
	.vld          (  vld              ),
	.leading_zeros(  leading_zeros    )   
	);

endmodule

测试波形:

打印结果:

      D         vld leading_zeros
0000093ab5af   1    20
000000000000   0    47
000000000000   0    47
000000000000   0    47
000000000004   1    45
000000049d5a   1    29
000000000000   0    47
000000000000   0    47
0000000049d5   1    33
00049d5ad788   1    13
024ead6bc442   1     6
000000049d5a   1    29

可见,本设计正确实现了48位前导零计数功能。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值