一、要求
设计一个组合逻辑电路,检测输入32位0/1向量中从高到低第一个1出现的位置,如果向量为全0则输出32。例如:
输入00011000 10000000 00000000 00000000,输出3;
输入00000000 11111111 00000000 00000000,输出8;
输入00000000 00000000 00000000 00001010,输出28.
模块输入输出功能定义:
名称 | 方向 | 位宽 | 描述 |
data_in | I | 32 | 输入0/1向量 |
pos_out | O | 6 | 前导1出现位置,取值范围0 ~ 32 |
设计要求:
Verilog实现代码可综合,逻辑延迟越小越好,给出仿真结果。
二、实现
1.casex/casez
代码实现如下:
module seq_head_detect(
input [31:0] data_in,
output pos_out
);
reg [31:0] tmp;
reg [5:0] pos_out_tmp;
reg [5:0] pos_out;
always @(*) begin
tmp = data_in;
casex(tmp)
32'b1xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd0;
32'b01xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd1;
32'b001x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd2;
32'b0001_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd3; //第4位为1
32'b0000_1xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd4;
32'b0000_01xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd5;
32'b0000_001x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd6;
32'b0000_0001_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd7; //8
32'b0000_0000_1xxx_xxxx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd8;
32'b0000_0000_01xx_xxxx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd9;
32'b0000_0000_001x_xxxx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd10;
32'b0000_0000_0001_xxxx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd11; //12
32'b0000_0000_0000_1xxx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd12;
32'b0000_0000_0000_01xx_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd13;
32'b0000_0000_0000_001x_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd14;
32'b0000_0000_0000_0001_xxxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd15; //16
32'b0000_0000_0000_0000_1xxx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd16;
32'b0000_0000_0000_0000_01xx_xxxx_xxxx_xxxx : pos_out_tmp = 6'd17;
32'b0000_0000_0000_0000_001x_xxxx_xxxx_xxxx : pos_out_tmp = 6'd18;
32'b0000_0000_0000_0000_0001_xxxx_xxxx_xxxx : pos_out_tmp = 6'd19; //20
32'b0000_0000_0000_0000_0000_1xxx_xxxx_xxxx : pos_out_tmp = 6'd20;
32'b0000_0000_0000_0000_0000_01xx_xxxx_xxxx : pos_out_tmp = 6'd21;
32'b0000_0000_0000_0000_0000_001x_xxxx_xxxx : pos_out_tmp = 6'd22;
32'b0000_0000_0000_0000_0000_0001_xxxx_xxxx : pos_out_tmp = 6'd23; //24
32'b0000_0000_0000_0000_0000_0000_1xxx_xxxx : pos_out_tmp = 6'd24;
32'b0000_0000_0000_0000_0000_0000_01xx_xxxx : pos_out_tmp = 6'd25;
32'b0000_0000_0000_0000_0000_0000_001x_xxxx : pos_out_tmp = 6'd26;
32'b0000_0000_0000_0000_0000_0000_0001_xxxx : pos_out_tmp = 6'd27; //28
32'b0000_0000_0000_0000_0000_0000_0000_1xxx : pos_out_tmp = 6'd28;
32'b0000_0000_0000_0000_0000_0000_0000_01xx : pos_out_tmp = 6'd29;
32'b0000_0000_0000_0000_0000_0000_0000_001x : pos_out_tmp = 6'd30;
32'b0000_0000_0000_0000_0000_0000_0000_0001 : pos_out_tmp = 6'd31; //32
default : pos_out_tmp = 6'd32; //全0
endcase
pos_out = pos_out_tmp;
end
endmodule
2.逐项比较if...else...
module seq_head_detect(
input [31:0] data_in,
output pos_out
);
reg [31:0] tmp;
reg [5:0] pos_out_tmp;
reg [5:0] pos_out;
always @(*) begin
tmp = data_in;
if(tmp[31]) pos_out_tmp = 6'd0;
else if(tmp[30]) pos_out_tmp = 6'd1;
else if(tmp[29]) pos_out_tmp = 6'd2;
else if(tmp[28]) pos_out_tmp = 6'd3;
else if(tmp[27]) pos_out_tmp = 6'd4;
else if(tmp[26]) pos_out_tmp = 6'd5;
else if(tmp[25]) pos_out_tmp = 6'd6;
else if(tmp[24]) pos_out_tmp = 6'd7;
else if(tmp[23]) pos_out_tmp = 6'd8;
else if(tmp[22]) pos_out_tmp = 6'd9;
else if(tmp[21]) pos_out_tmp = 6'd10;
else if(tmp[20]) pos_out_tmp = 6'd11;
else if(tmp[19]) pos_out_tmp = 6'd12;
else if(tmp[18]) pos_out_tmp = 6'd13;
else if(tmp[17]) pos_out_tmp = 6'd14;
else if(tmp[16]) pos_out_tmp = 6'd15;
else if(tmp[15]) pos_out_tmp = 6'd16;
else if(tmp[14]) pos_out_tmp = 6'd17;
else if(tmp[13]) pos_out_tmp = 6'd18;
else if(tmp[12]) pos_out_tmp = 6'd19;
else if(tmp[11]) pos_out_tmp = 6'd20;
else if(tmp[10]) pos_out_tmp = 6'd21;
else if(tmp[9]) pos_out_tmp = 6'd22;
else if(tmp[8]) pos_out_tmp = 6'd23;
else if(tmp[7]) pos_out_tmp = 6'd24;
else if(tmp[6]) pos_out_tmp = 6'd25;
else if(tmp[5]) pos_out_tmp = 6'd26;
else if(tmp[4]) pos_out_tmp = 6'd27;
else if(tmp[3]) pos_out_tmp = 6'd28;
else if(tmp[2]) pos_out_tmp = 6'd29;
else if(tmp[1]) pos_out_tmp = 6'd30;
else if(tmp[0]) pos_out_tmp = 6'd31;
else pos_out_tmp = 6'd32;
pos_out = pos_out_tmp;
end
endmodule
3.二分法
module seq_head_detect(
input [31:0] data_in,
output [ 5:0] pos_out
);
//mark:assign不能给reg赋值,只能赋给wire
wire [4:0] data_chk;
wire [15:0] data_1;
wire [7:0] data_2;
wire [3:0] data_3;
wire [1:0] data_4;
assign data_chk[4] = |data_in[31:16];//高16位相或,依此类推
assign data_chk[3] = |data_1[15:8];
assign data_chk[2] = |data_2[7:4];
assign data_chk[1] = |data_3[3:2];
assign data_chk[0] = |data_4[1];
assign data_1 = (data_chk[4]) ? data_in[31:16] : data_in[15:0]; //若data_in高16位有1,则data1取其高16位,否则取低16位
assign data_2 = (data_chk[3]) ? data_1[15:8] : data_1[7:0]; //若data_1高8位有1,则data2取其高8位,否则取低8位
assign data_3 = (data_chk[2]) ? data_2[7:4] : data_2[3:0]; //若data_2高4位有1,则data3取其高4位,否则取低4位
assign data_4 = (data_chk[1]) ? data_3[3:2] : data_3[1:0]; //若data_3高2位有1,则data4取其高2位,否则取低2位
assign pos_out = (|data_in) ? {1'b0, ~data_chk} : 6'd32; //若data_in为全0,posout = 6'd32
/*data_in中有1时,用低5位表示足够,则最高位为0*/
/*假定data_in首位为1,则data_chk = 11111,应有pos_out = 00000,类推可知data_chk取反*/
endmodule
三、仿真
testbench:
`timescale 1ns / 1ps
module tb_seq_head_detect();
reg [31:0] data_in;
wire [5:0] pos_out;
initial begin
data_in = 32'b0000_0000_0000_0000_0000_0000_0000_0000;
#100
data_in = 32'b0000_0001_0000_0000_0000_0000_0000_1101;//第8位,pos_out = 7
#100
data_in = 32'b0000_0000_0000_0000_0010_0000_0000_1101;//第19位,pos_out = 18
end
seq_head_detect u_seq_head_detect(
.data_in (data_in),
.pos_out (pos_out)
);
endmodule
仿真结果: