数字电路设计与嵌入式开发——组合逻辑电路的Verilog实现
Intro
NOTE
实验课的显示器应该是Lenovo D186,电脑系统 windows xp。目测设备年龄超过 10 年,使用过程中是比较卡顿的;IDE 的编辑体验和笔记本比较类似。
此外拷贝程序建议别用太新的 u 盘,可能跟文件系统有关?没研究过这些。下图中的 U 盘可以正常使用,但昨天被我搞坏了…
![]() | ![]() |
---|
Part 1
实验结果与分析
使用开关 SW0~SW6
完成对 6 个 7 段显示的控制。
定义模块 seven_seg_display
,接收两个输入 hexnum
和 select
,输出两个输出 led
和 show
首先通过case
语句判断select
的值,然后通过 assign 语句更新led
的值;这个 case 语句的作用是,负责控制选择用哪一个 7 段数码管来显示数字
比如希望在select==0
时点亮DISP1 LTD-4708JR
数码管,可以在下面的约束文件中添加NET led<0> LOC=M17;
语句将led[0]
与M17
引脚绑定,即led[0]
对应电路图中的7SD-C1
信号。当遇到3'b000
这个 case 时,led=6'b000001;
,即led[0]
赋值为 1,即7SD-C1
为高电平,即选中第一个数码管 C1 进行显示;

