文章目录
数字设计实验:译码器与编码器
1.实验目的
本实验旨在设计一个3-8译码器和4-2编码器,并借助vivado软件和实验开发板来进行模拟仿真和实践验证,通过实验对编码和译码原理有初步的理解和认识,同时锻炼vivado软件的使用能力和verilog语言的编写能力.
2.实验内容
-
3-8译码器
实验内容:
1.写出3-8译码器真值表,通过化简写出译码器布尔表达式
2.使用Verilog HDL实现,用vivado仿真并下载到实验板进行验证
输入使用板上的switch拨段开关,输出使用板上的led灯。 -
4-2编码器
实验内容:
1.写出4-2编码器真值表,通过化简写出编码器布尔表达式
2.使用Verilog HDL实现,用vivado仿真并下载到实验板进行验证
输入使用板上的switch拨段开关,输出使用板上的led灯。
3.实验设计思路
3.1 3 - 8译码器分析
3 - 8译码器有3个输入x,y,z,只取0或1;共有8种输出,每个输出代表3个输入变量的一个最小项.
3 - 8译码器的真值表如下:
x | y | z | D0 | D1 | D2 | D3 | D4 | D5 | D6 | D7 |
---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
0 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
不难得到:
D
0
=
x
′
y
′
z
′
D
1
=
x
′
y
′
z
D
2
=
x
′
y
z
′
D
3
=
x
′
y
z
D
4
=
x
y
′
z
′
D
5
=
x
y
′
z
D
6
=
x
y
z
′
D
7
=
x
y
z
D_0 = x'y'z'~~~D_1 = x'y'z~~~D_2 = x'yz'~~~D_3 = x'yz\\D_4 = xy'z'~~~D_5 = xy'z~~~D_6 = xyz'~~~D_7 = xyz
D0=x′y′z′ D1=x′y′z D2=x′yz′ D3=x′yzD4=xy′z′ D5=xy′z D6=xyz′ D7=xyz
因此只需要根据Di的布尔表达式编写verilog代码即可.
3.2 4 - 2编码器分析
3.2.1 初始设计分析
4 - 2编码器有4个输入变量,每个输入代表一个四进制数,并初始假设在任何时候只有一个输入的值等于1;共有2个输出,每个输出对应于输入的二进制数.例如输入0,0,1,0,输出为00;输入1,0,0,0,输出为11.
4 - 2编码器的真值表如下:
D0 | D1 | D2 | D3 | x | y |
---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 0 | 0 | 1 |
0 | 0 | 1 | 0 | 1 | 0 |
0 | 0 | 0 | 1 | 1 | 1 |
不难得到:
x
=
D
2
+
D
3
y
=
D
1
+
D
3
x=D_2+D_3\\y=D_1+D_3
x=D2+D3y=D1+D3
因此只需要根据x,y的布尔表达式编写verilog代码即可.
3.2.2 改进设计分析
在3.2.1中分析设计的编码器有两个明显的缺点:
1.由于假设的是任何时候只有一个输入是有效的,而当多个输入变量为1时,就会产生一个没有定义的输入组合,会导致与正确输入相同的输出结果;
2.当所有输入变量都为0,也即所有输入都无效时,产生的输出是00,这与D0为1时产生的输出相同.
改进方法:优先编码器
1.新增第三个输出:有效位指示符V,当四个输入均为0即均无效时,V设置为0,当有一个及以上输入为1时,V设置为1;
2.引入优先级,当有多个输入同时有效时,最高优先级的输入被视为优先,在此编码器中,定义下标数字越大的输入优先级越高.
4 - 2优先编码器真值表如下:
D0 | D1 | D2 | D3 | x | y | V |
---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | X | X | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 1 |
X | 1 | 0 | 0 | 0 | 1 | 1 |
X | X | 1 | 0 | 1 | 0 | 1 |
X | X | X | 1 | 1 | 1 | 1 |
容易得到:
x
=
D
2
+
D
3
y
=
D
3
+
D
1
D
2
′
V
=
D
0
+
D
1
+
D
2
+
D
3
x=D_2+D_3\\y=D_3+D_1D_2'\\V=D_0+D_1+D_2+D_3
x=D2+D3y=D3+D1D2′V=D0+D1+D2+D3
因此只需要根据x,y,V的布尔表达式编写verilog代码即可.
4.实验过程与实验结果
4.1 3-8译码器的设计与实现
- 设计:
1.根据3.1中的分析,可以编写decoder模块:
module decoder(x, y, z, D);
input x, y, z;
output [7:0] D;
assign D[0] = (~x)&(~y)&(~z);
assign D[1] = (~x)&(~y)&z;
assign D[2] = (~x)&y&(~z);
assign D[3] = (~x)&y&z;
assign D[4] = x&(~y)&(~z);
assign D[5] = x&(~y)&z;
assign D[6] = x&y&(~z);
assign D[7] = x&y&z;
endmodule
2.为了能在软件上虚拟仿真,写一个decoder模块的测试平台test_decoder:
//test module
module test_decoder;
wire [7:0] out;
reg x, y, z;
decoder M1(x, y, z, out);
integer i;
initial begin
$display("%4s | %1s %1s %1s | %8s", "Time", "x", "y", "z", "D");
$display("-----------------------------");
// 遍历所有 8 种输入组合
for (i = 0; i < 8; i = i + 1) begin
{x, y, z} = i;
#1;
$display("%4t | %1b %1b %1b | %08b", $time, x, y, z, out);
end
$finish;
end
endmodule
作用是按照0~7的二进制编码顺序每隔1ps改变一次输入变量x,y,z,能在控制台和仿真图像上显示仿真结果.
- 仿真结果:
1.根据所设计的程序,在vivado仿真后生成的逻辑电路图如下,符合之前的设计思路:
2.控制台输出结果如下,符合译码器的功能:
3.仿真结果时序表如下,直观呈现了输入和输出随时间的变化:
- 导入实验板验证:
为了能正确接入到实验板上,需添加约束文件lab1_1_decoder.xdc
如下,目的是将程序里的变量与实验板上的组件正确配对:
## Switches
set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { x }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { y }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { z }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
## LEDs
set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { D[0] }]; #IO_L18P_T2_A24_15 Sch=led[0]
set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { D[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1]
set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { D[2] }]; #IO_L17N_T2_A25_15 Sch=led[2]
set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { D[3] }]; #IO_L8P_T1_D11_14 Sch=led[3]
set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { D[4] }]; #IO_L7P_T1_D09_14 Sch=led[4]
set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { D[5] }]; #IO_L18N_T2_A11_D27_14 Sch=led[5]
set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { D[6] }]; #IO_L17P_T2_A14_D30_14 Sch=led[6]
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { D[7] }]; #IO_L18P_T2_A12_D28_14 Sch=led[7]
将文件下载到实验板上进行验证,得到的实拍图片如下:
其中,开关上拨代表对应的输入变量为1;LED灯亮代表对应的输出变量为1.
上述实验结果表明,当根据输入变量为八进制数i(i = 0,1,2,…,7)按二进制的编码来上拨开关时,i对应的LED灯亮,其他灯都不亮.这也能更直观地验证译码器设计的正确性.
4.2 4 - 2编码器的设计与实现
4.2.1 初始设计
- 设计:
1.根据3.2.1中的分析,可以编写encoder模块:
module encoder(D, x, y);
input [3:0] D;
output x, y;
assign x = D[2] | D[3];
assign y = D[1] | D[3];
endmodule
2.为了能在软件上虚拟仿真,写一个encoder模块的测试平台test_encoder:
//test module
module test_encoder;
wire x, y;
reg [3:0] D;
encoder M1(D, x, y);
initial begin
$display("Time\tD\t x y");
// 输入0001
D = 4'b0001;
#1;
$display("%0d\t%b\t %b %b", $time, D, x, y);
// 输入0010
D = 4'b0010;
#1;
$display("%0d\t%b\t %b %b", $time, D, x, y);
// 输入0100
D = 4'b0100;
#1;
$display("%0d\t%b\t %b %b", $time, D, x, y);
// 输入1000
D = 4'b1000;
#1;
$display("%0d\t%b\t %b %b", $time, D, x, y);
$finish;
end
endmodule
作用使是按照第0,1,2,3位为1的顺序每隔1ps改变一次输入向量D,能通过运行后控制台的输出和仿真时序表来观察输出变量x,y的值的变化.
- 仿真结果:
1.根据所设计的程序,在vivado仿真后生成的逻辑电路图如下,符合之前的设计思路:
2.控制台输出结果如下,符合编码器的功能:
3.仿真结果时序表如下,直观呈现了输入和输出随时间的变化:
- 导入实验板验证:
为了能正确接入到实验板上,需添加约束文件lab1_2_encoder.xdc
如下,目的是将程序里的变量与实验板上的组件正确配对:
## Switches
set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { D[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { D[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { D[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { D[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3]
## LEDs
set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { x }]; #IO_L18P_T2_A24_15 Sch=led[0]
set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { y }]; #IO_L24P_T3_RS1_15 Sch=led[1]
将文件下载到实验板上进行验证,得到的实拍图片如下:
其中,开关上拨代表对应的输入变量为1;LED灯亮代表对应的输出变量为1.
上述实验结果表明,当输入中仅有第i(i = 0,1,2,3)个为1即对应的开关上拨时,LED灯组合xy代表了i的二进制编码(亮为1,不亮为0).这也能更直观地验证编码器设计的正确性.
4.2.2 改进设计
- 设计:
1.根据3.2.2中的分析,可以编写encoder_plus模块:
module encoder_plus(D, x, y, V);
input [3:0] D;
output x, y, V;
assign x = D[2] | D[3];
assign y = (D[1] & (~D[2])) | D[3];
assign V = D[0] | D[1] | D[2] | D[3];
endmodule
2.为了能在软件上虚拟仿真,写一个encoder_plus模块的测试平台test_encoder_plus:
//test module
module test_encoder_plus;
wire x, y, V;
reg [3:0] D;
encoder_plus M1(D, x, y, V);
integer i;
initial begin
$display("Time\tD\t x y V");
// 遍历所有 16 种输入组合
for (i = 0; i < 16; i = i + 1) begin
D = i;
#1;
$display("%0d\t%b\t %b %b %b", $time, D, x, y, V);
end
$finish;
end
endmodule
- 仿真结果:
1.根据所设计的程序,在vivado仿真后生成的逻辑电路图如下,符合之前的设计思路:
2.控制台输出结果如下,符合编码器的功能:
3.仿真结果时序表如下,直观呈现了输入和输出随时间的变化:
- 导入实验板验证:
为了能正确接入到实验板上,需添加约束文件lab1_2_encoder_plus.xdc
如下,目的是将程序里的变量与实验板上的组件正确配对:
## Switches
set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { D[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { D[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 } [get_ports { D[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 } [get_ports { D[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3]
## LEDs
set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { x }]; #IO_L18P_T2_A24_15 Sch=led[0]
set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { y }]; #IO_L24P_T3_RS1_15 Sch=led[1]
set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { V }]; #IO_L17N_T2_A25_15 Sch=led[2]
将文件下载到实验板上进行验证,得到的实拍图片如下:
其中,开关上拨代表对应的输入变量为1;LED灯亮代表对应的输出变量为1.
前四张图为有效且规范的输入,后四张为对无效输入和不规范输入的处理结果(不规范输入仅3举例).
上述实验结果表明,当仅当有开关上拨时有效位指示灯才会亮;输入规范时,功能与上述初始编码器相当;而输入不规范时,优先编码器对输入进行优先处理.这也能更直观地验证优先编码器设计的正确性.
5.实验总结
5.1 实验中遇到的问题与解决方法
1.在没有实验板的情况下要想初步确定实验设计的正确性,可以在verilog文件中编写自己原先设计的模块的测试平台test_module
,通过合理设置时延来改变输入进而改变输出.这样通过vivado软件自带的simulation功能便可观察仿真时序图表.同时还可借助display函数在控制台可视化呈现输出随输入的变化.
2.本实验一个主要的问题就是在编码器设计部分,初始版本有诸多欠缺,如输入的有效性判断,不规范输入等问题,然而可以通过设计一个优先编码器,并添加一个有效指示符的输出变量,便可巧妙地解决这一问题.
5.2 实验体会
本实验通过分析译码器和编码器的工作原理,使用vivado软件以verilog语言设计了一个3-8译码器和4-2编码器,同时将初始的4-2编码器改进设计成优先编码器,最后通过vivado软件仿真和实验板硬件操作,验证了译码器和编码器设计的正确性.通过本实验,加深了对译码,编码工作原理的理解,同时增强了vivado软件结合实验板的操作能力.