verilog——74HC85四位数值比较器并扩展为16位数值比较器

verilog——74HC85四位数值比较器并扩展为16位数值比较器

    • 74HC85的仿真
      • 设计思路
      • 代码
        • 设计模块
        • 测试模块
      • 仿真结果
    • 扩展为16位比较器
      • 设计思路
      • 串行代码实现
        • 设计模块
        • 测试模块
      • 串行仿真
      • 并行代码
        • 设计模块
        • 测试模块
      • 仿真结果
    • 问题总结

74HC85的仿真

设计思路

根据数据比较的原理写出真值表,如下图
真值表

代码

设计模块

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
//filename:74HC85.V
module _74HC85 (
input [2:0]I,
input [3:0] A,B,
output reg [2:0] L);
/*参数说明:
I为扩展输入端,是来自高位的比较结果,扩展输入端与其他数值比较器的输出连接,以便组成位数更多的数值比较器。
AB:为需要比较的两个四位二进制数值。
L为输出结果。L2=1时,表示a大于b;L1=1时,表示a小于b,;L0=1时,表示a等于b。
*/
always@(*)
begin
    if(I==3'b100)    L=3'b100;
    else if(I==3'b010)    L=3'b010; //扩展输入端的优先级最高,最先判断。
    else
    begin
    if(A[3]>B[3])    L=3'b100;
    else if(A[3]<B[3])    L=3'b010;   //高位优先级高,先进行判断。
    else
    begin
        if(A[2]>B[2])    L=3'b100;
        else if(A[2]<B[2])    L=3'b010;
        else
        begin
        if(A[1]>B[1])    L=3'b100;
            else if(A[1]<B[1])    L=3'b010;
        else
        begin
            if(A[0]>B[0])    L=3'b100;
                else if(A[0]<B[0])    L=3'b010;
            else    L=3'b001;
        end
        end
    end
    end
end
endmodule

测试模块

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
//filename:tb_74HC85.v
`timescale 10ns/1ns
module tb_74HC85();
reg [2:0]I;
reg [3:0] A,B;
wire [2:0] L;

_74HC85 U(I,A,B,L);

initial
    $monitor($time,"\tI=%b,A=%b,B=%b,L=%b",I,A,B,L);
initial begin
    I=3'b100;A=4'b0000;B=4'b1111;   //扩展输入端A大于b为真。
    #5;
    I=3'b001;A=4'b0000;B=4'b1111;  //扩展输入端A等于b为真。
    #5;
    I=3'b010;A=4'b1111;B=4'b0000;   //扩展输入端A小于b为真。
    #5;
    I=3'b001;A=4'b1111;B=4'b0000;  //扩展输入端A等于b为真。
    #5;
    I=3'b001;A=4'b0100;B=4'b0010;//扩展输入端A等于b为真。
    #5;
    I=3'b001;A=4'b0001;B=4'b0001;//扩展输入端A等于b为真。
    #5;
    $stop;
end
endmodule

仿真结果

在这里插入图片描述
在这里插入图片描述

扩展为16位比较器

设计思路

1)采用串联方式扩展数值比较器的位数。
高四位的比较结果应作为低四位的条件,即高四位比较器的输出端应分别于低四位比较器的扩展输入端连接。原理图如下,图中数值高位低位的存储地址与我设计的不同,按照我的设计,应该将图中的0-7顺序改成7-0;
2)采用并联方式扩展数值比较器的位数。
当位数较多且要满足一定的速度要求时,采用并联方式。并联方式采用两级比较方法。将16位按高低位次序分成四组,每组四位,各组的比较比较是并行进行的。将每组的比较数据再经四位比较器进行比较后得出结果。原理图如下,
在这里插入图片描述

串行代码实现

设计模块

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
78
79
80
81
82
//filename:74HC85.V
module _74HC85 (
input [2:0]I,
input [3:0] A,B,
output reg [2:0] L);
/*参数说明:
I为扩展输入端,是来自高位的比较结果,扩展输入端与其他数值比较器的输出连接,以便组成位数更多的数值比较器。
AB:为需要比较的两个四位二进制数值。
L为输出结果。L2=1时,表示a大于b;L1=1时,表示a小于b,;L0=1时,表示a等于b。
*/
always@(*)
begin
    if(I==3'b100)    L=3'b100;
    else if(I==3'b010)    L=3'b010; //扩展输入端的优先级最高,最先判断。
    else
    begin
    if(A[3]>B[3])    L=3'b100;
    else if(A[3]<B[3])    L=3'b010;   //高位优先级高,先进行判断。
    else
    begin
        if(A[2]>B[2])    L=3'b100;
        else if(A[2]<B[2])    L=3'b010;
        else
        begin
        if(A[1]>B[1])    L=3'b100;
            else if(A[1]<B[1])    L=3'b010;
        else
        begin
            if(A[0]>B[0])    L=3'b100;
                else if(A[0]<B[0])    L=3'b010;
            else    L=3'b001;
        end
        end
    end
    end
end
endmodule

module _16com(
input [15:0] A16,B16,
input [2:0] I,
output [2:0] F);
wire [2:0] F3,F2,F1;
wire [3:0] AC3,BC3,AC2,BC2,AC1,BC1,AC0,BC0;
/*
参数说明:
输入:
AB为需要进行比较的两个16位二进制数;
I为扩展输入端。
输出:
F为输出结果。F2=1时,表示a大于b;F1=1时,表示a小于b,;F0=1时,表示a等于b。
*/

/*将16位以四位一组,分到四个74HC85上*/
genvar k; // 定义循环变量。
for(k=15;k>=12;k=k-1)
begin
    assign AC3[k-12]=A16[k];
    assign BC3[k-12]=B16[k];
end
for(k=11;k>=8;k=k-1)
begin
    assign AC2[k-8]=A16[k];
    assign BC2[k-8]=B16[k];
end
for(k=7;k>=4;k=k-1)
begin
    assign AC1[k-4]=A16[k];
    assign BC1[k-4]=B16[k];
end
for(k=3;k>=0;k=k-1)
begin
    assign AC0[k]=A16[k];
    assign BC0[k]=B16[k];
end
//高位的比较结果作为低位的条件,高四位比较器的输出端应分别与低四位比较器的扩展输入端相连。
_74HC85 C3(I,AC3,BC3,F3);
_74HC85 C2(F3,AC2,BC2,F2);
_74HC85 C1(F2,AC1,BC1,F1);
_74HC85 C0(F1,AC0,BC0,F);

endmodule

测试模块

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
//filename:tb_74HC85.v
`timescale 10ns/1ns
module tb_16com();
reg [2:0]I;
reg [15:0] A16,B16;
wire [2:0] F;

_16com U(A16,B16,I,F);

initial
    $monitor($time,"\tI=%b,A=%b,B=%b,F=%b",I,A16,B16,F);
initial begin
    I=3'b001;A16=16'b1111_1111_1111_1111;B16=16'b1111_1111_1111_1110; //扩展输入端中A等于b为真,A大于b的情况。
    #5;
    I=3'b001;A16=16'b0111_1111_1111_1111;B16=16'b1111_1111_1111_1111;//扩展输入端中A等于b为真,A小于b的情况。
    #5;
    I=3'b001;A16=16'b1111_1111_1111_1111;B16=16'b1111_1111_1111_1111;//扩展输入端中A等于b为真,A等于B的情况。
    #5;
    I=3'b100;A16=16'b0111_1111_1111_1111;B16=16'b1111_1111_1111_1111;//扩展输入端中A大于b为真的情况。
    #5;
    I=3'b010;A16=16'b1111_1111_1111_1111;B16=16'b0111_1111_1111_1111;//扩展输入端中A小于b为真的情况。
    #5;
    $stop;
end
endmodule

串行仿真

在这里插入图片描述
在这里插入图片描述

并行代码

设计模块

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
78
79
80
81
82
83
84
85
86
87
88
//filename:74HC85.V
module _74HC85 (
input [2:0]I,
input [3:0] A,B,
output reg [2:0] L);
always@(*)
begin
    if(I==3'b100)    L=3'b100;
    else if(I==3'b010)    L=3'b010;
    else
    begin
    if(A[3]>B[3])    L=3'b100;
    else if(A[3]<B[3])    L=3'b010;
    else
    begin
        if(A[2]>B[2])    L=3'b100;
        else if(A[2]<B[2])    L=3'b010;
        else
        begin
        if(A[1]>B[1])    L=3'b100;
            else if(A[1]<B[1])    L=3'b010;
        else
        begin
            if(A[0]>B[0])    L=3'b100;
                else if(A[0]<B[0])    L=3'b010;
            else    L=3'b001;
        end
        end
    end
    end
end
endmodule

module _16com(
input [15:0] A16,B16,
input [2:0] I,
output [2:0] F);
wire [2:0] F3,F2,F1,F0;
wire [3:0] AC3,BC3,AC2,BC2,AC1,BC1,AC0,BC0,AC,BC;
/*
参数说明:
输入:
AB为需要进行比较的两个16位二进制数;
I为扩展输入端。
输出:
F为输出结果。F2=1时,表示a大于b;F1=1时,表示a小于b,;F0=1时,表示a等于b。
*/

/*将16位以四位一组,分到四个74HC85上*/
genvar k;
for(k=15;k>=12;k=k-1)
begin
    assign AC3[k-12]=A16[k];
    assign BC3[k-12]=B16[k];
end
for(k=11;k>=8;k=k-1)
begin
    assign AC2[k-8]=A16[k];
    assign BC2[k-8]=B16[k];
end
for(k=7;k>=4;k=k-1)
begin
    assign AC1[k-4]=A16[k];
    assign BC1[k-4]=B16[k];
end
for(k=3;k>=0;k=k-1)
begin
    assign AC0[k]=A16[k];
    assign BC0[k]=B16[k];
end
//将16位按高低为次序分成四组,每组四位各组的比较是并行进行的。
_74HC85 C3(3'b001,AC3,BC3,F3);
_74HC85 C2(3'b001,AC2,BC2,F2);
_74HC85 C1(3'b001,AC1,BC1,F1);
_74HC85 C0(3'b001,AC0,BC0,F0);
//将每组的比较结果在经四位比较器进行比较后得出结果。
assign AC[3]=F3[2];
assign AC[2]=F2[2];
assign AC[1]=F1[2];
assign AC[0]=F0[2];

assign BC[3]=F3[1];
assign BC[2]=F2[1];
assign BC[1]=F1[1];
assign BC[0]=F0[1];

_74HC85 C4(I,AC,BC,F);
endmodule

测试模块

同串行

仿真结果

经验证,同前。

问题总结

1.16位比较器编写过程中出现了参数不对照的问题,后来发现是实参的位置错了,导致与形参不匹配。下次一定要注意,形参和实参的匹配。
2.在实际单片机,CPU的IO口等实际应用中,数学上的高位通常分配到低位地址,所以数学上的1000,对应计算机上的数组为A= {0,0,0,1},A【0】=1,表示数值最高位上的1存放在低位地址中(A[0])。因此我本次设计的16位比较器虽然能够实现功能,但是应用性 低。
3.书上两种四片16位比较器的扩展输入端直接取3‘b001,不能进一步级联构成更多位比较器,再此做出改进。