然后通过display
的 8 个 bits 分别负责a,b,c,d,e,f,g,dp
数码管的亮灭,从而更新显示的 hexadecimal number;本实验中 Digilent Anvyl 开发板上的数码管为共阴极数码管。以4'h0: display = 8'b11111100;
为例,表示a,b,c,d,e,f
亮,g,dp
灭;
bin | hex |
---|---|
8'b11111100 | 0 |
8'b01100000 | 1 |
8'b11011010 | 2 |
8'b11110010 | 3 |
8'b01100110 | 4 |
8'b10110110 | 5 |
8'b10111110 | 6 |
8'b11100000 | 7 |
8'b11111110 | 8 |
8'b11100110 | 9 |
8'b11101110 | a |
8'b00111110 | b |
8'b10011100 | c |
8'b01111010 | d |
8'b10011110 | e |
8'b10001110 | f |

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
module seven_seg_display (
input [3:0] hexnum, // 4-bit input, controls displayed data (0 to F)
input [2:0] select, // 3-bit input, selects which 7-segment display to control (000 to 101)
output reg [5:0] led, // 6-bit output, activates one of six 7-segment displays
output reg [7:0] display // 8-bit output, controls the segments of the 7-segment display
);
// Control which 7-segment display is active based on the 'select' input
always @(*) begin
case (select)
3'b000: led = 6'b000001; // Activate 7SD-1
3'b001: led = 6'b000010; // Activate 7SD-2
3'b010: led = 6'b000100; // Activate 7SD-3
3'b011: led = 6'b001000; // Activate 7SD-4
3'b100: led = 6'b010000; // Activate 7SD-5
3'b101: led = 6'b100000; // Activate 7SD-6
default: led = 6'b000000; // Turn off all displays for other values of 'select'
endcase
end
// Determine the pattern to display on the 7-segment display based on 'hexnum'
always @(*) begin
case (hexnum)
4'h0: display = 8'b11111100; // Display 0
4'h1: display = 8'b01100000; // Display 1
4'h2: display = 8'b11011010; // Display 2
4'h3: display = 8'b11110010; // Display 3
4'h4: display = 8'b01100110; // Display 4
4'h5: display = 8'b10110110; // Display 5
4'h6: display = 8'b10111110; // Display 6
4'h7: display = 8'b11100000; // Display 7
4'h8: display = 8'b11111110; // Display 8
4'h9: display = 8'b11100110; // Display 9
4'hA: display = 8'b11101110; // Display A
4'hB: display = 8'b00111110; // Display B
4'hC: display = 8'b10011100; // Display C
4'hD: display = 8'b01111010; // Display D
4'hE: display = 8'b10011110; // Display E
4'hF: display = 8'b10001110; // Display F
default: display = 8'b00000000; // Turn off all segments for invalid hexnum
endcase
end
endmodule
参照该图,补全约束文件,使得数字 0~F 在 正确的 7 段数码管上以正确的形式显示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 下面是ucf文件,为了显示效果,文中用bash代码块进行高亮
NET hexnum<O> LOC=V5;
NET hexnum<1> LOC=U4;
NET hexnum<2> LOC=V3;
NET hexnum<3> LOC=P4;
NET select<O> LOC=R4;
NET select<1> LOC=P6;
NET select<2> LOC=P5
NET led<0> LOC=M17;
NET led<1> LOC=P16;
NET led<2> LOC=P19;
NET led<3> LOC=N16;
NET led<4> LOC=AB21;
NET led<5> LOC=AA20;
NET display<O> LOC=P15;
NET display<1> LOC=Y21
NET display<2> LOC=P20;
NET display<3> LOC=AB19;
NET display<4> LOC=N15;
NET display<5> LOC=Y22;
NET display<6> LOC=AA22;
NET display<7> LOC=AA21;
验证图片
编译后将 bit 文件写入开发板验证即可
Part 2
实验结果与分析
根据控制信号 C 的值,选择一个 2 位输入信号 D0、D1 或 D2,并将该信号输出到 Y。下面是代码的具体解释和实现思路。输出信号通过 LD0 和 LD1 两个发光二极管进行验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module Mux3to1_2bit (
input [1:0] C,
input [1:0] D0,
input [1:0] D1,
input [1:0] D2,
output reg[1:0] Y
);
always@(*)
case (C)
2'b00: Y = D0;
2'b01: Y = D1;
2'b10: Y = D2;
default: Y = 2'b00;
endcase
endmodule
验证图片
Part 3
实验结果与分析
输入端有 3 根信号线,表示从000
到111
8 种不同的二进制组合,输出端有 8 根信号线,每一根线对应输入的一种二进制组合。
编写如下代码,然后在约束文件中将out[0]-outp[7]
分别绑定到 LD0 到 LD7 八个 LED 灯即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
module decoder3to8(
input [2:0] in, // 3-bit input
output reg [7:0] out // 8-bit output
);
always @(*) begin
out = 8'b0000_0000; // 初始化输出
case (in)
3'b000: out = 8'b0000_0001;
3'b001: out = 8'b0000_0010;
3'b010: out = 8'b0000_0100;
3'b011: out = 8'b0000_1000;
3'b100: out = 8'b0001_0000;
3'b101: out = 8'b0010_0000;
3'b110: out = 8'b0100_0000;
3'b111: out = 8'b1000_0000;
default: out = 8'b0000_0000;
endcase
end
endmodule
验证图片
队友的玉手出镜,拨码挡住了,懒得重新拍了(没挡住看得也费力,老师应该也不会细看)
Part 4
实验结果与分析
代码结构与 3-8 译码器类似,将输入输出倒置即可。在约束文件中,out[0]、out[1]、out[2]
绑定到LD0、LD1、LD2
即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module encoder8to3(
input [7:0] in, // 8-bit input
output reg [2:0] out // 3-bit output
);
always @(*) begin
case (in)
8'b0000_0001: out = 3'b000;
8'b0000_0010: out = 3'b001;
8'b0000_0100: out = 3'b010;
8'b0000_1000: out = 3'b011;
8'b0001_0000: out = 3'b100;
8'b0010_0000: out = 3'b101;
8'b0100_0000: out = 3'b110;
8'b1000_0000: out = 3'b111;
default: out = 3'b000;
endcase
end
endmodule
验证图片
Part 5
实验结果与分析
用 Verilog 实现一个 3 位二进制加减法器。X=0 时进行加法计算;X=1 时进行减法计算
代码根据控制信号 X 的值来决定是执行加法还是减法操作
A
和B
是 3 位的无符号操作数(即全为正数)X
是控制信号,当X = 0
时执行加法,当X = 1
时执行减法。Y
是 4 位输出结果,返回运算结果的补码形式Overflow
作为 Flag,用于指示是否在操作中发生溢出。
为方便运算,在计算过程中需要将运算数转为补码;转换的过程如下
A
作为被加数/被减数,一定为正数;只需要在A
前面加一个0
bit 作为符号位即可assign A_comp = {1'b0, A};
B
作为加数/减数,根据控制信号X
来确定其正负,如果是加法(X==0
),加一个0
作为符号位即可;如果是减法(X==1
),那么运算可以视作A+(-B)
,-B
作为负数,求补码需要先按位取反(符号位不需要取反)再加 1assign B_comp = (X == 0) ? {1'b0, B} : {1'b1, ~B} + 1
接下来判断运算结果是否溢出
- 如果是减法,运算结果一定不会溢出;(运算结果一定会在
0到-7
这个区间里) - 如果是加法,运算结果可能溢出;例如
A=011,B=110
得到Y=1101
,两个正数相加得到负数,显然发生了溢出;assign Overflow = (X == 0) ? Y[3] : 0;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module AdderSubtractor(
input [2:0] A, // 3-bit operand A
input [2:0] B, // 3-bit operand B
input X, // Control signal: 0 for addition, 1 for subtraction
output [3:0] Y, // 4-bit result to include overflow
output Overflow // Overflow indicator
);
// 4-bit complement of A and B
wire [3:0] A_comp;
wire [3:0] B_comp;
assign A_comp = {1'b0, A};
assign B_comp = (X == 0) ? {1'b0, B} : {1'b1, ~B} + 1;
assign Y = A_comp + B_comp;
assign Overflow = (X == 0) ? Y[3] : 0;
endmodule
1
2
3
4
5
6
7
8
9
10
11
12
NET A<O> LOC=V5;
NET A<1> LOC=U4;
NET A<2> LOC=V3;
NET B<0> LOC=P4;
NET B<1> LOC=R4;
NET B<2> LOC=P6;
NET X LOC=P5;
NET Y<O> LOC=W3;
NET Y<1> LOC=Y4;
NET Y<2> LOC=Y1;
NET Y<3> LOC=AB4;
NET Overflow LOC=AA4;
验证图片
数字电路设计与嵌入式开发——组合逻辑电路的Verilog实现